system.module 102 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
 
Dries committed
4 5 6 7 8
/**
 * @file
 * Configuration system that lets administrators modify the workings of the site.
 */

Steven Wittens's avatar
Steven Wittens committed
9
define('VERSION', '6.0-dev');
10

11 12 13 14 15
define('DRUPAL_MINIMUM_PHP',    '4.3.3');
define('DRUPAL_MINIMUM_MYSQL',  '4.1.0'); // If using MySQL
define('DRUPAL_MINIMUM_PGSQL',  '7.4');   // If using PostgreSQL
define('DRUPAL_MINIMUM_APACHE', '1.3');   // If using Apache

Dries's avatar
 
Dries committed
16 17 18 19
/**
 * Implementation of hook_help().
 */
function system_help($section) {
20 21
  global $base_url;

22
  switch ($section) {
23
    case 'admin/help#system':
24
      $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 website 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 website performance. The settings module provides control over preferences, behaviours including visual and operational settings.') .'</p>';
25
      $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>';
26
      $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>';
27
      $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>';
28
      return $output;
29
    case 'admin':
30
      return '<p>'. t('Welcome to the administration section. Here you may control how your site functions.') .'</p>';
31
    case 'admin/by-module':
32
      return '<p>'. t('This page shows you all available administration tasks for each module.') .'</p>';
33
    case 'admin/build/themes':
34
      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>';
35
    case 'admin/build/themes/settings':
36
      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>';
37 38
    case 'admin/build/themes/settings/'. arg(4):
      $reference = explode('.', arg(4), 2);
39
      $theme = array_pop($reference);
40
      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>';
41
    case 'admin/build/modules':
42
      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>
43
<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')));
44
    case 'admin/build/modules/uninstall':
45
      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>';
46
    case 'admin/logs/status':
47
      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>';
48
  }
Dries's avatar
 
Dries committed
49 50
}

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
function system_theme() {
  return array_merge(drupal_common_themes(), array(
    'system_theme_select_form' => array(
      'arguments' => array('form' => NULL),
    ),
    'system_themes_form' => array(
      'arguments' => array('form' => NULL),
    ),
    'system_modules' => array(
      'arguments' => array('form' => NULL),
    ),
    'system_modules_uninstall' => array(
      'arguments' => array('form' => NULL),
    ),
    'status_report' => array(
      'arguments' => array('requirements' => NULL),
    ),
    'admin_page' => array(
      'arguments' => array('blocks' => NULL),
    ),
    'admin_block' => array(
      'arguments' => array('block' => NULL),
    ),
    'admin_block_content' => array(
      'arguments' => array('content' => NULL),
    ),
    'system_admin_by_module' => array(
      'arguments' => array('menu_items' => NULL),
    ),
  ));
}
Dries's avatar
 
Dries committed
82 83 84
/**
 * Implementation of hook_perm().
 */
Dries's avatar
 
Dries committed
85
function system_perm() {
86
  return array('administer site configuration', 'access administration pages', 'select different theme');
Dries's avatar
 
Dries committed
87 88
}

89 90 91 92 93
/**
 * Implementation of hook_elements().
 */
function system_elements() {
  // Top level form
94
  $type['form'] = array('#method' => 'post', '#action' => request_uri());
95 96

  // Inputs
97
  $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1);
98 99
  $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE);
  $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE);
100
  $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
101
  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128);
102
  $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
103
  $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE);
104
  $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios'));
105
  $type['radio'] = array('#input' => TRUE, '#default_value' => NULL);
106
  $type['checkboxes'] = array('#input' => TRUE, '#process' => array('expand_checkboxes'), '#tree' => TRUE);
107
  $type['select'] = array('#input' => TRUE, '#size' => 0, '#multiple' => FALSE);
108 109
  $type['weight'] = array('#input' => TRUE, '#delta' => 10, '#default_value' => 0, '#process' => array('process_weight'));
  $type['date'] = array('#input' => TRUE, '#process' => array('expand_date' => array()), '#element_validate' => array('date_validate'));
110
  $type['file'] = array('#input' => TRUE, '#size' => 60);
111 112

  // Form structure
