[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

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

   1  <?php
   2  // $Id: system.module,v 1.585.2.59 2010/12/15 21:11:23 goba Exp $
   3  
   4  /**
   5   * @file
   6   * Configuration system that lets administrators modify the workings of the site.
   7   */
   8  
   9  /**
  10   * The current system version.
  11   */
  12  define('VERSION', '6.20');
  13  
  14  /**
  15   * Core API compatibility.
  16   */
  17  define('DRUPAL_CORE_COMPATIBILITY', '6.x');
  18  
  19  /**
  20   * Minimum supported version of PHP.
  21   */
  22  define('DRUPAL_MINIMUM_PHP',    '4.3.5');
  23  
  24  /**
  25   * Minimum recommended value of PHP memory_limit.
  26   */
  27  define('DRUPAL_MINIMUM_PHP_MEMORY_LIMIT',    '16M');
  28  
  29  /**
  30   * Minimum supported version of MySQL, if it is used.
  31   */
  32  define('DRUPAL_MINIMUM_MYSQL',  '4.1.1');
  33  
  34  /**
  35   * Minimum supported version of PostgreSQL, if it is used.
  36   */
  37  define('DRUPAL_MINIMUM_PGSQL',  '7.4');
  38  
  39  /**
  40   * Maximum age of temporary files in seconds.
  41   */
  42  define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 21600);
  43  
  44  /**
  45   * Implementation of hook_help().
  46   */
  47  function system_help($path, $arg) {
  48    global $base_url;
  49  
  50    switch ($path) {
  51      case 'admin/help#system':
  52        $output = '<p>'. t('The system module is at the foundation of your Drupal website, and provides basic but extensible functionality for use by other modules and themes. Some integral elements of Drupal are contained in and managed by the system module, including caching, enabling or disabling of modules and themes, preparing and displaying the administrative page, and configuring fundamental site settings. A number of key system maintenance operations are also part of the system module.') .'</p>';
  53        $output .= '<p>'. t('The system module provides:') .'</p>';
  54        $output .= '<ul><li>'. t('support for enabling and disabling <a href="@modules">modules</a>. Drupal comes packaged with a number of core modules; each module provides a discrete set of features and may be enabled depending on the needs of your site. A wide array of additional modules contributed by members of the Drupal community are available for download at the <a href="@drupal-modules">Drupal.org module page</a>.', array('@modules' => url('admin/build/modules'), '@drupal-modules' => 'http://drupal.org/project/modules')) .'</li>';
  55        $output .= '<li>'. t('support for enabling and disabling <a href="@themes">themes</a>, which determine the design and presentation of your site. Drupal comes packaged with several core themes and additional contributed themes are available at the <a href="@drupal-themes">Drupal.org theme page</a>.', array('@themes' => url('admin/build/themes'), '@drupal-themes' => 'http://drupal.org/project/themes')) .'</li>';
  56        $output .= '<li>'. t('a robust <a href="@cache-settings">caching system</a> that allows the efficient re-use of previously-constructed web pages and web page components. Drupal stores the pages requested by anonymous users in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, Drupal\'s caching system may significantly increase the speed of your site.', array('@cache-settings' => url('admin/settings/performance'))) .'</li>';
  57        $output .= '<li>'. t('a set of routine administrative operations that rely on a correctly-configured <a href="@cron">cron maintenance task</a> to run automatically. A number of other modules, including the feed aggregator, ping module and search also rely on <a href="@cron">cron maintenance tasks</a>. For more information, see the online handbook entry for <a href="@handbook">configuring cron jobs</a>.', array('@cron' => url('admin/reports/status'), '@handbook' => 'http://drupal.org/cron')) .'</li>';
  58        $output .= '<li>'. t('basic configuration options for your site, including <a href="@date-settings">date and time settings</a>, <a href="@file-system">file system settings</a>, <a href="@clean-url">clean URL support</a>, <a href="@site-info">site name and other information</a>, and a <a href="@site-maintenance">site maintenance</a> function for taking your site temporarily off-line.', array('@date-settings' => url('admin/settings/date-time'), '@file-system' => url('admin/settings/file-system'), '@clean-url' => url('admin/settings/clean-urls'), '@site-info' => url('admin/settings/site-information'), '@site-maintenance' => url('admin/settings/site-maintenance'))) .'</li></ul>';
  59        $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@system">System module</a>.', array('@system' => 'http://drupal.org/handbook/modules/system/')) .'</p>';
  60        return $output;
  61      case 'admin':
  62        return '<p>'. t('Welcome to the administration section. Here you may control how your site functions.') .'</p>';
  63      case 'admin/by-module':
  64        return '<p>'. t('This page shows you all available administration tasks for each module.') .'</p>';
  65      case 'admin/build/themes':
  66        $output = '<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. Alternatively, to override these settings in a specific theme, click the "configure" link for that theme. Note that different themes may have different regions available for displaying content; for consistency in presentation, you may wish to enable only one theme.') .'</p>';
  67        $output .= '<p>'. t('To change the appearance of your site, a number of <a href="@themes">contributed themes</a> are available.', array('@themes' => 'http://drupal.org/project/themes')) .'</p>';
  68        return $output;
  69      case 'admin/build/themes/settings/'. $arg[4]:
  70        $reference = explode('.', $arg[4], 2);
  71        $theme = array_pop($reference);
  72        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>';
  73      case 'admin/build/themes/settings':
  74        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>';
  75      case 'admin/build/modules':
  76        $output = '<p>'. t('Modules are plugins that extend Drupal\'s core functionality. Enable modules by selecting the <em>Enabled</em> checkboxes below and clicking the <em>Save configuration</em> button. Once a module is enabled, new <a href="@permissions">permissions</a> may be available. To reduce server load, modules with their <em>Throttle</em> checkbox selected are temporarily disabled when your site becomes extremely busy. (Note that the <em>Throttle</em> checkbox is only available if the Throttle module is enabled.)', array('@permissions' => url('admin/user/permissions')));
  77        if (module_exists('throttle')) {
  78          $output .= ' '. t('The auto-throttle functionality must be enabled on the <a href="@throttle">throttle configuration page</a> after having enabled the throttle module.', array('@throttle' => url('admin/settings/throttle')));
  79        }
  80        $output .= '</p>';
  81        $output .= '<p>'. t('It is important that <a href="@update-php">update.php</a> is run every time a module is updated to a newer version.', array('@update-php' => $base_url .'/update.php')) .'</p>';
  82        $output .= '<p>'. t('You can find all administration tasks belonging to a particular module on the <a href="@by-module">administration by module page</a>.', array('@by-module' => url('admin/by-module'))) .'</p>';
  83        $output .= '<p>'. t('To extend the functionality of your site, a number of <a href="@modules">contributed modules</a> are available.', array('@modules' => 'http://drupal.org/project/modules')) .'</p>';
  84        $output .= '<p>'. t('To clear all caches, click the button on the <a href="@performance">Performance page</a>.', array('@performance' => url('admin/settings/performance', array('fragment' => 'edit-clear')))) .'</p>';
  85        return $output;
  86      case 'admin/build/modules/uninstall':
  87        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>';
  88      case 'admin/build/block/configure':
  89        if ($arg[4] == 'system' && $arg[5] == 0) {
  90          return '<p>'. t('The <em>Powered by Drupal</em> block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') .'</p>';
  91        }
  92        break;
  93      case 'admin/settings/actions':
  94      case 'admin/settings/actions/manage':
  95        $output = '<p>'. t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the trigger module, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions.') .'</p>';
  96        $output .= '<p>'. t('There are two types of actions: simple and advanced. Simple actions do not require any additional configuration, and are listed here automatically. Advanced actions can do more than simple actions; for example, send an e-mail to a specified address, or check for certain words within a piece of content. These actions need to be created and configured first before they may be used. To create an advanced action, select the action from the drop-down below and click the <em>Create</em> button.') .'</p>';
  97        if (module_exists('trigger')) {
  98          $output .= '<p>'. t('You may proceed to the <a href="@url">Triggers</a> page to assign these actions to system events.', array('@url' => url('admin/build/trigger'))) .'</p>';
  99        }
 100        return $output;
 101      case 'admin/settings/actions/configure':
 102        return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended, in order to better identify the precise action taking place. This description will be displayed in modules such as the trigger module when assigning actions to system events, so it is best if it is as descriptive as possible (for example, "Send e-mail to Moderation Team" rather than simply "Send e-mail").');
 103      case 'admin/reports/status':
 104        return '<p>'. t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues.") .'</p>';
 105    }
 106  }
 107  
 108  /**
 109   * Implementation of hook_theme().
 110   */
 111  function system_theme() {
 112    return array_merge(drupal_common_theme(), array(
 113      'system_theme_select_form' => array(
 114        'arguments' => array('form' => NULL),
 115        'file' => 'system.admin.inc',
 116      ),
 117      'system_themes_form' => array(
 118        'arguments' => array('form' => NULL),
 119        'file' => 'system.admin.inc',
 120      ),
 121      'system_modules' => array(
 122        'arguments' => array('form' => NULL),
 123        'file' => 'system.admin.inc',
 124      ),
 125      'system_modules_uninstall' => array(
 126        'arguments' => array('form' => NULL),
 127        'file' => 'system.admin.inc',
 128      ),
 129      'status_report' => array(
 130        'arguments' => array('requirements' => NULL),
 131        'file' => 'system.admin.inc',
 132      ),
 133      'admin_page' => array(
 134        'arguments' => array('blocks' => NULL),
 135        'file' => 'system.admin.inc',
 136      ),
 137      'admin_block' => array(
 138        'arguments' => array('block' => NULL),
 139        'file' => 'system.admin.inc',
 140      ),
 141      'admin_block_content' => array(
 142        'arguments' => array('content' => NULL),
 143        'file' => 'system.admin.inc',
 144      ),
 145      'system_admin_by_module' => array(
 146        'arguments' => array('menu_items' => NULL),
 147        'file' => 'system.admin.inc',
 148      ),
 149      'system_powered_by' => array(
 150        'arguments' => array('image_path' => NULL),
 151      ),
 152    ));
 153  }
 154  
 155  /**
 156   * Implementation of hook_perm().
 157   */
 158  function system_perm() {
 159    return array('administer site configuration', 'access administration pages', 'administer actions', 'access site reports', 'select different theme', 'administer files');
 160  }
 161  
 162  /**
 163   * Implementation of hook_elements().
 164   */
 165  function system_elements() {
 166    // Top level form
 167    $type['form'] = array('#method' => 'post', '#action' => request_uri());
 168  
 169    // Inputs
 170    $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'));
 171    $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#process' => array('form_expand_ahah'));
 172    $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL);
 173    $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE, '#process' => array('form_expand_ahah'));
 174    $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#process' => array('form_expand_ahah'));
 175    $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
 176    $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE, '#process' => array('form_expand_ahah'));
 177    $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios'));
 178    $type['radio'] = array('#input' => TRUE, '#default_value' => NULL, '#process' => array('form_expand_ahah'));
 179    $type['checkboxes'] = array('#input' => TRUE, '#process' => array('expand_checkboxes'), '#tree' => TRUE);
 180    $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1, '#process' => array('form_expand_ahah'));
 181    $type['select'] = array('#input' => TRUE, '#size' => 0, '#multiple' => FALSE, '#process' => array('form_expand_ahah'));
 182    $type['weight'] = array('#input' => TRUE, '#delta' => 10, '#default_value' => 0, '#process' => array('process_weight', 'form_expand_ahah'));
 183    $type['date'] = array('#input' => TRUE, '#process' => array('expand_date'), '#element_validate' => array('date_validate'));
 184    $type['file'] = array('#input' => TRUE, '#size' => 60);
 185  
 186    // Form structure
 187    $type['item'] = array('#value' => '');
 188    $type['hidden'] = array('#input' => TRUE, '#process' => array('form_expand_ahah'));
 189    $type['value'] = array('#input' => TRUE);
 190    $type['markup'] = array('#prefix' => '', '#suffix' => '');
 191    $type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE, '#value' => NULL, '#process' => array('form_expand_ahah'));
 192    $type['token'] = array('#input' => TRUE);
 193    return $type;
 194  }
 195  
 196  /**
 197   * Implementation of hook_menu().
 198   */
 199  function system_menu() {
 200    $items['system/files'] = array(
 201      'title' => 'File download',
 202      'page callback' => 'file_download',
 203      'access callback' => TRUE,
 204      'type' => MENU_CALLBACK,
 205    );
 206    $items['admin'] = array(
 207      'title' => 'Administer',
 208      'access arguments' => array('access administration pages'),
 209      'page callback' => 'system_main_admin_page',
 210      'weight' => 9,
 211      'file' => 'system.admin.inc',
 212    );
 213    $items['admin/compact'] = array(
 214      'title' => 'Compact mode',
 215      'page callback' => 'system_admin_compact_page',
 216      'access arguments' => array('access administration pages'),
 217      'type' => MENU_CALLBACK,
 218      'file' => 'system.admin.inc',
 219    );
 220    $items['admin/by-task'] = array(
 221      'title' => 'By task',
 222      'page callback' => 'system_main_admin_page',
 223      'access arguments' => array('access administration pages'),
 224      'file' => 'system.admin.inc',
 225      'type' => MENU_DEFAULT_LOCAL_TASK,
 226    );
 227    $items['admin/by-module'] = array(
 228      'title' => 'By module',
 229      'page callback' => 'system_admin_by_module',
 230      'access arguments' => array('access administration pages'),
 231      'file' => 'system.admin.inc',
 232      'type' => MENU_LOCAL_TASK,
 233      'weight' => 2,
 234    );
 235    $items['admin/content'] = array(
 236      'title' => 'Content management',
 237      'description' => "Manage your site's content.",
 238      'position' => 'left',
 239      'weight' => -10,
 240      'page callback' => 'system_admin_menu_block_page',
 241      'access arguments' => array('access administration pages'),
 242      'file' => 'system.admin.inc',
 243    );
 244  
 245    // menu items that are basically just menu blocks
 246    $items['admin/settings'] = array(
 247      'title' => 'Site configuration',
 248      'description' => 'Adjust basic site configuration options.',
 249      'position' => 'right',
 250      'weight' => -5,
 251      'page callback' => 'system_settings_overview',
 252      'access arguments' => array('access administration pages'),
 253      'file' => 'system.admin.inc',
 254    );
 255    $items['admin/build'] = array(
 256      'title' => 'Site building',
 257      'description' => 'Control how your site looks and feels.',
 258      'position' => 'right',
 259      'weight' => -10,
 260      'page callback' => 'system_admin_menu_block_page',
 261      'access arguments' => array('access administration pages'),
 262      'file' => 'system.admin.inc',
 263    );
 264    $items['admin/settings/admin'] = array(
 265      'title' => 'Administration theme',
 266      'description' => 'Settings for how your administrative pages should look.',
 267      'position' => 'left',
 268      'page callback' => 'drupal_get_form',
 269      'page arguments' => array('system_admin_theme_settings'),
 270      'access arguments' => array('administer site configuration'),
 271      'block callback' => 'system_admin_theme_settings',
 272      'file' => 'system.admin.inc',
 273    );
 274    // Themes:
 275    $items['admin/build/themes'] = array(
 276      'title' => 'Themes',
 277      'description' => 'Change which theme your site uses or allows users to set.',
 278      'page callback' => 'drupal_get_form',
 279      'page arguments' => array('system_themes_form', NULL),
 280      'access arguments' => array('administer site configuration'),
 281      'file' => 'system.admin.inc',
 282    );
 283    $items['admin/build/themes/select'] = array(
 284      'title' => 'List',
 285      'description' => 'Select the default theme.',
 286      'type' => MENU_DEFAULT_LOCAL_TASK,
 287      'weight' => -1,
 288    );
 289    $items['admin/build/themes/settings'] = array(
 290      'title' => 'Configure',
 291      'page arguments' => array('system_theme_settings'),
 292      'access arguments' => array('administer site configuration'),
 293      'type' => MENU_LOCAL_TASK,
 294    );
 295    // Theme configuration subtabs
 296    $items['admin/build/themes/settings/global'] = array(
 297      'title' => 'Global settings',
 298      'type' => MENU_DEFAULT_LOCAL_TASK,
 299      'weight' => -1,
 300    );
 301  
 302    foreach (list_themes() as $theme) {
 303      $items['admin/build/themes/settings/'. $theme->name] = array(
 304        'title' => $theme->info['name'],
 305        'page arguments' => array('system_theme_settings', $theme->name),
 306        'type' => MENU_LOCAL_TASK,
 307        'access callback' => '_system_themes_access',
 308        'access arguments' => array($theme),
 309      );
 310    }
 311  
 312    // Modules:
 313    $items['admin/build/modules'] = array(
 314      'title' => 'Modules',
 315      'description' => 'Enable or disable add-on modules for your site.',
 316      'page callback' => 'drupal_get_form',
 317      'page arguments' => array('system_modules'),
 318      'access arguments' => array('administer site configuration'),
 319      'file' => 'system.admin.inc',
 320    );
 321    $items['admin/build/modules/list'] = array(
 322      'title' => 'List',
 323      'type' => MENU_DEFAULT_LOCAL_TASK,
 324    );
 325    $items['admin/build/modules/list/confirm'] = array(
 326      'title' => 'List',
 327      'access arguments' => array('administer site configuration'),
 328      'type' => MENU_CALLBACK,
 329    );
 330    $items['admin/build/modules/uninstall'] = array(
 331      'title' => 'Uninstall',
 332      'page arguments' => array('system_modules_uninstall'),
 333      'access arguments' => array('administer site configuration'),
 334      'type' => MENU_LOCAL_TASK,
 335    );
 336    $items['admin/build/modules/uninstall/confirm'] = array(
 337      'title' => 'Uninstall',
 338      'access arguments' => array('administer site configuration'),
 339      'type' => MENU_CALLBACK,
 340    );
 341  
 342    // Actions:
 343    $items['admin/settings/actions'] = array(
 344      'title' => 'Actions',
 345      'description' => 'Manage the actions defined for your site.',
 346      'access arguments' => array('administer actions'),
 347      'page callback' => 'system_actions_manage'
 348    );
 349    $items['admin/settings/actions/manage'] = array(
 350      'title' => 'Manage actions',
 351      'description' => 'Manage the actions defined for your site.',
 352      'page callback' => 'system_actions_manage',
 353      'type' => MENU_DEFAULT_LOCAL_TASK,
 354      'weight' => -2,
 355    );
 356    $items['admin/settings/actions/configure'] = array(
 357      'title' => 'Configure an advanced action',
 358      'page callback' => 'drupal_get_form',
 359      'page arguments' => array('system_actions_configure'),
 360      'access arguments' => array('administer actions'),
 361      'type' => MENU_CALLBACK,
 362    );
 363    $items['admin/settings/actions/delete/%actions'] = array(
 364      'title' => 'Delete action',
 365      'description' => 'Delete an action.',
 366      'page callback' => 'drupal_get_form',
 367      'page arguments' => array('system_actions_delete_form', 4),
 368      'access arguments' => array('administer actions'),
 369      'type' => MENU_CALLBACK,
 370    );
 371    $items['admin/settings/actions/orphan'] = array(
 372      'title' => 'Remove orphans',
 373      'page callback' => 'system_actions_remove_orphans',
 374      'access arguments' => array('administer actions'),
 375      'type' => MENU_CALLBACK,
 376    );
 377  
 378    // Settings:
 379    $items['admin/settings/site-information'] = array(
 380      'title' => 'Site information',
 381      'description' => 'Change basic site information, such as the site name, slogan, e-mail address, mission, front page and more.',
 382      'page callback' => 'drupal_get_form',
 383      'page arguments' => array('system_site_information_settings'),
 384      'access arguments' => array('administer site configuration'),
 385      'file' => 'system.admin.inc',
 386    );
 387    $items['admin/settings/error-reporting'] = array(
 388      'title' => 'Error reporting',
 389      'description' => 'Control how Drupal deals with errors including 403/404 errors as well as PHP error reporting.',
 390      'page callback' => 'drupal_get_form',
 391      'page arguments' => array('system_error_reporting_settings'),
 392      'access arguments' => array('administer site configuration'),
 393      'file' => 'system.admin.inc',
 394    );
 395    $items['admin/settings/logging'] = array(
 396      'title' => 'Logging and alerts',
 397      'description' => "Settings for logging and alerts modules. Various modules can route Drupal's system events to different destination, such as syslog, database, email, ...etc.",
 398      'page callback' => 'system_logging_overview',
 399      'access arguments' => array('administer site configuration'),
 400      'file' => 'system.admin.inc',
 401    );
 402    $items['admin/settings/performance'] = array(
 403      'title' => 'Performance',
 404      'description' => 'Enable or disable page caching for anonymous users and set CSS and JS bandwidth optimization options.',
 405      'page callback' => 'drupal_get_form',
 406      'page arguments' => array('system_performance_settings'),
 407      'access arguments' => array('administer site configuration'),
 408      'file' => 'system.admin.inc',
 409    );
 410    $items['admin/settings/file-system'] = array(
 411      'title' => 'File system',
 412      'description' => 'Tell Drupal where to store uploaded files and how they are accessed.',
 413      'page callback' => 'drupal_get_form',
 414      'page arguments' => array('system_file_system_settings'),
 415      'access arguments' => array('administer site configuration'),
 416      'file' => 'system.admin.inc',
 417    );
 418    $items['admin/settings/image-toolkit'] = array(
 419      'title' => 'Image toolkit',
 420      'description' => 'Choose which image toolkit to use if you have installed optional toolkits.',
 421      'page callback' => 'drupal_get_form',
 422      'page arguments' => array('system_image_toolkit_settings'),
 423      'access arguments' => array('administer site configuration'),
 424      'file' => 'system.admin.inc',
 425    );
 426    $items['admin/content/rss-publishing'] = array(
 427      'title' => 'RSS publishing',
 428      'description' => 'Configure the number of items per feed and whether feeds should be titles/teasers/full-text.',
 429      'page callback' => 'drupal_get_form',
 430      'page arguments' => array('system_rss_feeds_settings'),
 431      'access arguments' => array('administer site configuration'),
 432      'file' => 'system.admin.inc',
 433    );
 434    $items['admin/settings/date-time'] = array(
 435      'title' => 'Date and time',
 436      'description' => "Settings for how Drupal displays date and time, as well as the system's default timezone.",
 437      'page callback' => 'drupal_get_form',
 438      'page arguments' => array('system_date_time_settings'),
 439      'access arguments' => array('administer site configuration'),
 440      'file' => 'system.admin.inc',
 441    );
 442    $items['admin/settings/date-time/lookup'] = array(
 443      'title' => 'Date and time lookup',
 444      'type' => MENU_CALLBACK,
 445      'page callback' => 'system_date_time_lookup',
 446      'access arguments' => array('administer site configuration'),
 447      'file' => 'system.admin.inc',
 448    );
 449    $items['admin/settings/site-maintenance'] = array(
 450      'title' => 'Site maintenance',
 451      'description' => 'Take the site off-line for maintenance or bring it back online.',
 452      'page callback' => 'drupal_get_form',
 453      'page arguments' => array('system_site_maintenance_settings'),
 454      'access arguments' => array('administer site configuration'),
 455      'file' => 'system.admin.inc',
 456    );
 457    $items['admin/settings/clean-urls'] = array(
 458      'title' => 'Clean URLs',
 459      'description' => 'Enable or disable clean URLs for your site.',
 460      'page callback' => 'drupal_get_form',
 461      'page arguments' => array('system_clean_url_settings'),
 462      'access arguments' => array('administer site configuration'),
 463      'file' => 'system.admin.inc',
 464    );
 465    $items['admin/settings/clean-urls/check'] = array(
 466      'title' => 'Clean URL check',
 467      'page callback' => 'drupal_json',
 468      'page arguments' => array(array('status' => TRUE)),
 469      'access callback' => TRUE,
 470      'type' => MENU_CALLBACK,
 471    );
 472  
 473    // Reports:
 474    $items['admin/reports'] = array(
 475      'title' => 'Reports',
 476      'description' => 'View reports from system logs and other status information.',
 477      'page callback' => 'system_admin_menu_block_page',
 478      'access arguments' => array('access site reports'),
 479      'weight' => 5,
 480      'position' => 'left',
 481      'file' => 'system.admin.inc',
 482    );
 483    $items['admin/reports/status'] = array(
 484      'title' => 'Status report',
 485      'description' => "Get a status report about your site's operation and any detected problems.",
 486      'page callback' => 'system_status',
 487      'weight' => 10,
 488      'access arguments' => array('administer site configuration'),
 489      'file' => 'system.admin.inc',
 490    );
 491    $items['admin/reports/status/run-cron'] = array(
 492      'title' => 'Run cron',
 493      'page callback' => 'system_run_cron',
 494      'access arguments' => array('administer site configuration'),
 495      'type' => MENU_CALLBACK,
 496      'file' => 'system.admin.inc',
 497    );
 498    $items['admin/reports/status/php'] = array(
 499      'title' => 'PHP',
 500      'page callback' => 'system_php',
 501      'access arguments' => array('administer site configuration'),
 502      'type' => MENU_CALLBACK,
 503      'file' => 'system.admin.inc',
 504    );
 505    $items['admin/reports/status/sql'] = array(
 506      'title' => 'SQL',
 507      'page callback' => 'system_sql',
 508      'access arguments' => array('administer site configuration'),
 509      'type' => MENU_CALLBACK,
 510      'file' => 'system.admin.inc',
 511    );
 512    // Default page for batch operations
 513    $items['batch'] = array(
 514      'page callback' => 'system_batch_page',
 515      'access callback' => TRUE,
 516      'type' => MENU_CALLBACK,
 517      'file' => 'system.admin.inc',
 518    );
 519    return $items;
 520  }
 521  
 522  /**
 523   * Menu item access callback - only admin or enabled themes can be accessed.
 524   */
 525  function _system_themes_access($theme) {
 526    return user_access('administer site configuration') && ($theme->status || $theme->name == variable_get('admin_theme', '0'));
 527  }
 528  
 529  /**
 530   * Implementation of hook_init().
 531   */
 532  function system_init() {
 533    // Use the administrative theme if the user is looking at a page in the admin/* path.
 534    if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit'))) {
 535      global $custom_theme;
 536      $custom_theme = variable_get('admin_theme', '0');
 537      drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
 538    }
 539  
 540    // Add the CSS for this module.
 541    drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module');
 542    drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module');
 543    drupal_add_css(drupal_get_path('module', 'system') .'/system-menus.css', 'module');
 544  }
 545  
 546  /**
 547   * Implementation of hook_user().
 548   *
 549   * Allows users to individually set their theme and time zone.
 550   */
 551  function system_user($type, $edit, &$user, $category = NULL) {
 552    if ($type == 'form' && $category == 'account') {
 553      $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);
 554  
 555      if (variable_get('configurable_timezones', 1)) {
 556        $zones = _system_zonelist();
 557        $form['timezone'] = array(
 558          '#type' => 'fieldset',
 559          '#title' => t('Locale settings'),
 560          '#weight' => 6,
 561          '#collapsible' => TRUE,
 562        );
 563        $form['timezone']['timezone'] = array(
 564          '#type' => 'select',
 565          '#title' => t('Time zone'),
 566          '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone', 0),
 567          '#options' => $zones,
 568          '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'),
 569        );
 570      }
 571  
 572      return $form;
 573    }
 574  }
 575  
 576  /**
 577   * Implementation of hook_block().
 578   *
 579   * Generate a block with a promotional link to Drupal.org.
 580   */
 581  function system_block($op = 'list', $delta = 0, $edit = NULL) {
 582    switch ($op) {
 583      case 'list':
 584        $blocks[0] = array(
 585          'info' => t('Powered by Drupal'),
 586          'weight' => '10',
 587           // Not worth caching.
 588          'cache' => BLOCK_NO_CACHE,
 589        );
 590        return $blocks;
 591      case 'configure':
 592        // Compile a list of fields to show
 593        $form['wrapper']['color'] = array(
 594          '#type' => 'select',
 595          '#title' => t('Badge color'),
 596          '#default_value' => variable_get('drupal_badge_color', 'powered-blue'),
 597          '#options' => array('powered-black' => t('Black'), 'powered-blue' => t('Blue'), 'powered-gray' => t('Gray')),
 598        );
 599        $form['wrapper']['size'] = array(
 600          '#type' => 'select',
 601          '#title' => t('Badge size'),
 602          '#default_value' => variable_get('drupal_badge_size', '80x15'),
 603          '#options' => array('80x15' => t('Small'), '88x31' => t('Medium'), '135x42' => t('Large')),
 604        );
 605        return $form;
 606      case 'save':
 607        variable_set('drupal_badge_color', $edit['color']);
 608        variable_set('drupal_badge_size', $edit['size']);
 609        break;
 610      case 'view':
 611        $image_path = 'misc/'. variable_get('drupal_badge_color', 'powered-blue') .'-'. variable_get('drupal_badge_size', '80x15') .'.png';
 612        $block['subject'] = NULL; // Don't display a title
 613        $block['content'] = theme('system_powered_by', $image_path);
 614        return $block;
 615    }
 616  }
 617  
 618  /**
 619   * Provide a single block on the administration overview page.
 620   *
 621   * @param $item
 622   *   The menu item to be displayed.
 623   */
 624  function system_admin_menu_block($item) {
 625    $content = array();
 626    if (!isset($item['mlid'])) {
 627      $item += db_fetch_array(db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = '%s' AND module = 'system'", $item['path']));
 628    }
 629    $result = db_query("
 630      SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.*
 631      FROM {menu_links} ml
 632      LEFT JOIN {menu_router} m ON ml.router_path = m.path
 633      WHERE ml.plid = %d AND ml.menu_name = '%s' AND hidden = 0", $item['mlid'], $item['menu_name']);
 634    while ($item = db_fetch_array($result)) {
 635      _menu_link_translate($item);
 636      if (!$item['access']) {
 637        continue;
 638      }
 639      // The link 'description' either derived from the hook_menu 'description' or
 640      // entered by the user via menu module is saved as the title attribute.
 641      if (!empty($item['localized_options']['attributes']['title'])) {
 642        $item['description'] = $item['localized_options']['attributes']['title'];
 643      }
 644      // Prepare for sorting as in function _menu_tree_check_access().
 645      // The weight is offset so it is always positive, with a uniform 5-digits.
 646      $content[(50000 + $item['weight']) .' '. drupal_strtolower($item['title']) .' '. $item['mlid']] = $item;
 647    }
 648    ksort($content);
 649    return $content;
 650  }
 651  
 652  /**
 653   * Process admin theme form submissions.
 654   */
 655  function system_admin_theme_submit($form, &$form_state) {
 656    // If we're changing themes, make sure the theme has its blocks initialized.
 657    if ($form_state['values']['admin_theme'] && $form_state['values']['admin_theme'] != variable_get('admin_theme', '0')) {
 658      $result = db_result(db_query("SELECT COUNT(*) FROM {blocks} WHERE theme = '%s'", $form_state['values']['admin_theme']));
 659      if (!$result) {
 660        system_initialize_theme_blocks($form_state['values']['admin_theme']);
 661      }
 662    }
 663  }
 664  
 665  /**
 666   * Returns a fieldset containing the theme select form.
 667   *
 668   * @param $description
 669   *    description of the fieldset
 670   * @param $default_value
 671   *    default value of theme radios
 672   * @param $weight
 673   *    weight of the fieldset
 674   * @return
 675   *    a form array
 676   */
 677  function system_theme_select_form($description = '', $default_value = '', $weight = 0) {
 678    if (user_access('select different theme')) {
 679      $enabled = array();
 680      $themes = list_themes();
 681  
 682      foreach ($themes as $theme) {
 683        if ($theme->status) {
 684          $enabled[] = $theme;
 685        }
 686      }
 687  
 688      if (count($enabled) > 1) {
 689        ksort($enabled);
 690  
 691        $form['themes'] = array(
 692          '#type' => 'fieldset',
 693          '#title' => t('Theme configuration'),
 694          '#description' => $description,
 695          '#collapsible' => TRUE,
 696          '#theme' => 'system_theme_select_form'
 697        );
 698  
 699        foreach ($enabled as $info) {
 700          // For the default theme, revert to an empty string so the user's theme updates when the site theme is changed.
 701          $info->key = $info->name == variable_get('theme_default', 'garland') ? '' : $info->name;
 702  
 703          $screenshot = NULL;
 704          $theme_key = $info->name;
 705          while ($theme_key) {
 706            if (file_exists($themes[$theme_key]->info['screenshot'])) {
 707              $screenshot = $themes[$theme_key]->info['screenshot'];
 708              break;
 709            }
 710            $theme_key = isset($themes[$theme_key]->info['base theme']) ? $themes[$theme_key]->info['base theme'] : NULL;
 711          }
 712  
 713          $screenshot = $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
 714  
 715          $form['themes'][$info->key]['screenshot'] = array('#value' => $screenshot);
 716          $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>' : ''));
 717          $options[$info->key] = '';
 718        }
 719  
 720        $form['themes']['theme'] = array('#type' => 'radios', '#options' => $options, '#default_value' => $default_value ? $default_value : '');
 721        $form['#weight'] = $weight;
 722        return $form;
 723      }
 724    }
 725  }
 726  
 727  /**
 728   * Checks the existence of the directory specified in $form_element. This
 729   * function is called from the system_settings form to check both the
 730   * file_directory_path and file_directory_temp directories. If validation
 731   * fails, the form element is flagged with an error from within the
 732   * file_check_directory function.
 733   *
 734   * @param $form_element
 735   *   The form element containing the name of the directory to check.
 736   */
 737  function system_check_directory($form_element) {
 738    file_check_directory($form_element['#value'], FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
 739    return $form_element;
 740  }
 741  
 742  /**
 743   * Retrieves the current status of an array of files in the system table.
 744   *
 745   * @param $files
 746   *   An array of files to check.
 747   * @param $type
 748   *   The type of the files.
 749   */
 750  function system_get_files_database(&$files, $type) {
 751    // Extract current files from database.
 752    $result = db_query("SELECT filename, name, type, status, throttle, schema_version FROM {system} WHERE type = '%s'", $type);
 753    while ($file = db_fetch_object($result)) {
 754      if (isset($files[$file->name]) && is_object($files[$file->name])) {
 755        $file->old_filename = $file->filename;
 756        foreach ($file as $key => $value) {
 757          if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
 758            $files[$file->name]->$key = $value;
 759          }
 760        }
 761      }
 762    }
 763  }
 764  
 765  /**
 766   * Prepare defaults for themes.
 767   *
 768   * @return
 769   *   An array of default themes settings.
 770   */
 771  function system_theme_default() {
 772    return array(
 773      'regions' => array(
 774        'left' => 'Left sidebar',
 775        'right' => 'Right sidebar',
 776        'content' => 'Content',
 777        'header' => 'Header',
 778        'footer' => 'Footer',
 779      ),
 780      'description' => '',
 781      'features' => array(
 782        'comment_user_picture',
 783        'favicon',
 784        'mission',
 785        'logo',
 786        'name',
 787        'node_user_picture',
 788        'search',
 789        'slogan',
 790        'primary_links',
 791        'secondary_links',
 792      ),
 793      'stylesheets' => array(
 794        'all' => array('style.css')
 795      ),
 796      'scripts' => array('script.js'),
 797      'screenshot' => 'screenshot.png',
 798      'php' => DRUPAL_MINIMUM_PHP,
 799    );
 800  }
 801  
 802  /**
 803   * Collect data about all currently available themes.
 804   *
 805   * @return
 806   *   Array of all available themes and their data.
 807   */
 808  function system_theme_data() {
 809    // Scan the installation theme .info files and their engines.
 810    $themes = _system_theme_data();
 811  
 812    // Extract current files from database.
 813    system_get_files_database($themes, 'theme');
 814  
 815    db_query("DELETE FROM {system} WHERE type = 'theme'");
 816  
 817    foreach ($themes as $theme) {
 818      if (!isset($theme->owner)) {
 819        $theme->owner = '';
 820      }
 821  
 822      db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0);
 823    }
 824  
 825    return $themes;
 826  }
 827  
 828  /**
 829   * Helper function to scan and collect theme .info data and their engines.
 830   *
 831   * @return
 832   *   An associative array of themes information.
 833   */
 834  function _system_theme_data() {
 835    static $themes_info = array();
 836  
 837    if (empty($themes_info)) {
 838      // Find themes
 839      $themes = drupal_system_listing('\.info$', 'themes');
 840      // Find theme engines
 841      $engines = drupal_system_listing('\.engine$', 'themes/engines');
 842  
 843      $defaults = system_theme_default();
 844  
 845      $sub_themes = array();
 846      // Read info files for each theme
 847      foreach ($themes as $key => $theme) {
 848        $themes[$key]->info = drupal_parse_info_file($theme->filename) + $defaults;
 849  
 850        // Invoke hook_system_info_alter() to give installed modules a chance to
 851        // modify the data in the .info files if necessary.
 852        drupal_alter('system_info', $themes[$key]->info, $themes[$key]);
 853  
 854        if (!empty($themes[$key]->info['base theme'])) {
 855          $sub_themes[] = $key;
 856        }
 857        if (empty($themes[$key]->info['engine'])) {
 858          $filename = dirname($themes[$key]->filename) .'/'. $themes[$key]->name .'.theme';
 859          if (file_exists($filename)) {
 860            $themes[$key]->owner = $filename;
 861            $themes[$key]->prefix = $key;
 862          }
 863        }
 864        else {
 865          $engine = $themes[$key]->info['engine'];
 866          if (isset($engines[$engine])) {
 867            $themes[$key]->owner = $engines[$engine]->filename;
 868            $themes[$key]->prefix = $engines[$engine]->name;
 869            $themes[$key]->template = TRUE;
 870          }
 871        }
 872  
 873        // Give the stylesheets proper path information.
 874        $pathed_stylesheets = array();
 875        foreach ($themes[$key]->info['stylesheets'] as $media => $stylesheets) {
 876          foreach ($stylesheets as $stylesheet) {
 877            $pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->filename) .'/'. $stylesheet;
 878          }
 879        }
 880        $themes[$key]->info['stylesheets'] = $pathed_stylesheets;
 881  
 882        // Give the scripts proper path information.
 883        $scripts = array();
 884        foreach ($themes[$key]->info['scripts'] as $script) {
 885          $scripts[$script] = dirname($themes[$key]->filename) .'/'. $script;
 886        }
 887        $themes[$key]->info['scripts'] = $scripts;
 888        // Give the screenshot proper path information.
 889        if (!empty($themes[$key]->info['screenshot'])) {
 890          $themes[$key]->info['screenshot'] = dirname($themes[$key]->filename) .'/'. $themes[$key]->info['screenshot'];
 891        }
 892      }
 893  
 894      // Now that we've established all our master themes, go back and fill in
 895      // data for subthemes.
 896      foreach ($sub_themes as $key) {
 897        $themes[$key]->base_themes = system_find_base_themes($themes, $key);
 898        // Don't proceed if there was a problem with the root base theme.
 899        if (!current($themes[$key]->base_themes)) {
 900          continue;
 901        }
 902        $base_key = key($themes[$key]->base_themes);
 903        foreach (array_keys($themes[$key]->base_themes) as $base_theme) {
 904          $themes[$base_theme]->sub_themes[$key] = $themes[$key]->info['name'];
 905        }
 906        // Copy the 'owner' and 'engine' over if the top level theme uses a
 907        // theme engine.
 908        if (isset($themes[$base_key]->owner)) {
 909          if (isset($themes[$base_key]->info['engine'])) {
 910            $themes[$key]->info['engine'] = $themes[$base_key]->info['engine'];
 911            $themes[$key]->owner = $themes[$base_key]->owner;
 912            $themes[$key]->prefix = $themes[$base_key]->prefix;
 913          }
 914          else {
 915            $themes[$key]->prefix = $key;
 916          }
 917        }
 918      }
 919  
 920      $themes_info = $themes;
 921    }
 922  
 923    return $themes_info;
 924  }
 925  
 926  /**
 927   * Find all the base themes for the specified theme.
 928   *
 929   * Themes can inherit templates and function implementations from earlier themes.
 930   *
 931   * @param $themes
 932   *   An array of available themes.
 933   * @param $key
 934   *   The name of the theme whose base we are looking for.
 935   * @param $used_keys
 936   *   A recursion parameter preventing endless loops.
 937   * @return
 938   *   Returns an array of all of the theme's ancestors; the first element's value
 939   *   will be NULL if an error occurred.
 940   */
 941  function system_find_base_themes($themes, $key, $used_keys = array()) {
 942    $base_key = $themes[$key]->info['base theme'];
 943    // Does the base theme exist?
 944    if (!isset($themes[$base_key])) {
 945      return array($base_key => NULL);
 946    }
 947  
 948    $current_base_theme = array($base_key => $themes[$base_key]->info['name']);
 949  
 950    // Is the base theme itself a child of another theme?
 951    if (isset($themes[$base_key]->info['base theme'])) {
 952      // Do we already know the base themes of this theme?
 953      if (isset($themes[$base_key]->base_themes)) {
 954        return $themes[$base_key]->base_themes + $current_base_theme;
 955      }
 956      // Prevent loops.
 957      if (!empty($used_keys[$base_key])) {
 958        return array($base_key => NULL);
 959      }
 960      $used_keys[$base_key] = TRUE;
 961      return system_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
 962    }
 963    // If we get here, then this is our parent theme.
 964    return $current_base_theme;
 965  }
 966  
 967  /**
 968   * This function has been deprecated in favor of system_find_base_themes().
 969   *
 970   * Recursive function to find the top level base theme. Themes can inherit
 971   * templates and function implementations from earlier themes.
 972   *
 973   * @param $themes
 974   *   An array of available themes.
 975   * @param $key
 976   *   The name of the theme whose base we are looking for.
 977   * @param $used_keys
 978   *   A recursion parameter preventing endless loops.
 979   * @return
 980   *   Returns the top level parent that has no ancestor or returns NULL if there isn't a valid parent.
 981   */
 982  function system_find_base_theme($themes, $key, $used_keys = array()) {
 983    $base_key = $themes[$key]->info['base theme'];
 984    // Does the base theme exist?
 985    if (!isset($themes[$base_key])) {
 986      return NULL;
 987    }
 988  
 989    // Is the base theme itself a child of another theme?
 990    if (isset($themes[$base_key]->info['base theme'])) {
 991      // Prevent loops.
 992      if (!empty($used_keys[$base_key])) {
 993        return NULL;
 994      }
 995      $used_keys[$base_key] = TRUE;
 996      return system_find_base_theme($themes, $base_key, $used_keys);
 997    }
 998    // If we get here, then this is our parent theme.
 999    return $base_key;
1000  }
1001  
1002  /**
1003   * Get a list of available regions from a specified theme.
1004   *
1005   * @param $theme_key
1006   *   The name of a theme.
1007   * @return
1008   *   An array of regions in the form $region['name'] = 'description'.
1009   */
1010  function system_region_list($theme_key) {
1011    static $list = array();
1012  
1013    if (!array_key_exists($theme_key, $list)) {
1014      $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key)));
1015      $list[$theme_key] = array_map('t', $info['regions']);
1016    }
1017  
1018    return $list[$theme_key];
1019  }
1020  
1021  /**
1022   * Get the name of the default region for a given theme.
1023   *
1024   * @param $theme
1025   *   The name of a theme.
1026   * @return
1027   *   A string that is the region name.
1028   */
1029  function system_default_region($theme) {
1030    $regions = array_keys(system_region_list($theme));
1031    return isset($regions[0]) ? $regions[0] : '';
1032  }
1033  
1034  /**
1035   * Assign an initial, default set of blocks for a theme.
1036   *
1037   * This function is called the first time a new theme is enabled. The new theme
1038   * gets a copy of the default theme's blocks, with the difference that if a
1039   * particular region isn't available in the new theme, the block is assigned
1040   * to the new theme's default region.
1041   *
1042   * @param $theme
1043   *   The name of a theme.
1044   */
1045  function system_initialize_theme_blocks($theme) {
1046    // Initialize theme's blocks if none already registered.
1047    if (!(db_result(db_query("SELECT COUNT(*) FROM {blocks} WHERE theme = '%s'", $theme)))) {
1048      $default_theme = variable_get('theme_default', 'garland');
1049      $regions = system_region_list($theme);
1050      $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
1051      while ($block = db_fetch_array($result)) {
1052        // If the region isn't supported by the theme, assign the block to the theme's default region.
1053        if (!array_key_exists($block['region'], $regions)) {
1054          $block['region'] = system_default_region($theme);
1055        }
1056        db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle, cache) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, %d)",
1057            $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle'], $block['cache']);
1058      }
1059    }
1060  }
1061  
1062  /**
1063   * Add default buttons to a form and set its prefix.
1064   *
1065   * @ingroup forms
1066   * @see system_settings_form_submit()
1067   * @param $form
1068   *   An associative array containing the structure of the form.
1069   * @return
1070   *   The form structure.
1071   */
1072  function system_settings_form($form) {
1073    $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
1074    $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
1075  
1076    if (!empty($_POST) && form_get_errors()) {
1077      drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
1078    }
1079    $form['#submit'][] = 'system_settings_form_submit';
1080    $form['#theme'] = 'system_settings_form';
1081    return $form;
1082  }
1083  
1084  /**
1085   * Execute the system_settings_form.
1086   *
1087   * If you want node type configure style handling of your checkboxes,
1088   * add an array_filter value to your form.
1089   */
1090  function system_settings_form_submit($form, &$form_state) {
1091    $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
1092  
1093    // Exclude unnecessary elements.
1094    unset($form_state['values']['submit'], $form_state['values']['reset'], $form_state['values']['form_id'], $form_state['values']['op'], $form_state['values']['form_token'], $form_state['values']['form_build_id']);
1095  
1096    foreach ($form_state['values'] as $key => $value) {
1097      if ($op == t('Reset to defaults')) {
1098        variable_del($key);
1099      }
1100      else {
1101        if (is_array($value) && isset($form_state['values']['array_filter'])) {
1102          $value = array_keys(array_filter($value));
1103        }
1104        variable_set($key, $value);
1105      }
1106    }
1107    if ($op == t('Reset to defaults')) {
1108      drupal_set_message(t('The configuration options have been reset to their default values.'));
1109    }
1110    else {
1111      drupal_set_message(t('The configuration options have been saved.'));
1112    }
1113  
1114    cache_clear_all();
1115    drupal_rebuild_theme_registry();
1116  }
1117  
1118  /**
1119   * Helper function to sort requirements.
1120   */
1121  function _system_sort_requirements($a, $b) {
1122    if (!isset($a['weight'])) {
1123      if (!isset($b['weight'])) {
1124        return strcmp($a['title'], $b['title']);
1125      }
1126      return -$b['weight'];
1127    }
1128    return isset($b['weight']) ? $a['weight'] - $b['weight'] : $a['weight'];
1129  }
1130  
1131  /**
1132   * Implementation of hook_node_type().
1133   *
1134   * Updates theme settings after a node type change.
1135   */
1136  function system_node_type($op, $info) {
1137    if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
1138      $old = 'toggle_node_info_'. $info->old_type;
1139      $new = 'toggle_node_info_'. $info->type;
1140  
1141      $theme_settings = variable_get('theme_settings', array());
1142      if (isset($theme_settings[$old])) {
1143        $theme_settings[$new] = $theme_settings[$old];
1144        unset($theme_settings[$old]);
1145        variable_set('theme_settings', $theme_settings);
1146      }
1147    }
1148  }
1149  
1150  /**
1151   * Generates a form array for a confirmation form.
1152   *
1153   * This function returns a complete form array for confirming an action. The
1154   * form contains a confirm button as well as a cancellation link that allows a
1155   * user to abort the action.
1156   *
1157   * If the submit handler for a form that implements confirm_form() is invoked,
1158   * the user successfully confirmed the action. You should never directly
1159   * inspect $_POST to see if an action was confirmed.
1160   *
1161   * Note - if the parameters $question, $description, $yes, or $no could contain
1162   * any user input (such as node titles or taxonomy terms), it is the
1163   * responsibility of the code calling confirm_form() to sanitize them first with
1164   * a function like check_plain() or filter_xss().
1165   *
1166   * @param $form
1167   *   Additional elements to add to the form; for example, hidden elements.
1168   * @param $question
1169   *   The question to ask the user (e.g. "Are you sure you want to delete the
1170   *   block <em>foo</em>?"). The page title will be set to this value.
1171   * @param $path
1172   *   The page to go to if the user cancels the action. This can be either:
1173   *   - A string containing a Drupal path.
1174   *   - An associative array with a 'path' key. Additional array values are
1175   *     passed as the $options parameter to l().
1176   *   If the 'destination' query parameter is set in the URL when viewing a
1177   *   confirmation form, that value will be used instead of $path.
1178   * @param $description
1179   *   Additional text to display. Defaults to t('This action cannot be undone.').
1180   * @param $yes
1181   *   A caption for the button that confirms the action (e.g. "Delete",
1182   *   "Replace", ...). Defaults to t('Confirm').
1183   * @param $no
1184   *   A caption for the link which cancels the action (e.g. "Cancel"). Defaults
1185   *   to t('Cancel').
1186   * @param $name
1187   *   The internal name used to refer to the confirmation item.
1188   *
1189   * @return
1190   *   The form array.
1191   */
1192  function confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm') {
1193    $description = isset($description) ? $description : t('This action cannot be undone.');
1194  
1195    // Prepare cancel link
1196    $query = $fragment = NULL;
1197    if (is_array($path)) {
1198      $query = isset($path['query']) ? $path['query'] : NULL;
1199      $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
1200      $path = isset($path['path']) ? $path['path'] : NULL;
1201    }
1202    $cancel = l($no ? $no : t('Cancel'), $path, array('query' => $query, 'fragment' => $fragment));
1203  
1204    drupal_set_title($question);
1205  
1206    // Confirm form fails duplication check, as the form values rarely change -- so skip it.
1207    $form['#skip_duplicate_check'] = TRUE;
1208  
1209    $form['#attributes'] = array('class' => 'confirmation');
1210    $form['description'] = array('#value' => $description);
1211    $form[$name] = array('#type' => 'hidden', '#value' => 1);
1212  
1213    $form['actions'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
1214    $form['actions']['submit'] = array('#type' => 'submit', '#value' => $yes ? $yes : t('Confirm'));
1215    $form['actions']['cancel'] = array('#value' => $cancel);
1216    $form['#theme'] = 'confirm_form';
1217    return $form;
1218  }
1219  
1220  /**
1221   * Determine if a user is in compact mode.
1222   */
1223  function system_admin_compact_mode() {
1224    global $user;
1225    return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get('admin_compact_mode', FALSE);
1226  }
1227  
1228  /**
1229   * Generate a list of tasks offered by a specified module.
1230   *
1231   * @param $module
1232   *   Module name.
1233   * @return
1234   *   An array of task links.
1235   */
1236  function system_get_module_admin_tasks($module) {
1237    static $items;
1238  
1239    $admin_access = user_access('administer permissions');
1240    $admin_tasks = array();
1241  
1242    if (!isset($items)) {
1243      $result = db_query("
1244         SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, ml.*
1245         FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE 'admin/%' AND hidden >= 0 AND module = 'system' AND m.number_parts > 2");
1246      $items = array();
1247      while ($item = db_fetch_array($result)) {
1248        _menu_link_translate($item);
1249        if ($item['access']) {
1250          $items[$item['router_path']] = $item;
1251        }
1252      }
1253    }
1254    $admin_tasks = array();
1255    $admin_task_count = 0;
1256    // Check for permissions.
1257    if (module_hook($module, 'perm') && $admin_access) {
1258      $admin_tasks[-1] = l(t('Configure permissions'), 'admin/user/permissions', array('fragment' => 'module-'. $module));
1259    }
1260  
1261    // Check for menu items that are admin links.
1262    if ($menu = module_invoke($module, 'menu')) {
1263      foreach (array_keys($menu) as $path) {
1264        if (isset($items[$path])) {
1265          $admin_tasks[$items[$path]['title'] . $admin_task_count ++] = l($items[$path]['title'], $path);
1266        }
1267      }
1268    }
1269  
1270    return $admin_tasks;
1271  }
1272  
1273  /**
1274   * Implementation of hook_cron().
1275   *
1276   * Remove older rows from flood and batch table. Remove old temporary files.
1277   */
1278  function system_cron() {
1279    // Cleanup the flood.
1280    db_query('DELETE FROM {flood} WHERE timestamp < %d', time() - 3600);
1281    // Cleanup the batch table.
1282    db_query('DELETE FROM {batch} WHERE timestamp < %d', time() - 864000);
1283  
1284    // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
1285    $result = db_query('SELECT * FROM {files} WHERE status = %d and timestamp < %d', FILE_STATUS_TEMPORARY, time() - DRUPAL_MAXIMUM_TEMP_FILE_AGE);
1286    while ($file = db_fetch_object($result)) {
1287      if (file_exists($file->filepath)) {
1288        // If files that exist cannot be deleted, continue so the database remains
1289        // consistent.
1290        if (!file_delete($file->filepath)) {
1291          watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->filepath), 'error');
1292          continue;
1293        }
1294      }
1295      db_query('DELETE FROM {files} WHERE fid = %d', $file->fid);
1296    }
1297    $core = array('cache', 'cache_block', 'cache_filter', 'cache_page', 'cache_form', 'cache_menu');
1298    $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
1299    foreach ($cache_tables as $table) {
1300      cache_clear_all(NULL, $table);
1301    }
1302  }
1303  
1304  /**
1305   * Implementation of hook_hook_info().
1306   */
1307  function system_hook_info() {
1308    return array(
1309      'system' => array(
1310        'cron' => array(
1311          'run' => array(
1312            'runs when' => t('When cron runs'),
1313          ),
1314        ),
1315      ),
1316    );
1317  }
1318  
1319  /**
1320   * Implementation of hook_action_info().
1321   */
1322  function system_action_info() {
1323    return array(
1324      'system_message_action' => array(
1325        'type' => 'system',
1326        'description' => t('Display a message to the user'),
1327        'configurable' => TRUE,
1328        'hooks' => array(
1329          'nodeapi' => array('view', 'insert', 'update', 'delete'),
1330          'comment' => array('view', 'insert', 'update', 'delete'),
1331          'user' => array('view', 'insert', 'update', 'delete', 'login'),
1332          'taxonomy' => array('insert', 'update', 'delete'),
1333        ),
1334      ),
1335      'system_send_email_action' => array(
1336        'description' => t('Send e-mail'),
1337        'type' => 'system',
1338        'configurable' => TRUE,
1339        'hooks' => array(
1340          'nodeapi' => array('view', 'insert', 'update', 'delete'),
1341          'comment' => array('view', 'insert', 'update', 'delete'),
1342          'user' => array('view', 'insert', 'update', 'delete', 'login'),
1343          'taxonomy' => array('insert', 'update', 'delete'),
1344        )
1345      ),
1346      'system_goto_action' => array(
1347        'description' => t('Redirect to URL'),
1348        'type' => 'system',
1349        'configurable' => TRUE,
1350        'hooks' => array(
1351          'nodeapi' => array('view', 'insert', 'update', 'delete'),
1352          'comment' => array('view', 'insert', 'update', 'delete'),
1353          'user' => array('view', 'insert', 'update', 'delete', 'login'),
1354        )
1355      )
1356    );
1357  }
1358  
1359  /**
1360   * Menu callback. Display an overview of available and configured actions.
1361   */
1362  function system_actions_manage() {
1363    $output = '';
1364    $actions = actions_list();
1365    actions_synchronize($actions);
1366    $actions_map = actions_actions_map($actions);
1367    $options = array(t('Choose an advanced action'));
1368    $unconfigurable = array();
1369  
1370    foreach ($actions_map as $key => $array) {
1371      if ($array['configurable']) {
1372        $options[$key] = $array['description'] .'...';
1373      }
1374      else {
1375        $unconfigurable[] = $array;
1376      }
1377    }
1378  
1379    $row = array();
1380    $instances_present = db_fetch_object(db_query("SELECT aid FROM {actions} WHERE parameters <> ''"));
1381    $header = array(
1382      array('data' => t('Action type'), 'field' => 'type'),
1383      array('data' => t('Description'), 'field' => 'description'),
1384      array('data' => $instances_present ? t('Operations') : '', 'colspan' => '2')
1385    );
1386    $sql = 'SELECT * FROM {actions}';
1387    $result = pager_query($sql . tablesort_sql($header), 50);
1388    while ($action = db_fetch_object($result)) {
1389      $row[] = array(
1390        array('data' => $action->type),
1391        array('data' => filter_xss_admin($action->description)),
1392        array('data' => $action->parameters ? l(t('configure'), "admin/settings/actions/configure/$action->aid") : ''),
1393        array('data' => $action->parameters ? l(t('delete'), "admin/settings/actions/delete/$action->aid") : '')
1394      );
1395    }
1396  
1397    if ($row) {
1398      $pager = theme('pager', NULL, 50, 0);
1399      if (!empty($pager)) {
1400        $row[] = array(array('data' => $pager, 'colspan' => '3'));
1401      }
1402      $output .= '<h3>'. t('Actions available to Drupal:') .'</h3>';
1403      $output .= theme('table', $header, $row);
1404    }
1405  
1406    if ($actions_map) {
1407      $output .= drupal_get_form('system_actions_manage_form', $options);
1408    }
1409  
1410    return $output;
1411  }
1412  
1413  /**
1414   * Define the form for the actions overview page.
1415   *
1416   * @see system_actions_manage_form_submit()
1417   * @ingroup forms
1418   * @param $form_state
1419   *   An associative array containing the current state of the form; not used.
1420   * @param $options
1421   *   An array of configurable actions.
1422   * @return
1423   *   Form definition.
1424   */
1425  function system_actions_manage_form($form_state, $options = array()) {
1426    $form['parent'] = array(
1427      '#type' => 'fieldset',
1428      '#title' => t('Make a new advanced action available'),
1429      '#prefix' => '<div class="container-inline">',
1430      '#suffix' => '</div>',
1431    );
1432    $form['parent']['action'] = array(
1433      '#type' => 'select',
1434      '#default_value' => '',
1435      '#options' => $options,
1436      '#description' => '',
1437    );
1438    $form['parent']['buttons']['submit'] = array(
1439      '#type' => 'submit',
1440      '#value' => t('Create'),
1441    );
1442    return $form;
1443  }
1444  
1445  /**
1446   * Process system_actions_manage form submissions.
1447   */
1448  function system_actions_manage_form_submit($form, &$form_state) {
1449    if ($form_state['values']['action']) {
1450      $form_state['redirect'] = 'admin/settings/actions/configure/'. $form_state['values']['action'];
1451    }
1452  }
1453  
1454  /**
1455   * Menu callback. Create the form for configuration of a single action.
1456   *
1457   * We provide the "Description" field. The rest of the form
1458   * is provided by the action. We then provide the Save button.
1459   * Because we are combining unknown form elements with the action
1460   * configuration form, we use actions_ prefix on our elements.
1461   *
1462   * @see system_actions_configure_validate()
1463   * @see system_actions_configure_submit()
1464   * @param $action
1465   *   md5 hash of action ID or an integer. If it's an md5 hash, we
1466   *   are creating a new instance. If it's an integer, we're editing
1467   *   an existing instance.
1468   * @return
1469   *   Form definition.
1470   */
1471  function system_actions_configure($form_state, $action = NULL) {
1472    if ($action === NULL) {
1473      drupal_goto('admin/settings/actions');
1474    }
1475  
1476    $actions_map = actions_actions_map(actions_list());
1477    $edit = array();
1478  
1479    // Numeric action denotes saved instance of a configurable action;
1480    // else we are creating a new action instance.
1481    if (is_numeric($action)) {
1482      $aid = $action;
1483      // Load stored parameter values from database.
1484      $data = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $aid));
1485      $edit['actions_description'] = $data->description;
1486      $edit['actions_type'] = $data->type;
1487      $function = $data->callback;
1488      $action = md5($data->callback);
1489      $params = unserialize($data->parameters);
1490      if ($params) {
1491        foreach ($params as $name => $val) {
1492          $edit[$name] = $val;
1493        }
1494      }
1495    }
1496    else {
1497      $function = $actions_map[$action]['callback'];
1498      $edit['actions_description'] = $actions_map[$action]['description'];
1499      $edit['actions_type'] = $actions_map[$action]['type'];
1500    }
1501  
1502    $form['actions_description'] = array(
1503      '#type' => 'textfield',
1504      '#title' => t('Description'),
1505      '#default_value' => $edit['actions_description'],
1506      '#maxlength' => '255',
1507      '#description' => t('A unique description for this advanced action. This description will be displayed in the interface of modules that integrate with actions, such as Trigger module.'),
1508      '#weight' => -10
1509    );
1510    $action_form = $function .'_form';
1511    $form = array_merge($form, $action_form($edit));
1512    $form['actions_type'] = array(
1513      '#type' => 'value',
1514      '#value' => $edit['actions_type'],
1515    );
1516    $form['actions_action'] = array(
1517      '#type' => 'hidden',
1518      '#value' => $action,
1519    );
1520    // $aid is set when configuring an existing action instance.
1521    if (isset($aid)) {
1522      $form['actions_aid'] = array(
1523        '#type' => 'hidden',
1524        '#value' => $aid,
1525      );
1526    }
1527    $form['actions_configured'] = array(
1528      '#type' => 'hidden',
1529      '#value' => '1',
1530    );
1531    $form['buttons']['submit'] = array(
1532      '#type' => 'submit',
1533      '#value' => t('Save'),
1534      '#weight' => 13
1535    );
1536  
1537    return $form;
1538  }
1539  
1540  /**
1541   * Validate system_actions_configure form submissions.
1542   */
1543  function system_actions_configure_validate($form, $form_state) {
1544    $function = actions_function_lookup($form_state['values']['actions_action']) .'_validate';
1545    // Hand off validation to the action.
1546    if (function_exists($function)) {
1547      $function($form, $form_state);
1548    }
1549  }
1550  
1551  /**
1552   * Process system_actions_configure form submissions.
1553   */
1554  function system_actions_configure_submit($form, &$form_state) {
1555    $function = actions_function_lookup($form_state['values']['actions_action']);
1556    $submit_function = $function .'_submit';
1557  
1558    // Action will return keyed array of values to store.
1559    $params = $submit_function($form, $form_state);
1560    $aid = isset($form_state['values']['actions_aid']) ? $form_state['values']['actions_aid'] : NULL;
1561  
1562    actions_save($function, $form_state['values']['actions_type'], $params, $form_state['values']['actions_description'], $aid);
1563    drupal_set_message(t('The action has been successfully saved.'));
1564  
1565    $form_state['redirect'] = 'admin/settings/actions/manage';
1566  }
1567  
1568  /**
1569   * Create the form for confirmation of deleting an action.
1570   *
1571   * @ingroup forms
1572   * @see system_actions_delete_form_submit()
1573   */
1574  function system_actions_delete_form($form_state, $action) {
1575  
1576    $form['aid'] = array(
1577      '#type' => 'hidden',
1578      '#value' => $action->aid,
1579    );
1580    return confirm_form($form,
1581      t('Are you sure you want to delete the action %action?', array('%action' => $action->description)),
1582      'admin/settings/actions/manage',
1583      t('This cannot be undone.'),
1584      t('Delete'), t('Cancel')
1585    );
1586  }
1587  
1588  /**
1589   * Process system_actions_delete form submissions.
1590   *
1591   * Post-deletion operations for action deletion.
1592   */
1593  function system_actions_delete_form_submit($form, &$form_state) {
1594    $aid = $form_state['values']['aid'];
1595    $action = actions_load($aid);
1596    actions_delete($aid);
1597    watchdog('user', 'Deleted action %aid (%action)', array('%aid' => $aid, '%action' => $action->description));
1598    drupal_set_message(t('Action %action was deleted', array('%action' => $action->description)));
1599    $form_state['redirect'] = 'admin/settings/actions/manage';
1600  }
1601  
1602  /**
1603   * Post-deletion operations for deleting action orphans.
1604   *
1605   * @param $orphaned
1606   *   An array of orphaned actions.
1607   */
1608  function system_action_delete_orphans_post($orphaned) {
1609    foreach ($orphaned as $callback) {
1610      drupal_set_message(t("Deleted orphaned action (%action).", array('%action' => $callback)));
1611    }
1612  }
1613  
1614  /**
1615   * Remove actions that are in the database but not supported by any enabled module.
1616   */
1617  function system_actions_remove_orphans() {
1618    actions_synchronize(actions_list(), TRUE);
1619    drupal_goto('admin/settings/actions/manage');
1620  }
1621  
1622  /**
1623   * Return a form definition so the Send email action can be configured.
1624   *
1625   * @see system_send_email_action_validate()
1626   * @see system_send_email_action_submit()
1627   * @param $context
1628   *   Default values (if we are editing an existing action instance).
1629   * @return
1630   *   Form definition.
1631   */
1632  function system_send_email_action_form($context) {
1633    // Set default values for form.
1634    if (!isset($context['recipient'])) {
1635      $context['recipient'] = '';
1636    }
1637    if (!isset($context['subject'])) {
1638      $context['subject'] = '';
1639    }
1640    if (!isset($context['message'])) {
1641      $context['message'] = '';
1642    }
1643  
1644    $form['recipient'] = array(
1645      '#type' => 'textfield',
1646      '#title' => t('Recipient'),
1647      '#default_value' => $context['recipient'],
1648      '#maxlength' => '254',
1649      '#description' => t('The email address to which the message should be sent OR enter %author if you would like to send an e-mail to the author of the original post.', array('%author' => '%author')),
1650    );
1651    $form['subject'] = array(
1652      '#type' => 'textfield',
1653      '#title' => t('Subject'),
1654      '#default_value' => $context['subject'],
1655      '#maxlength' => '254',
1656      '#description' => t('The subject of the message.'),
1657    );
1658    $form['message'] = array(
1659      '#type' => 'textarea',
1660      '#title' => t('Message'),
1661      '#default_value' => $context['message'],
1662      '#cols' => '80',
1663      '#rows' => '20',
1664      '#description' => t('The message that should be sent. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body. Not all variables will be available in all contexts.'),
1665    );
1666    return $form;
1667  }
1668  
1669  /**
1670   * Validate system_send_email_action form submissions.
1671   */
1672  function system_send_email_action_validate($form, $form_state) {
1673    $form_values = $form_state['values'];
1674    // Validate the configuration form.
1675    if (!valid_email_address($form_values['recipient']) && $form_values['recipient'] != '%author') {
1676      // We want the literal %author placeholder to be emphasized in the error message.
1677      form_set_error('recipient', t('Please enter a valid email address or %author.', array('%author' => '%author')));
1678    }
1679  }
1680  
1681  /**
1682   * Process system_send_email_action form submissions.
1683   */
1684  function system_send_email_action_submit($form, $form_state) {
1685    $form_values = $form_state['values'];
1686    // Process the HTML form to store configuration. The keyed array that
1687    // we return will be serialized to the database.
1688    $params = array(
1689      'recipient' => $form_values['recipient'],
1690      'subject'   => $form_values['subject'],
1691      'message'   => $form_values['message'],
1692    );
1693    return $params;
1694  }
1695  
1696  /**
1697   * Implementation of a configurable Drupal action. Sends an email.
1698   */
1699  function system_send_email_action($object, $context) {
1700    global $user;
1701  
1702    switch ($context['hook']) {
1703      case 'nodeapi':
1704        // Because this is not an action of type 'node' the node
1705        // will not be passed as $object, but it will still be available
1706        // in $context.
1707        $node = $context['node'];
1708        break;
1709      // The comment hook provides nid, in $context.
1710      case 'comment':
1711        $comment = $context['comment'];
1712        $node = node_load($comment->nid);
1713        break;
1714      case 'user':
1715        // Because this is not an action of type 'user' the user
1716        // object is not passed as $object, but it will still be available
1717        // in $context.
1718        $account = $context['account'];
1719        if (isset($context['node'])) {
1720          $node = $context['node'];
1721        }
1722        elseif ($context['recipient'] == '%author') {
1723          // If we don't have a node, we don't have a node author.
1724          watchdog('error', 'Cannot use %author token in this context.');
1725          return;
1726        }
1727        break;
1728      default:
1729        // We are being called directly.
1730        $node = $object;
1731    }
1732  
1733    $recipient = $context['recipient'];
1734  
1735    if (isset($node)) {
1736      if (!isset($account)) {
1737        $account = user_load(array('uid' => $node->uid));
1738      }
1739      if ($recipient == '%author') {
1740        $recipient = $account->mail;
1741      }
1742    }
1743  
1744    if (!isset($account)) {
1745      $account = $user;
1746  
1747    }
1748    $language = user_preferred_language($account);
1749    $params = array('account' => $account, 'object' => $object, 'context' => $context);
1750    if (isset($node)) {
1751      $params['node'] = $node;
1752    }
1753  
1754    if (drupal_mail('system', 'action_send_email', $recipient, $language, $params)) {
1755      watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient));
1756    }
1757    else {
1758      watchdog('error', 'Unable to send email to %recipient', array('%recipient' => $recipient));
1759    }
1760  }
1761  
1762  /**
1763   * Implementation of hook_mail().
1764   */
1765  function system_mail($key, &$message, $params) {
1766    $account = $params['account'];
1767    $context = $params['context'];
1768    $variables = array(
1769      '%site_name' => variable_get('site_name', 'Drupal'),
1770      '%username' => $account->name,
1771    );
1772    if ($context['hook'] == 'taxonomy') {
1773      $object = $params['object'];
1774      $vocabulary = taxonomy_vocabulary_load($object->vid);
1775      $variables += array(
1776        '%term_name' => $object->name,
1777        '%term_description' => $object->description,
1778        '%term_id' => $object->tid,
1779        '%vocabulary_name' => $vocabulary->name,
1780        '%vocabulary_description' => $vocabulary->description,
1781        '%vocabulary_id' => $vocabulary->vid,
1782      );
1783    }
1784  
1785    // Node-based variable translation is only available if we have a node.
1786    if (isset($params['node'])) {
1787      $node = $params['node'];
1788      $variables += array(
1789        '%uid' => $node->uid,
1790        '%node_url' => url('node/'. $node->nid, array('absolute' => TRUE)),
1791        '%node_type' => node_get_types('name', $node),
1792        '%title' => $node->title,
1793        '%teaser' => $node->teaser,
1794        '%body' => $node->body,
1795      );
1796    }
1797    $subject = strtr($context['subject'], $variables);
1798    $body = strtr(filter_xss_admin($context['message']), $variables);
1799    $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
1800    $message['body'][] = drupal_html_to_text($body);
1801  }
1802  
1803  function system_message_action_form($context) {
1804    $form['message'] = array(
1805      '#type' => 'textarea',
1806      '#title' => t('Message'),
1807      '#default_value' => isset($context['message']) ? $context['message'] : '',
1808      '#required' => TRUE,
1809      '#rows' => '8',
1810      '#description' => t('The message to be displayed to the current user. You may include the following variables: %site_name, %username, %node_url, %node_type, %title, %teaser, %body. Not all variables will be available in all contexts.'),
1811    );
1812    return $form;
1813  }
1814  
1815  function system_message_action_submit($form, $form_state) {
1816    return array('message' => $form_state['values']['message']);
1817  }
1818  
1819  /**
1820   * A configurable Drupal action. Sends a message to the current user's screen.
1821   */
1822  function system_message_action(&$object, $context = array()) {
1823    global $user;
1824    $variables = array(
1825      '%site_name' => variable_get('site_name', 'Drupal'),
1826      '%username' => $user->name ? $user->name : variable_get('anonymous', t('Anonymous')),
1827    );
1828  
1829    // This action can be called in any context, but if placeholders
1830    // are used a node object must be present to be the source
1831    // of substituted text.
1832    switch ($context['hook']) {
1833      case 'nodeapi':
1834        // Because this is not an action of type 'node' the node
1835        // will not be passed as $object, but it will still be available
1836        // in $context.
1837        $node = $context['node'];
1838        break;
1839      // The comment hook also provides the node, in context.
1840      case 'comment':
1841        $comment = $context['comment'];
1842        $node = node_load($comment->nid);
1843        break;
1844      case 'taxonomy':
1845        $vocabulary = taxonomy_vocabulary_load($object->vid);
1846        $variables = array_merge($variables, array(
1847          '%term_name' => check_plain($object->name),
1848          '%term_description' => filter_xss_admin($object->description),
1849          '%term_id' => $object->tid,
1850          '%vocabulary_name' => check_plain($vocabulary->name),
1851          '%vocabulary_description' => filter_xss_admin($vocabulary->description),
1852          '%vocabulary_id' => $vocabulary->vid,
1853          )
1854        );
1855        break;
1856      default:
1857        // We are being called directly.
1858        $node = $object;
1859    }
1860  
1861    if (isset($node) && is_object($node)) {
1862      $variables = array_merge($variables, array(
1863        '%uid' => $node->uid,
1864        '%node_url' => url('node/'. $node->nid, array('absolute' => TRUE)),
1865        '%node_type' => check_plain(node_get_types('name', $node)),
1866        '%title' => check_plain($node->title),
1867        '%teaser' => check_markup($node->teaser, $node->format, FALSE),
1868        '%body' => check_markup($node->body, $node->format, FALSE),
1869        )
1870      );
1871    }
1872    $context['message'] = strtr(filter_xss_admin($context['message']), $variables);
1873    drupal_set_message($context['message']);
1874  }
1875  
1876  /**
1877   * Implementation of a configurable Drupal action. Redirect user to a URL.
1878   */
1879  function system_goto_action_form($context) {
1880    $form['url'] = array(
1881      '#type' => 'textfield',
1882      '#title' => t('URL'),
1883      '#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like http://drupal.org.'),
1884      '#default_value' => isset($context['url']) ? $context['url'] : '',
1885      '#required' => TRUE,
1886    );
1887    return $form;
1888  }
1889  
1890  function system_goto_action_submit($form, $form_state) {
1891    return array(
1892      'url' => $form_state['values']['url']
1893    );
1894  }
1895  
1896  function system_goto_action($object, $context) {
1897    drupal_goto($context['url']);
1898  }
1899  
1900  /**
1901   * Generate an array of time zones and their local time&date.
1902   */
1903  function _system_zonelist() {
1904    $timestamp = time();
1905    $zonelist = array(-11, -10, -9.5, -9, -8, -7, -6, -5, -4.5, -4, -3.5, -3, -2.5, -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);
1906    $zones = array();
1907    foreach ($zonelist as $offset) {
1908      $zone = $offset * 3600;
1909      $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') .' O', $zone);
1910    }
1911    return $zones;
1912  }
1913  
1914  /**
1915   * Checks whether the server is capable of issuing HTTP requests.
1916   *
1917   * The function sets the drupal_http_request_fail system variable to TRUE if
1918   * drupal_http_request() does not work and then the system status report page
1919   * will contain an error.
1920   *
1921   * @return
1922   *  TRUE if this installation can issue HTTP requests.
1923   */
1924  function system_check_http_request() {
1925    // Try to get the content of the front page via drupal_http_request().
1926    $result = drupal_http_request(url('', array('absolute' => TRUE)), array(), 'GET', NULL, 0);
1927    // We only care that we get a http response - this means that Drupal
1928    // can make a http request.
1929    $works = isset($result->code) && ($result->code >= 100) && ($result->code < 600);
1930    variable_set('drupal_http_request_fails', !$works);
1931    return $works;
1932  }
1933  
1934  /**
1935   * Format the Powered by Drupal text.
1936   *
1937   * @ingroup themeable
1938   */
1939  function theme_system_powered_by($image_path) {
1940    $image = theme('image', $image_path, t('Powered by Drupal, an open source content management system'), t('Powered by Drupal, an open source content management system'));
1941    return l($image, 'http://drupal.org', array('html' => TRUE, 'absolute' => TRUE, 'external' => TRUE));
1942  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7