system.module 120 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
define('DRUPAL_CORE_COMPATIBILITY', '6.x');
11

12
13
14
15
16
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

17
18
19
// Maximum age of temporary files in seconds.
define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 1440);

Dries's avatar
   
Dries committed
20
21
22
23
/**
 * Implementation of hook_help().
 */
function system_help($section) {
24
25
  global $base_url;

26
  switch ($section) {
27
    case 'admin/help#system':
28
      $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>';
29
      $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>';
30
      $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>';
31
      $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>';
32
      return $output;
33
    case 'admin':
34
      return '<p>'. t('Welcome to the administration section. Here you may control how your site functions.') .'</p>';
35
    case 'admin/by-module':
36
      return '<p>'. t('This page shows you all available administration tasks for each module.') .'</p>';
37
    case 'admin/build/themes':
38
      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>';
39
    case 'admin/build/themes/settings':
40
      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>';
41
42
    case 'admin/build/themes/settings/'. arg(4):
      $reference = explode('.', arg(4), 2);
43
      $theme = array_pop($reference);
44
      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>';
45
    case 'admin/build/modules':
46
      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>
47
<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')));
48
    case 'admin/build/modules/uninstall':
49
      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>';
50
    case 'admin/logs/status':
51
      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>';
52
  }
Dries's avatar
   
Dries committed
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
82
83
84
85
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
86
87
88
/**
 * Implementation of hook_perm().
 */
Dries's avatar
 
Dries committed
89
function system_perm() {
90
  return array('administer site configuration', 'access administration pages', 'select different theme', 'administer files');
Dries's avatar
   
Dries committed
91
92
}

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

  // Inputs
101
  $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1);
102
103
  $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);
104
  $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
105
  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128);
106
  $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
107
  $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE);
108
  $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios'));
109
  $type['radio'] = array('#input' => TRUE, '#default_value' => NULL);
110
  $type['checkboxes'] = array('#input' => TRUE, '#process' => array('expand_checkboxes'), '#tree' => TRUE);
111
  $type['select'] = array('#input' => TRUE, '#size' => 0, '#multiple' => FALSE);
112
113
  $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'));
114
  $type['file'] = array('#input' => TRUE, '#size' => 60);
115
116

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

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

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

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

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

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

353
354
function system_init() {
  // Use the administrative theme if the user is looking at a page in the admin/* path.
355
  if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit'))) {
356
357
358
359
360
361
362
363
364
365
    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
366
367
368
369
370
/**
 * Implementation of hook_user().
 *
 * Allows users to individually set their theme and time zone.
 */
371
function system_user($type, $edit, &$user, $category = NULL) {
Dries's avatar
Dries committed
372
  if ($type == 'form' && $category == 'account') {
373
    $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
374

375
    if (variable_get('configurable_timezones', 1)) {
Steven Wittens's avatar
Steven Wittens committed
376
      $zones = _system_zonelist();
377
      $form['timezone'] = array(
378
        '#type' => 'fieldset',
379
380
381
382
        '#title' => t('Locale settings'),
        '#weight' => 6,
        '#collapsible' => TRUE,
      );
383
      $form['timezone']['timezone'] = array(
384
385
386
387
388
        '#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.'),
389
      );
Dries's avatar
   
Dries committed
390
    }
Dries's avatar
Dries committed
391

392
    return $form;
Dries's avatar
   
Dries committed
393
  }
Dries's avatar
   
Dries committed
394
395
}

396
397
398
/**
 * Provide a single block on the administration overview page.
 */
399
function system_admin_menu_block($item) {
400
  $content = array();
401
402
  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']));
403
  }
404
405
406
407
408
409
410
  $result = db_query("
    SELECT *
    FROM {menu_links} ml
    INNER JOIN {menu_router} m ON ml.router_path = m.path
    WHERE ml.plid = %d AND ml.menu_name = 'navigation' AND hidden = 0
    ORDER BY m.weight, m.title", $item['mlid']);
  while ($item = db_fetch_array($result)) {
411
    _menu_link_translate($item);
412
    if (!$item['access']) {
413
      continue;
414
    }
415
    $content[] = (array)$item;
416
417
418
419
420
421
422
423
424
  }
  return $content;
}

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