113
  $type['item'] = array('#value' => '');
114 115 116
  $type['hidden'] = array('#input' => TRUE);
  $type['value'] = array('#input' => TRUE);
  $type['markup'] = array('#prefix' => '', '#suffix' => '');
117
  $type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE, '#value' => NULL);
Dries's avatar
Dries committed
118
  $type['token'] = array('#input' => TRUE);
119 120 121
  return $type;
}

Dries's avatar
 
Dries committed
122
/**
Dries's avatar
 
Dries committed
123
 * Implementation of hook_menu().
Dries's avatar
 
Dries committed
124
 */
125 126
function system_menu() {
  $items['system/files'] = array(
127
    'title' => 'File download',
128 129 130 131 132
    'page callback' => 'file_download',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['admin'] = array(
133
    'title' => 'Administer',
134 135 136
    'access arguments' => array('access administration pages'),
    'page callback' => 'system_main_admin_page',
    'weight' => 9,
137
    'file' => 'system.admin.inc',
138 139
  );
  $items['admin/compact'] = array(
140
    'title' => 'Compact mode',
141 142 143 144
    'page callback' => 'system_admin_compact_page',
    'type' => MENU_CALLBACK,
  );
  $items['admin/by-task'] = array(
145
    'title' => 'By task',
146 147 148 149
    'page callback' => 'system_main_admin_page',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/by-module'] = array(
150
    'title' => 'By module',
151 152 153 154 155 156
    'page callback' => 'system_admin_by_module',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  // menu items that are basically just menu blocks
  $items['admin/settings'] = array(
157 158
    'title' => 'Site configuration',
    'description' => 'Adjust basic site configuration options.',
159 160 161 162 163 164
    'position' => 'right',
    'weight' => -5,
    'page callback' => 'system_settings_overview',
    'access arguments' => array('administer site configuration'),
  );
  $items['admin/build'] = array(
165 166
    'title' => 'Site building',
    'description' => 'Control how your site looks and feels.',
167 168 169 170
    'position' => 'right',
    'weight' => -10,
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array('administer site configuration'),
171
    'file' => 'system.admin.inc',
172 173
  );
  $items['admin/settings/admin'] = array(
174 175
    'title' => 'Administration theme',
    'description' => 'Settings for how your administrative pages should look.',
176 177 178 179 180 181 182
    'position' => 'left',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_admin_theme_settings'),
    'block callback' => 'system_admin_theme_settings',
  );
  // Themes:
  $items['admin/build/themes'] = array(
183 184
    'title' => 'Themes',
    'description' => 'Change which theme your site uses or allows users to set.',
185
    'page callback' => 'drupal_get_form',
186
    'page arguments' => array('system_themes_form'),
187 188
  );
  $items['admin/build/themes/select'] = array(
189 190
    'title' => 'List',
    'description' => 'Select the default theme.',
191 192 193 194
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -1,
  );
  $items['admin/build/themes/settings'] = array(
195
    'title' => 'Configure',
196 197 198 199 200
    'page arguments' => array('system_theme_settings'),
    'type' => MENU_LOCAL_TASK,
  );
  // Theme configuration subtabs
  $items['admin/build/themes/settings/global'] = array(
201
    'title' => 'Global settings',
202 203 204
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -1,
  );
Dries's avatar
 
Dries committed
205

206 207 208
  foreach (list_themes() as $theme) {
    if ($theme->status) {
      $items['admin/build/themes/settings/'. $theme->name] = array(
209
        'title' => $theme->info['name'],
210 211 212
        'page arguments' => array('system_theme_settings', $theme->name),
        'type' => MENU_LOCAL_TASK,
      );
Dries's avatar
 
Dries committed
213
    }
Dries's avatar
 
Dries committed
214
  }
drumm's avatar
drumm committed
215

216 217
  // Modules:
  $items['admin/build/modules'] = array(
218 219
    'title' => 'Modules',
    'description' => 'Enable or disable add-on modules for your site.',
220 221 222 223
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_modules'),
  );
  $items['admin/build/modules/list'] = array(
224
    'title' => 'List',
225 226 227
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['admin/build/modules/list/confirm'] = array(
228
    'title' => 'List',
229 230 231
    'type' => MENU_CALLBACK,
  );
  $items['admin/build/modules/uninstall'] = array(
232
    'title' => 'Uninstall',
233 234 235 236
    'page arguments' => array('system_modules_uninstall'),
    'type' => MENU_LOCAL_TASK,
  );
  $items['admin/build/modules/uninstall/confirm'] = array(
237
    'title' => 'Uninstall',
238 239
    'type' => MENU_CALLBACK,
  );
Dries's avatar
 
Dries committed
240

241 242
  // Settings:
  $items['admin/settings/site-information'] = array(
243 244
    'title' => 'Site information',
    'description' => 'Change basic site information, such as the site name, slogan, e-mail address, mission, front page and more.',
245 246 247 248
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_site_information_settings'),
  );
  $items['admin/settings/error-reporting'] = array(
249 250
    'title' => 'Error reporting',
    'description' => 'Control how Drupal deals with errors including 403/404 errors as well as PHP error reporting.',
251 252 253
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_error_reporting_settings'),
  );
254
  $items['admin/settings/logging'] = array(
255 256
    'title' => 'Logging and alerts',
    'description' => "Settings for logging and alerts modules. Various modules can route Drupal's system events to different destination, such as syslog, database, email, ...etc.",
257 258
    'page callback' => 'system_logging_overview',
  );
259
  $items['admin/settings/performance'] = array(
260 261
    'title' => 'Performance',
    'description' => 'Enable or disable page caching for anonymous users, and enable or disable CSS preprocessor.',
262 263 264 265
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_performance_settings'),
  );
  $items['admin/settings/file-system'] = array(
266 267
    'title' => 'File system',
    'description' => 'Tell Drupal where to store uploaded files and how they are accessed.',
268 269 270 271
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_file_system_settings'),
  );
  $items['admin/settings/image-toolkit'] = array(
272 273
    'title' => 'Image toolkit',
    'description' => 'Choose which image toolkit to use if you have installed optional toolkits.',
274 275 276 277
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_image_toolkit_settings'),
  );
  $items['admin/content/rss-publishing'] = array(
278 279
    'title' => 'RSS publishing',
    'description' => 'Configure the number of items per feed and whether feeds should be titles/teasers/full-text.',
280 281 282 283
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_rss_feeds_settings'),
  );
  $items['admin/settings/date-time'] = array(
284 285
    'title' => 'Date and time',
    'description' => "Settings for how Drupal displays date and time, as well as the system's default timezone.",
286 287 288
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_date_time_settings'),
  );
289 290 291 292 293
  $items['admin/settings/date-time/lookup'] = array(
    'title' => t('Date and time lookup'),
    'type' => MENU_CALLBACK,
    'page callback' => 'system_date_time_lookup',
  );
294
  $items['admin/settings/site-maintenance'] = array(
295 296
    'title' => 'Site maintenance',
    'description' => 'Take the site off-line for maintenance or bring it back online.',
297 298 299 300
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_site_maintenance_settings'),
  );
  $items['admin/settings/clean-urls'] = array(
301 302
    'title' => 'Clean URLs',
    'description' => 'Enable or disable clean URLs for your site.',
303 304 305 306 307 308
    'page callback' => 'drupal_get_form',
    'page arguments' => array('system_clean_url_settings'),
  );

  // Logs:
  $items['admin/logs'] = array(
309 310
    'title' => 'Logs',
    'description' => 'View system logs and other status information.',
311 312 313
    'page callback' => 'system_admin_menu_block_page',
    'weight' => 5,
    'position' => 'left',
314
    'file' => 'system.admin.inc',
315 316
  );
  $items['admin/logs/status'] = array(
317 318
    'title' => 'Status report',
    'description' => "Get a status report about your site's operation and any detected problems.",
319 320 321 322 323
    'page callback' => 'system_status',
    'weight' => 10,
    'access arguments' => array('administer site configuration'),
  );
  $items['admin/logs/status/run-cron'] = array(
324
    'title' => 'Run cron',
325 326 327 328
    'page callback' => 'system_run_cron',
    'type' => MENU_CALLBACK,
  );
  $items['admin/logs/status/php'] = array(
329
    'title' => 'PHP',
330 331 332 333
    'page callback' => 'system_php',
    'type' => MENU_CALLBACK,
  );
  $items['admin/logs/status/sql'] = array(
334
    'title' => 'SQL',
335 336 337
    'page callback' => 'system_sql',
    'type' => MENU_CALLBACK,
  );
338 339 340 341 342 343
  // Default page for batch operations
  $items['batch'] = array(
    'page callback' => 'system_batch_page',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
Dries's avatar
 
Dries committed
344
  return $items;
Dries's avatar
 
Dries committed
345 346
}

347 348 349 350 351 352 353 354 355 356 357 358 359
function system_init() {
  // Use the administrative theme if the user is looking at a page in the admin/* path.
  if (arg(0) == 'admin') {
    global $custom_theme;
    $custom_theme = variable_get('admin_theme', '0');
    drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
  }

  // Add the CSS for this module.
  drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module');
  drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module');
}

Dries's avatar
 
Dries committed
360 361 362 363 364
/**
 * Implementation of hook_user().
 *
 * Allows users to individually set their theme and time zone.
 */
365
function system_user($type, $edit, &$user, $category = NULL) {
Dries's avatar
Dries committed
366
  if ($type == 'form' && $category == 'account') {
367
    $form['theme_select'] = system_theme_select_form(t('Selecting a different theme will change the look and feel of the site.'), isset($edit['theme']) ? $edit['theme'] : NULL, 2);
Dries's avatar
Dries committed
368

369
    if (variable_get('configurable_timezones', 1)) {
Steven Wittens's avatar
Steven Wittens committed
370
      $zones = _system_zonelist();
371
      $form['timezone'] = array(
372
        '#type' => 'fieldset',
373 374 375 376
        '#title' => t('Locale settings'),
        '#weight' => 6,
        '#collapsible' => TRUE,
      );
377
      $form['timezone']['timezone'] = array(
378 379 380 381 382
        '#type' => 'select',
        '#title' => t('Time zone'),
        '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone', 0),
        '#options' => $zones,
        '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'),
383
      );
Dries's avatar
 
Dries committed
384
    }
Dries's avatar
Dries committed
385

386
    return $form;
Dries's avatar
 
Dries committed
387
  }
Dries's avatar
 
Dries committed
388 389
}

390 391 392
/**
 * Provide a single block on the administration overview page.
 */
393
function system_admin_menu_block($item) {
394
  $content = array();
395 396 397 398 399
  if (!isset($item->mlid)) {
    $item->mlid = db_result(db_query("SELECT mlid FROM {menu_links} ml WHERE ml.router_path = '%s' AND menu_name = 'navigation'", $item->path));
  }
  $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path
                      WHERE ml.plid = '%s' AND ml.menu_name = 'navigation' ORDER BY m.weight, m.title", $item->mlid);
400
  while ($item = db_fetch_object($result)) {
401
    _menu_link_translate($item);
402 403
    if (!$item->access) {
      continue;
404
    }
405
    $content[] = (array)$item;
406 407 408 409 410 411 412 413 414
  }
  return $content;
}

function system_admin_compact_page($mode = 'off') {
  global $user;
  user_save($user, array('admin_compact_mode' => ($mode == 'on')));
  drupal_goto('admin');
}
415

416
/**
417
 * This function allows selection of the theme to show in administration sections.
418
 */
419
function system_admin_theme_settings() {
420 421 422 423
  $themes = system_theme_data();
  ksort($themes);
  $options[0] = t('System default');
  foreach ($themes as $theme) {
424
    $options[$theme->name] = $theme->info['name'];
425 426 427 428 429 430
  }

  $form['admin_theme'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#title' => t('Administration theme'),
431
    '#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.'),
432
    '#default_value' => variable_get('admin_theme', '0'),
433 434
  );

435
  $form['#submit'][] = 'system_admin_theme_submit';
436
  return system_settings_form($form);
437 438 439
}


440
function system_admin_theme_submit($form_values, $form, &$form_state) {
441
  // If we're changing themes, make sure the theme has its blocks initialized.
442
  if ($form_values['admin_theme'] != variable_get('admin_theme', '0')) {
443 444 445 446 447 448 449
    $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_values['admin_theme']);
    if (!db_num_rows($result)) {
      system_initialize_theme_blocks($form_values['admin_theme']);
    }
  }
}

