Index: system.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v retrieving revision 1.158 diff -u -r1.158 system.admin.inc --- modules/system/system.admin.inc 19 Jun 2009 20:35:05 -0000 1.158 +++ modules/system/system.admin.inc 3 Jul 2009 18:08:13 -0000 @@ -1241,6 +1241,14 @@ '#description' => t('Render all blocks on the default 404 (not found) page. Disabling blocks can help with performance but might leave users with a less functional site.'), '#default_value' => variable_get('site_404_blocks', 0) ); + $form['cron_safe_threshold'] = array( + '#type' => 'select', + '#title' => t('Automatically run cron'), + '#default_value' => variable_get('cron_safe_threshold', DRUPAL_DEFAULT_CRON_THRESHOLD), + '#options' => array(0 => t('Never')) + drupal_map_assoc(array(1,3600, 10800, 21600, 43200, 86400, 604800), 'format_interval'), + '#description' => t('When enabled, the site will check whether cron has been run in the configured interval and automatically run it upon the next page request. For more information visit the status report page.', array('@status-report-url' => url('admin/reports/status'))), + ); + $form['#validate'][] = 'system_site_information_settings_validate'; return system_settings_form($form); @@ -1264,6 +1272,11 @@ if (!empty($item) && !menu_valid_path($item)) { form_set_error('site_frontpage', t("The path '@path' is either invalid or you do not have access to it.", array('@path' => $item['link_path']))); } + // Clear cache when enabling or disabling the cron threshold + $cron_threshold = variable_get('cron_safe_threshold', DRUPAL_DEFAULT_CRON_THRESHOLD); + if(($cron_threshold > 0 && $form_state['input']['cron_safe_threshold'] == 0) || ($cron_threshold == 0 && $form_state['input']['cron_safe_threshold'] > 0)) { + cache_clear_all(); + } } /** Index: system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.718 diff -u -r1.718 system.module --- modules/system/system.module 1 Jul 2009 13:44:53 -0000 1.718 +++ modules/system/system.module 3 Jul 2009 18:43:12 -0000 @@ -42,6 +42,11 @@ define('DRUPAL_MAXIMUM_TEMP_FILE_AGE', 21600); /** + * Default interval between automatically ran cron task in seconds. + */ +define('DRUPAL_DEFAULT_CRON_THRESHOLD', 10800); + +/** * New users will be set to the default time zone at registration. */ define('DRUPAL_USER_TIMEZONE_DEFAULT', 0); @@ -476,6 +481,12 @@ 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); + $items['system/run-cron-image'] = array( + 'title' => 'Execute cron', + 'page callback' => 'system_run_cron_image', + 'access callback' => '_system_run_cron_image_access', + 'type' => MENU_CALLBACK, + ); $items['admin'] = array( 'title' => 'Administer', 'access arguments' => array('access administration pages'), @@ -2680,3 +2691,54 @@ return $local; } + +/** + * Implement hook_footer(). + * + * Adds triggers to run the cron via an image callback when the feature to run + * cron automatically is enabled. The image will always be loaded even when the + * threshold is not yet crossed to prevent troubles which could occur + * if the page is cached. + */ +function system_footer() { + if (_system_run_cron_image_access()) { + // GET the image callback with XMLHttpRequest, it will work only + // when Javascript is available + drupal_add_js('(function($){ $.get("'.url('system/run-cron-image').'"); })(jQuery);', array('type' => 'inline', 'scope' => 'header')); + // Image callback as HTML code for a graceful degradation when Javascript + // is not available + return ''; + } +} + +/** + * Menu page callback; executes the cron via an image callback. + */ +function system_run_cron_image() { + drupal_page_is_cacheable(FALSE); + + // Output a transparent 1x1 image to the browser + drupal_set_header('Content-Type', 'image/gif'); + echo "\x47\x49\x46\x38\x39\x61\x1\x0\x1\x0\x80\xff\x0\xc0\xc0\xc0\x0\x0\x0\x21\xf9\x4\x1\x0\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b"; + + // Run the cron automatically if it has never ran or threshold was crossed + $cron_last = variable_get('cron_last', NULL); + $cron_threshold = variable_get('cron_safe_threshold', DRUPAL_DEFAULT_CRON_THRESHOLD); + if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $cron_threshold)) { + drupal_cron_run(); + } + + exit; +} + +/** + * Checks if the feature to run cron automatically is enabled. + * + * Also used as a menu access callback for this feature. + * + * @return + * TRUE if the cron threshold is enabled, FALSE otherwise. + */ +function _system_run_cron_image_access() { + return variable_get('cron_safe_threshold', DRUPAL_DEFAULT_CRON_THRESHOLD) > 0; +}