426
/**
427
 * This function allows selection of the theme to show in administration sections.
428
 */
429
function system_admin_theme_settings() {
430
431
432
433
  $themes = system_theme_data();
  ksort($themes);
  $options[0] = t('System default');
  foreach ($themes as $theme) {
434
    $options[$theme->name] = $theme->info['name'];
435
436
437
438
439
440
  }

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

445
446
447
  $form['node_admin_theme'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use administration theme for content editing'),
448
    '#description' => t('Use the administration theme when editing existing posts or creating new ones.'),
449
450
451
    '#default_value' => variable_get('node_admin_theme', '0'),
  );

452
  $form['#submit'][] = 'system_admin_theme_submit';
453
  return system_settings_form($form);
454
455
456
}


457
function system_admin_theme_submit($form, &$form_state) {
458
  // If we're changing themes, make sure the theme has its blocks initialized.
459
460
  if ($form_state['values']['admin_theme'] != variable_get('admin_theme', '0')) {
    $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_state['values']['admin_theme']);
461
    if (!db_num_rows($result)) {
462
      system_initialize_theme_blocks($form_state['values']['admin_theme']);
463
464
465
466
    }
  }
}

467
/**
468
469
470
471
472
473
474
475
476
477
478
 * 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
 */
479
function system_theme_select_form(&$form_state, $description = '', $default_value = '', $weight = 0) {
480
  if (user_access('select different theme')) {
481
    $enabled = array();
482
483
484
    $themes = list_themes();

    foreach ($themes as $theme) {
485
486
487
488
489
490
491
492
493
      if ($theme->status) {
        $enabled[] = $theme;
      }
    }

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

      $form['themes'] = array(
Dries's avatar
Dries committed
494
495
496
497
        '#type' => 'fieldset',
        '#title' => t('Theme configuration'),
        '#description' => $description,
        '#collapsible' => TRUE,
498
499
500
501
502
        '#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.
503
        $info->key = $info->name == variable_get('theme_default', 'garland') ? '' : $info->name;
504

505
506
507
508
509
510
511
512
513
514
515
        $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');
516

517
        $form['themes'][$info->key]['screenshot'] = array('#value' => $screenshot);
518
        $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>' : ''));
519
520
521
522
523
524
525
526
527
528
529
        $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) {
530
531
  foreach (element_children($form) as $key) {
    $row = array();
532
    if (isset($form[$key]['description']) && is_array($form[$key]['description'])) {
533
534
535
      $row[] = drupal_render($form[$key]['screenshot']);
      $row[] = drupal_render($form[$key]['description']);
      $row[] = drupal_render($form['theme'][$key]);
536
537
538
539
    }
    $rows[] = $row;
  }

540
  $header = array(t('Screenshot'), t('Name'), t('Selected'));
541
542
543
544
  $output = theme('table', $header, $rows);
  return $output;
}

Steven Wittens's avatar
Steven Wittens committed
545
546
547
548
549
550
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
551
    $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
552
553
554
555
  }
  return $zones;
}