450 451 452 453 454 455 456 457 458 459 460 461 462 463
/*
 * Returns a fieldset containing the theme select form.
 *
 * @param $description
 *    description of the fieldset
 * @param $default_value
 *    default value of theme radios
 * @param $weight
 *    weight of the fieldset
 * @return
 *    a form array
 */
function system_theme_select_form($description = '', $default_value = '', $weight = 0) {
  if (user_access('select different theme')) {
464
    $enabled = array();
465 466 467
    $themes = list_themes();

    foreach ($themes as $theme) {
468 469 470 471 472 473 474 475 476
      if ($theme->status) {
        $enabled[] = $theme;
      }
    }

    if (count($enabled) > 1) {
      ksort($enabled);

      $form['themes'] = array(
Dries's avatar
Dries committed
477 478 479 480
        '#type' => 'fieldset',
        '#title' => t('Theme configuration'),
        '#description' => $description,
        '#collapsible' => TRUE,
481 482 483 484 485
        '#theme' => 'system_theme_select_form'
      );

      foreach ($enabled as $info) {
        // For the default theme, revert to an empty string so the user's theme updates when the site theme is changed.
486
        $info->key = $info->name == variable_get('theme_default', 'garland') ? '' : $info->name;
487

488 489 490 491 492 493 494 495 496 497 498
        $screenshot = NULL;
        $theme_key = $info->name;
        while ($theme_key) {
          if (file_exists($themes[$theme_key]->info['screenshot'])) {
            $screenshot = $themes[$theme_key]->info['screenshot'];
            break;
          }
          $theme_key = isset($themes[$theme_key]->info['base theme']) ? $themes[$theme_key]->info['base theme'] : NULL;
        }

        $screenshot = $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
499

500
        $form['themes'][$info->key]['screenshot'] = array('#value' => $screenshot);
501
        $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>' : ''));
502 503 504 505 506 507 508 509 510 511 512
        $options[$info->key] = '';
      }

      $form['themes']['theme'] = array('#type' => 'radios', '#options' => $options, '#default_value' => $default_value ? $default_value : '');
      $form['#weight'] = $weight;
      return $form;
    }
  }
}

