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