Dries's avatar
Dries committed
556
557
558
559
function system_site_information_settings() {
  $form['site_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
560
    '#default_value' => variable_get('site_name', 'Drupal'),
561
    '#description' => t('The name of this website.'),
Dries's avatar
Dries committed
562
    '#required' => TRUE
563
  );
Dries's avatar
Dries committed
564
565
566
567
  $form['site_mail'] = array(
    '#type' => 'textfield',
    '#title' => t('E-mail address'),
    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
568
569
    '#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,
570
  );
Dries's avatar
Dries committed
571
572
573
574
  $form['site_slogan'] = array(
    '#type' => 'textfield',
    '#title' => t('Slogan'),
    '#default_value' => variable_get('site_slogan', ''),
575
    '#description' => t('The slogan of this website. Some themes display a slogan when available.')
576
577
  );

Dries's avatar
Dries committed
578
579
580
581
  $form['site_mission'] = array(
    '#type' => 'textarea',
    '#title' => t('Mission'),
    '#default_value' => variable_get('site_mission', ''),
582
    '#description' => t('Your site\'s mission statement or focus.')
583
  );
Dries's avatar
Dries committed
584
585
586
587
  $form['site_footer'] = array(
    '#type' => 'textarea',
    '#title' => t('Footer message'),
    '#default_value' => variable_get('site_footer', ''),
588
    '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
589
  );
Dries's avatar
Dries committed
590
591
592
  $form['anonymous'] = array(
    '#type' => 'textfield',
    '#title' => t('Anonymous user'),
593
    '#default_value' => variable_get('anonymous', t('Anonymous')),
594
    '#description' => t('The name used to indicate anonymous users.')
595
  );
Dries's avatar
Dries committed
596
597
598
599
  $form['site_frontpage'] = array(
    '#type' => 'textfield',
    '#title' => t('Default front page'),
    '#default_value' => variable_get('site_frontpage', 'node'),
600
601
    '#size' => 40,
    '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
602
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
603
  );
604

605
  return system_settings_form($form);
Dries's avatar
Dries committed
606
607
608
609
}

function system_clean_url_settings() {
  $form['clean_url'] = array(
610
611
612
613
    '#type' => 'radios',
    '#title' => t('Clean URLs'),
    '#default_value' => variable_get('clean_url', 0),
    '#options' => array(t('Disabled'), t('Enabled')),
614
    '#description' => t('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
615
  );
616

617
618
  if (!variable_get('clean_url', 0)) {
    if (strpos(request_uri(), '?q=') !== FALSE) {
619
620
621
622
623
624
625
626
627
628
629
      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>';

630
      $form['clean_url']['#disabled'] = TRUE;
631
632
      $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>';
633
634
    }
    else {
635
      $form['clean_url']['#description'] .= ' '. t('Your server has been successfully tested to support this feature.');
636
637
    }
  }
Dries's avatar
   
Dries committed
638

639
  return system_settings_form($form);
Dries's avatar
Dries committed
640
641
642
}

function system_error_reporting_settings() {
drumm's avatar
drumm committed
643
644

  $form['site_403'] = array(
Dries's avatar
Dries committed
645
    '#type' => 'textfield',
drumm's avatar
drumm committed
646
    '#title' => t('Default 403 (access denied) page'),
Dries's avatar
Dries committed
647
    '#default_value' => variable_get('site_403', ''),
648
649
    '#size' => 40,
    '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
650
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
651
  );
drumm's avatar
drumm committed
652
653

  $form['site_404'] = array(
Dries's avatar
Dries committed
654
    '#type' => 'textfield',
drumm's avatar
drumm committed
655
    '#title' => t('Default 404 (not found) page'),
Dries's avatar
Dries committed
656
    '#default_value' =>  variable_get('site_404', ''),
657
658
    '#size' => 40,
    '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
659
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
660
  );
drumm's avatar
drumm committed
661
662

  $form['error_level'] = array(
663
664
    '#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
665
    '#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.')
666
  );
drumm's avatar
drumm committed
667

668
  return system_settings_form($form);
Dries's avatar
Dries committed
669
}
Dries's avatar
 
Dries committed
670

671
function system_performance_settings() {
672

673
674
675
676
677
678
  $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) {
679
    $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>';
680
681
  }
  else {
682
    $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>';
683
  }
684
685
686
687
688
  $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.'),
  );
689

690
  $form['page_cache']['cache'] = array(
Dries's avatar
Dries committed
691
    '#type' => 'radios',
692
    '#title' => t('Caching mode'),
Dries's avatar
Dries committed
693
    '#default_value' => variable_get('cache', CACHE_DISABLED),
694
695
    '#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
696
697
  );

698
699
  $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');
700
  $form['page_cache']['cache_lifetime'] = array(
Dries's avatar
Dries committed
701
702
703
704
    '#type' => 'select',
    '#title' => t('Minimum cache lifetime'),
    '#default_value' => variable_get('cache_lifetime', 0),
    '#options' => $period,
705
    '#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.')