function theme_system_theme_select_form($form) {
513 514
  foreach (element_children($form) as $key) {
    $row = array();
515
    if (isset($form[$key]['description']) && is_array($form[$key]['description'])) {
516 517 518
      $row[] = drupal_render($form[$key]['screenshot']);
      $row[] = drupal_render($form[$key]['description']);
      $row[] = drupal_render($form['theme'][$key]);
519 520 521 522
    }
    $rows[] = $row;
  }

523
  $header = array(t('Screenshot'), t('Name'), t('Selected'));
524 525 526 527
  $output = theme('table', $header, $rows);
  return $output;
}

Steven Wittens's avatar
Steven Wittens committed
528 529 530 531 532 533
function _system_zonelist() {
  $timestamp = time();
  $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);
  $zones = array();
  foreach ($zonelist as $offset) {
    $zone = $offset * 3600;
Dries's avatar
Dries committed
534
    $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') .' O', $zone);
Steven Wittens's avatar
Steven Wittens committed
535 536 537 538
  }
  return $zones;
}

Dries's avatar
Dries committed
539 540 541 542
function system_site_information_settings() {
  $form['site_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
543
    '#default_value' => variable_get('site_name', 'Drupal'),
544
    '#description' => t('The name of this website.'),
Dries's avatar
Dries committed
545
    '#required' => TRUE
546
  );
Dries's avatar
Dries committed
547 548 549 550
  $form['site_mail'] = array(
    '#type' => 'textfield',
    '#title' => t('E-mail address'),
    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
551 552
    '#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.'),
    '#required' => TRUE,
553
  );
Dries's avatar
Dries committed
554 555 556 557
  $form['site_slogan'] = array(
    '#type' => 'textfield',
    '#title' => t('Slogan'),
    '#default_value' => variable_get('site_slogan', ''),
558
    '#description' => t('The slogan of this website. Some themes display a slogan when available.')
559 560
  );

Dries's avatar
Dries committed
561 562 563 564
  $form['site_mission'] = array(
    '#type' => 'textarea',
    '#title' => t('Mission'),
    '#default_value' => variable_get('site_mission', ''),
565
    '#description' => t('Your site\'s mission statement or focus.')
566
  );
Dries's avatar
Dries committed
567 568 569 570
  $form['site_footer'] = array(
    '#type' => 'textarea',
    '#title' => t('Footer message'),
    '#default_value' => variable_get('site_footer', ''),
571
    '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
572
  );
Dries's avatar
Dries committed
573 574 575
  $form['anonymous'] = array(
    '#type' => 'textfield',
    '#title' => t('Anonymous user'),
576
    '#default_value' => variable_get('anonymous', t('Anonymous')),
577
    '#description' => t('The name used to indicate anonymous users.')
578
  );
Dries's avatar
Dries committed
579 580 581 582
  $form['site_frontpage'] = array(
    '#type' => 'textfield',
    '#title' => t('Default front page'),
    '#default_value' => variable_get('site_frontpage', 'node'),
583 584
    '#size' => 40,
    '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
585
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
586
  );