706
  );
707

708
709
710
  $form['bandwidth_optimizations'] = array(
    '#type' => 'fieldset',
    '#title' => t('Bandwidth optimizations'),
711
    '#description' => t('<p>Drupal can automatically aggregate and compress external resources like CSS and JavaScript into a single cached file. This can help reduce both the size and number of requests made to your website. This in turn reduces the server load, the bandwidth used, and the average page loading time for your visitors.</p><p>These options are disabled if you have not set up your files directory, or if your download method is set to private.</p>')
712
  );
713

714
  $directory = file_directory_path();
715
  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
716
717
  $form['bandwidth_optimizations']['preprocess_css'] = array(
    '#type' => 'radios',
718
719
    '#title' => t('Optimize CSS files'),
    '#default_value' => variable_get('preprocess_css', 0) && $is_writable,
720
721
    '#disabled' => !$is_writable,
    '#options' => array(t('Disabled'), t('Enabled')),
722
723
724
725
726
727
728
729
730
    '#description' => t("This option can interfere with theme development. It is recommended to only turn this on when your site is complete."),
  );
  $form['bandwidth_optimizations']['preprocess_js'] = array(
    '#type' => 'radios',
    '#title' => t('Optimize JavaScript files'),
    '#default_value' => variable_get('preprocess_js', 0) && $is_writable,
    '#disabled' => !$is_writable,
    '#options' => array(t('Disabled'), t('Enabled')),
    '#description' => t("This option can interfere with module development. It is recommended to only turn this on when your site is complete."),
731
732
  );

733
734
735
736
737
738
739
740
741
742
743
744
745
746
  $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.'),
  );

747
  $form['#submit'][] = 'drupal_clear_css_cache';
748
  $form['#submit'][] = 'drupal_clear_js_cache';
Dries's avatar
   
Dries committed
749

750
  return system_settings_form($form);
Dries's avatar
Dries committed
751
}
Dries's avatar
   
Dries committed
752

Dries's avatar
Dries committed
753
function system_file_system_settings() {
754

Dries's avatar
Dries committed
755
  $form['file_directory_path'] = array(
756
757
758
759
    '#type' => 'textfield',
    '#title' => t('File system path'),
    '#default_value' => file_directory_path(),
    '#maxlength' => 255,
760
    '#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.'),
761
    '#after_build' => array('system_check_directory'),
762
763
  );

Dries's avatar
Dries committed
764
  $form['file_directory_temp'] = array(
765
766
767
768
769
    '#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.'),
770
    '#after_build' => array('system_check_directory'),
771
772
  );

Dries's avatar
Dries committed
773
774
775
776
  $form['file_downloads'] = array(
    '#type' => 'radios',
    '#title' => t('Download method'),
    '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
777
    '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
778
    '#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.')
779
  );
Dries's avatar
   
Dries committed
780

781
  return system_settings_form($form);
Dries's avatar
Dries committed
782
783
784
}

function system_image_toolkit_settings() {
785
786
  $toolkits_available = image_get_available_toolkits();
  if (count($toolkits_available) > 1) {
Dries's avatar
Dries committed
787
788
789
790
791
    $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
792
    );
793
  }
Dries's avatar
Dries committed
794
  else {
795
    $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
796
  }
797
798
  $form['image_toolkit_settings'] = image_toolkit_invoke('settings');
  return system_settings_form($form);
Dries's avatar
Dries committed
799
800
801
}

function system_rss_feeds_settings() {
802

Dries's avatar
Dries committed
803
804
805
806
  $form['feed_default_items'] = array(
    '#type' => 'select',
    '#title' => t('Number of items per feed'),
    '#default_value' => variable_get('feed_default_items', 10),
807
808
    '#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.')
809
  );
Dries's avatar
Dries committed
810
811
812
  $form['feed_item_length'] = array(
    '#type' => 'select',
    '#title' => t('Display of XML feed items'),
Dries's avatar
Dries committed
813
    '#default_value' => variable_get('feed_item_length', 'teaser'),
814
815
    '#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.')