587

588
  return system_settings_form($form);
Dries's avatar
Dries committed
589 590 591 592
}

function system_clean_url_settings() {
  $form['clean_url'] = array(
593 594 595 596
    '#type' => 'radios',
    '#title' => t('Clean URLs'),
    '#default_value' => variable_get('clean_url', 0),
    '#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 601
  if (!variable_get('clean_url', 0)) {
    if (strpos(request_uri(), '?q=') !== FALSE) {
602 603 604 605 606 607 608 609 610 611 612 613
      drupal_add_js(array('cleanURL' => array('success' => t('Your server has been successfully tested to support this feature.'), 'failure' => t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => t('Testing clean URLs...'))), 'setting');
      drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
      drupal_add_js('
// Global Killswitch
if (Drupal.jsEnabled) {
  $(document).ready(function() {
    Drupal.cleanURLsSettingsCheck();
  });
}', 'inline');

      $form['clean_url']['#description'] .= ' <span>'. 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.', array('@handbook' => 'http://drupal.org/node/15365')) .'</span>';

614
      $form['clean_url']['#disabled'] = TRUE;
615 616
      $form['clean_url']['#prefix'] = '<div id="clean-url">';
      $form['clean_url']['#suffix'] = '<p>'. t('<a href="@clean_url">Run the clean url test</a>.', array('@clean_url' => base_path() .'admin/settings/clean-urls')) .'</p></div>';
617 618
    }
    else {
619
      $form['clean_url']['#description'] .= ' '. t('Your server has been successfully tested to support this feature.');
620 621
    }
  }
Dries's avatar
 
Dries committed
622

623
  return system_settings_form($form);
Dries's avatar
Dries committed
624 625 626
}

function system_error_reporting_settings() {
drumm's avatar
drumm committed
627 628

  $form['site_403'] = array(
Dries's avatar
Dries committed
629
    '#type' => 'textfield',
drumm's avatar
drumm committed
630
    '#title' => t('Default 403 (access denied) page'),
Dries's avatar
Dries committed
631
    '#default_value' => variable_get('site_403', ''),
632 633
    '#size' => 40,
    '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
634
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
635
  );
drumm's avatar
drumm committed
636 637

  $form['site_404'] = array(
Dries's avatar
Dries committed
638
    '#type' => 'textfield',
drumm's avatar
drumm committed
639
    '#title' => t('Default 404 (not found) page'),
Dries's avatar
Dries committed
640
    '#default_value' =>  variable_get('site_404', ''),
641 642
    '#size' => 40,
    '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
643
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
644
  );
drumm's avatar
drumm committed
645 646

  $form['error_level'] = array(
647 648
    '#type' => 'select', '#title' => t('Error reporting'), '#default_value' => variable_get('error_level', 1),
    '#options' => array(t('Write errors to the log'), t('Write errors to the log and to the screen')),
drumm's avatar
drumm committed
649
    '#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.')
650
  );
drumm's avatar
drumm committed
651

652
  return system_settings_form($form);
Dries's avatar
Dries committed
653
}
Dries's avatar
 
Dries committed
654

655
function system_performance_settings() {
656

657 658 659 660 661 662
  $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>';

  $problem_modules = array_unique(array_merge(module_implements('init'), module_implements('exit')));
  sort($problem_modules);

  if (count($problem_modules) > 0) {
663
    $description .= '<p>'. t('<strong class="error">The following enabled modules are incompatible with aggressive mode caching and will not function properly: %modules</strong>', array('%modules' => implode(', ', $problem_modules))) .'.</p>';
664 665
  }
  else {
666
    $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>';
667
  }
668 669 670 671 672
  $form['page_cache'] = array(
    '#type' => 'fieldset',
    '#title' => t('Page cache'),
    '#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.'),
  );
673

674
  $form['page_cache']['cache'] = array(
Dries's avatar
Dries committed
675
    '#type' => 'radios',
676
    '#title' => t('Caching mode'),
Dries's avatar
Dries committed
677
    '#default_value' => variable_get('cache', CACHE_DISABLED),
678 679
    '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
    '#description' => $description
680 681
  );

682 683
  $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
  $period[0] = t('none');
684
  $form['page_cache']['cache_lifetime'] = array(
Dries's avatar
Dries committed
685 686 687 688
    '#type' => 'select',
    '#title' => t('Minimum cache lifetime'),
    '#default_value' => variable_get('cache_lifetime', 0),
    '#options' => $period,
689
    '#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.')
690
  );
691

692 693 694 695 696
  $form['bandwidth_optimizations'] = array(
    '#type' => 'fieldset',
    '#title' => t('Bandwidth optimizations'),
    '#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.')
  );
697

698
  $directory = file_directory_path();
699
  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
700 701 702 703 704 705 706 707 708
  $form['bandwidth_optimizations']['preprocess_css'] = array(
    '#type' => 'radios',
    '#title' => t('Aggregate and compress CSS files'),
    '#default_value' => variable_get('preprocess_css', FALSE) && $is_writable,
    '#disabled' => !$is_writable,
    '#options' => array(t('Disabled'), t('Enabled')),
    '#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."),
  );

709 710 711 712 713 714 715 716 717 718 719 720 721 722
  $form['reverse_proxy'] = array(
    '#type' => 'fieldset',
    '#title' => t('Reverse proxy'),
    '#description' => t('Proper extraction of client IP addresses when Drupal is behind a reverse proxy.'),
  );

  $form['reverse_proxy']['reverse_proxy'] = array(
    '#type' => 'radios',
    '#title' => t('Reverse proxy'),
    '#default_value' => variable_get('reverse_proxy', FALSE),
    '#options' => array(t('Disabled'), t('Enabled')),
    '#description' => t('Enable this setting to determine the correct IP address of the remote client by examining information stored in the X-Forwarded-For headers. X-Forwarded-For headers are a standard mechanism for identifying client systems connecting through a reverse proxy server, such as Squid or Pound. Reverse proxy servers are often used to enhance the performance of heavily visited sites and may also provide other site caching, security or encryption benefits. If this Drupal installation operates behind a reverse proxy, this setting should be enabled so that correct IP address information is captured in Drupal\'s session management, logging, statistics and access management systems; if you are unsure about this setting, do not have a reverse proxy, or Drupal operates in a shared hosting environment, this setting should be set to disabled.'),
  );

723
  $form['#submit'][] = 'drupal_clear_css_cache';
Dries's avatar
 
Dries committed
724

725
  return system_settings_form($form);
Dries's avatar
Dries committed
726
}
Dries's avatar
 
Dries committed
727

Dries's avatar
Dries committed
728
function system_file_system_settings() {
729

Dries's avatar
Dries committed
730
  $form['file_directory_path'] = array(
731 732 733 734
    '#type' => 'textfield',
    '#title' => t('File system path'),
    '#default_value' => file_directory_path(),
    '#maxlength' => 255,
735
    '#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.'),
736
    '#after_build' => array('system_check_directory'),
737 738
  );