816
  );
817

818
  return system_settings_form($form);
Dries's avatar
Dries committed
819
820
821
}

function system_date_time_settings() {
822
823
824
825
826
827
828
  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');
829
  // Date settings:
Steven Wittens's avatar
Steven Wittens committed
830
  $zones = _system_zonelist();
831

832
  // Date settings: possible date formats
833
  $date_short = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
834
           '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
835
836
           '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');
837
  $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
838
          '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
839
          'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
840
          'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
841
  $date_long = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y,  F j - H:i',
842
        '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
843

844
  // Date settings: construct choices for user
845
846
  foreach ($date_short as $f) {
    $date_short_choices[$f] = format_date(time(), 'custom', $f);
Dries's avatar
   
Dries committed
847
  }
848
849
  foreach ($date_medium as $f) {
    $date_medium_choices[$f] = format_date(time(), 'custom', $f);
Dries's avatar
   
Dries committed
850
  }
851
852
  foreach ($date_long as $f) {
    $date_long_choices[$f] = format_date(time(), 'custom', $f);
Dries's avatar
   
Dries committed
853
854
  }

855
856
  $date_long_choices['custom'] = $date_medium_choices['custom'] = $date_short_choices['custom'] = t('Custom format');

857
858
859
860
861
862
  $form['locale'] = array(
    '#type' => 'fieldset',
    '#title' => t('Locale settings'),
  );

  $form['locale']['date_default_timezone'] = array(
Dries's avatar
Dries committed
863
864
865
866
867
    '#type' => 'select',
    '#title' => t('Default time zone'),
    '#default_value' => variable_get('date_default_timezone', 0),
    '#options' => $zones,
    '#description' => t('Select the default site time zone.')
868
869
  );

870
  $form['locale']['configurable_timezones'] = array(
Dries's avatar
Dries committed
871
    '#type' => 'radios',
872
    '#title' => t('User-configurable time zones'),
Dries's avatar
Dries committed
873
874
    '#default_value' => variable_get('configurable_timezones', 1),
    '#options' => array(t('Disabled'), t('Enabled')),
875
876
877
878
879
880
881
882
883
884
885
886
887
888
    '#description' => t('When enabled, users can set their own time zone and dates will be displayed accordingly.')
  );

  $form['locale']['date_first_day'] = array(
    '#type' => 'select',
    '#title' => t('First day of week'),
    '#default_value' => variable_get('date_first_day', 0),
    '#options' => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')),
    '#description' => t('The first day of the week for calendar views.')
  );

  $form['date_formats'] = array(
    '#type' => 'fieldset',
    '#title' => t('Formatting'),
889
890
  );

891
  $date_format_short = variable_get('date_format_short', $date_short[1]);
892
  $form['date_formats']['date_format_short'] = array(
893
894
    '#prefix' => '<div class="date-container"><div>',
    '#suffix' => '</div>',
Dries's avatar
Dries committed
895
896
    '#type' => 'select',
    '#title' => t('Short date format'),
897
898
899
900
    '#attributes' => array('class' => 'date-format'),
    '#default_value' => (isset($date_short_choices[$date_format_short]) ? $date_format_short : 'custom'),
    '#options' => $date_short_choices,
    '#description' => t('The short format of date display.'),
901
902
  );

903
  $default_short_custom = variable_get('date_format_short_custom', (isset($date_short_choices[$date_format_short]) ? $date_format_short : ''));