Dries's avatar
Dries committed
739
  $form['file_directory_temp'] = array(
740 741 742 743 744
    '#type' => 'textfield',
    '#title' => t('Temporary directory'),
    '#default_value' => file_directory_temp(),
    '#maxlength' => 255,
    '#description' => t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the Drupal installation directory.'),
745
    '#after_build' => array('system_check_directory'),
746 747
  );

Dries's avatar
Dries committed
748 749 750 751
  $form['file_downloads'] = array(
    '#type' => 'radios',
    '#title' => t('Download method'),
    '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
752
    '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
753
    '#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.')
754
  );
Dries's avatar
 
Dries committed
755

756
  return system_settings_form($form);
Dries's avatar
Dries committed
757 758 759
}

function system_image_toolkit_settings() {
760 761
  $toolkits_available = image_get_available_toolkits();
  if (count($toolkits_available) > 1) {
Dries's avatar
Dries committed
762 763 764 765 766
    $form['image_toolkit'] = array(
      '#type' => 'radios',
      '#title' => t('Select an image processing toolkit'),
      '#default_value' => variable_get('image_toolkit', image_get_toolkit()),
      '#options' => $toolkits_available
767
    );
768
  }
Dries's avatar
Dries committed
769
  else {
770
    $form['image_toolkit'] = array('#value' => '<p>'. t("No image toolkits found. Drupal will use PHP's built-in GD library for image handling.") .'</p>');
Dries's avatar
Dries committed
771
  }
772 773
  $form['image_toolkit_settings'] = image_toolkit_invoke('settings');
  return system_settings_form($form);
Dries's avatar
Dries committed
774 775 776
}

function system_rss_feeds_settings() {
777

Dries's avatar
Dries committed
778 779 780 781
  $form['feed_default_items'] = array(
    '#type' => 'select',
    '#title' => t('Number of items per feed'),
    '#default_value' => variable_get('feed_default_items', 10),
782 783
    '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
    '#description' => t('The default number of items to include in a feed.')
784
  );
Dries's avatar
Dries committed
785 786 787
  $form['feed_item_length'] = array(
    '#type' => 'select',
    '#title' => t('Display of XML feed items'),
Dries's avatar
Dries committed
788
    '#default_value' => variable_get('feed_item_length', 'teaser'),
789 790
    '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
    '#description' => t('Global setting for the length of XML feed items that are output by default.')
791
  );
792

793
  return system_settings_form($form);
Dries's avatar
Dries committed
794 795 796
}

function system_date_time_settings() {
797 798 799 800 801 802 803
  drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
  drupal_add_js(array('dateTime' => array('lookup' => url('admin/settings/date-time/lookup'))), 'setting');
  drupal_add_js('
// Global Killswitch
if (Drupal.jsEnabled) {
  $(document).ready(Drupal.dateTimeAutoAttach);
}', 'inline');
804
  // Date settings:
Steven Wittens's avatar
Steven Wittens committed
805
  $zones = _system_zonelist();
806

807
  // Date settings: possible date formats
808
  $date_short = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
809
           'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia',
Dries's avatar
 
Dries committed
810 811
           'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i',
           'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia');
812
  $date_medium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i',
Dries's avatar
 
Dries committed
813
          'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i',
Dries's avatar
 
Dries committed
814
          'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
815
          'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
816
  $date_long = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y,  F j - H:i',
817
        'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y,  F j - g:ia', 'l, j. F Y - G:i');
Dries's avatar
 
Dries committed
818

819
  // Date settings: construct choices for user
820 821
  foreach ($date_short as $f) {
    $date_short_choices[$f] = format_date(time(), 'custom', $f);
Dries's avatar
 
Dries committed
822
  }
823 824
  foreach ($date_medium as $f) {
    $date_medium_choices[$f] = format_date(time(), 'custom', $f);
Dries's avatar
 
Dries committed
825
  }
826 827
  foreach ($date_long as $f) {
    $date_long_choices[$f] = format_date(time