904
  $form['date_formats']['date_format_short_custom'] = array(
905
906
907
908
909
910
911
912
913
914
    '#prefix' => '<div class="custom-container">',
    '#suffix' => '</div></div>',
    '#type' => 'textfield',
    '#title' => t('Custom short date format'),
    '#attributes' => array('class' => 'custom-format'),
    '#default_value' => $default_short_custom,
    '#description' => t('A user-defined short date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(time(), 'custom', $default_short_custom))),
  );

  $date_format_medium = variable_get('date_format_medium', $date_medium[1]);
915
  $form['date_formats']['date_format_medium'] = array(
916
917
    '#prefix' => '<div class="date-container"><div>',
    '#suffix' => '</div>',
Dries's avatar
Dries committed
918
919
    '#type' => 'select',
    '#title' => t('Medium date format'),
920
921
922
923
924
925
926
    '#attributes' => array('class' => 'date-format'),
    '#default_value' => (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : 'custom'),
    '#options' => $date_medium_choices,
    '#description' => t('The medium sized date display.'),
  );

  $default_medium_custom = variable_get('date_format_medium_custom', (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : ''));
927
  $form['date_formats']['date_format_medium_custom'] = array(
928
929
930
931
932
933
934
    '#prefix' => '<div class="custom-container">',
    '#suffix' => '</div></div>',
    '#type' => 'textfield',
    '#title' => t('Custom medium date format'),
    '#attributes' => array('class' => 'custom-format'),
    '#default_value' => $default_medium_custom,
    '#description' => t('A user-defined medium date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(time(), 'custom', $default_medium_custom))),
935
936
  );

937
  $date_format_long = variable_get('date_format_long', $date_long[0]);
938
  $form['date_formats']['date_format_long'] = array(
939
940
    '#prefix' => '<div class="date-container"><div>',
    '#suffix' => '</div>',
Dries's avatar
Dries committed
941
942
    '#type' => 'select',
    '#title' => t('Long date format'),
943
944
945
    '#attributes' => array('class' => 'date-format'),
    '#default_value' => (isset($date_long_choices[$date_format_long]) ? $date_format_long : 'custom'),
    '#options' => $date_long_choices,
Dries's avatar
Dries committed
946
    '#description' => t('Longer date format used for detailed display.')
947
948
  );

949
  $default_long_custom = variable_get('date_format_long_custom', (isset($date_long_choices[$date_format_long]) ? $date_format_long : ''));
950
  $form['date_formats']['date_format_long_custom'] = array(
951
952
953
954
955
956
957
958
959
960
961
    '#prefix' => '<div class="custom-container">',
    '#suffix' => '</div></div>',
    '#type' => 'textfield',
    '#title' => t('Custom long date format'),
    '#attributes' => array('class' => 'custom-format'),
    '#default_value' => $default_long_custom,
    '#description' => t('A user-defined long date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(time(), 'custom', $default_long_custom))),
  );

  $form = system_settings_form($form);
  // We will call system_settings_form_submit() manually, so remove it for now.
962
  unset($form['#submit']);
963
964
  return $form;
}
Dries's avatar
   
Dries committed
965

966
967
968
function system_date_time_settings_submit($form, &$form_state) {
  if ($form_state['values']['date_format_short'] == 'custom') {
    $form_state['values']['date_format_short'] = $form_state['values']['date_format_short_custom'];
969
  }
970
971
  if ($form_state['values']['date_format_medium'] == 'custom') {
    $form_state['values']['date_format_medium'] = $form_state['values']['date_format_medium_custom'];
972
  }
973
974
  if ($form_state['values']['date_format_long'] == 'custom') {
    $form_state['values']['date_format_long'] = $form_state['values']['date_format_long_custom'];
975
  }
976
  return system_settings_form_submit($form, $form_state);
977
978
979
980
981
982
983
984
985
}

/**
 * Return the date for a given format string via Ajax.
 */
function system_date_time_lookup() {
  $result = format_date(time(), 'custom', $_GET['format']);
  echo drupal_to_js($result);
  exit;
Dries's avatar
Dries committed
986
}
Dries's avatar
 
Dries committed
987

988
function system_site_maintenance_settings() {
989

Dries's avatar
Dries committed
990
  $form['site_offline'] = array(
991
    '#type' => 'radios',
992
    '#title' => t('Site status'),
993
    '#default_value' => variable_get('site_offline', 0),
994
    '#options' => array(t('Online'), t('Off-line')),
995
    '#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'))),
996
997
  );

Dries's avatar
Dries committed
998
  $form['site_offline_message'] = array(
999
    '#type' => 'textarea',
1000
    '#title' => t('Site off-line message'),