? .DS_Store ? drupal_cron-19173-40-axyjo.patch ? drupal_cron-19173-43-axyjo.patch ? drupal_cron-19173-44-axyjo.patch ? drupal_cron-19173-47-axyjo.patch ? drupal_cron-19173-54-axyjo.patch ? drupal_cron-19173-55-axyjo.patch ? drupal_cron-19173-57-axyjo.patch ? drupal_cron-19173-59-axyjo.patch ? drupal_cron-19173-60-axyjo.patch ? drupal_cron-19173-61-axyjo.patch ? drupal_cron-19173-63-axyjo.patch ? drupal_cron-19173-66-axyjo.patch ? sites/default/files ? sites/default/private ? sites/default/settings.php Index: cron.php =================================================================== RCS file: /cvs/drupal/drupal/cron.php,v retrieving revision 1.42 diff -u -p -r1.42 cron.php --- cron.php 8 Feb 2009 20:27:51 -0000 1.42 +++ cron.php 5 Sep 2009 11:41:55 -0000 @@ -4,6 +4,8 @@ /** * @file * Handles incoming requests to fire off regularly-scheduled tasks (cron jobs). + * Takes one parameter, include or exclude, which contains a comma separated + * list of modules to either include or exclude from the cron run. */ /** @@ -14,7 +16,27 @@ define('DRUPAL_ROOT', getcwd()); include_once DRUPAL_ROOT . '/includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); if (isset($_GET['cron_key']) && variable_get('cron_key', 'drupal') == $_GET['cron_key']) { - drupal_cron_run(); + $include = (isset($_GET['include'])) ? $_GET['include'] : ''; + $exclude = (isset($_GET['exclude'])) ? $_GET['exclude'] : ''; + + if ($include && $exclude) { + watchdog('cron', t('Cron has been issued both the include and the exclude parameters.'), array(), WATCHDOG_ERROR); + return FALSE; + } + elseif ($include && !$exclude) { + $cron_param = $include; + $mode = 'include'; + } + elseif (!$include && $exclude) { + $cron_param = $exclude; + $mode = 'exclude'; + } + else { + $cron_param = NULL; + $mode = NULL; + } + + drupal_cron_run($cron_param, $mode); } else { watchdog('cron', 'Cron could not run because an invalid key was used.', array(), WATCHDOG_NOTICE); Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.982 diff -u -p -r1.982 common.inc --- includes/common.inc 5 Sep 2009 10:05:38 -0000 1.982 +++ includes/common.inc 5 Sep 2009 11:42:03 -0000 @@ -3744,11 +3744,25 @@ function drupal_page_set_cache() { } /** - * Executes a cron run when called + * Executes a cron run when called. + * + * If the function is called with no arguments, then cron for all modules is + * run. If only one argument is passed in, the result is FALSE. If both + * arguments are provided, then the function includes or excludes the modules + * specified in the first argument. + * + * @param $list + * A comma separated list of modules to act upon. + * @param $mode + * The mode of the operation. One of the following values are possible: + * - '' or NULL + * - 'include' + * - 'exclude' + * * @return - * Returns TRUE if ran successfully + * Returns TRUE if ran successfully. */ -function drupal_cron_run() { +function drupal_cron_run($list = NULL, $mode = NULL) { // Allow execution to continue even if the request gets canceled. @ignore_user_abort(TRUE); @@ -3764,7 +3778,7 @@ function drupal_cron_run() { // was not reset due to a database error. watchdog('cron', 'Cron has been running for more than an hour and is most likely stuck.', array(), WATCHDOG_ERROR); - // Release cron semaphore + // Release cron semaphore. variable_del('cron_semaphore'); } else { @@ -3773,23 +3787,63 @@ function drupal_cron_run() { } } else { - // Register shutdown callback + // Register shutdown callback. register_shutdown_function('drupal_cron_cleanup'); - // Lock cron semaphore + // Lock cron semaphore. variable_set('cron_semaphore', REQUEST_TIME); + // Create $cron_message so that it is defined. + $cron_message = ''; + + // Retrieve cron_last array to modify. + $cron_last = variable_get('cron_last', array()); + // Iterate through the modules calling their cron handlers (if any): - module_invoke_all('cron'); + if (!$list && !$mode) { + // No parameters were passed, so we're running all modules. + module_invoke_all('cron'); + foreach (module_implements('cron') as $module) { + $cron_last[$module] = REQUEST_TIME; + } + watchdog('cron', t('Cron run completed for all modules.'), array(), WATCHDOG_NOTICE); + } + elseif ($list) { + $module_list = module_implements('cron'); + $cron_modules = explode(',', $list); + $run_array = array(); + if ($mode == 'include') { + // Get only a list of modules that are specified AND enabled. + $run_array = array_intersect($module_list, $cron_modules); + } + elseif ($mode == 'exclude') { + // Get only a list of modules that are NOT specified but enabled. + $run_array = array_diff($module_list, $cron_modules); + } + if ($run_array) { + foreach ($run_array as $module) { + module_invoke($module, 'cron'); + $cron_last[$module] = REQUEST_TIME; + } + $msg = implode(', ', $run_array); + watchdog('cron', t('Cron run completed for modules: @ran.', array('@ran' => $msg)), array(), WATCHDOG_NOTICE); + } + else { + watchdog('cron', t('Cron did not run because no valid modules were specified.'), array(), WATCHDOG_ERROR); + } + } + else { + // Catch anything that's not covered already. + return FALSE; + } - // Record cron time - variable_set('cron_last', REQUEST_TIME); - watchdog('cron', 'Cron run completed.', array(), WATCHDOG_NOTICE); + // Record cron time for each module. + variable_set('cron_last', $cron_last); - // Release cron semaphore + // Release cron semaphore. variable_del('cron_semaphore'); - // Return TRUE so other functions can check if it did run successfully + // Return TRUE so other functions can check if it did run successfully. return TRUE; } } Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.157 diff -u -p -r1.157 module.inc --- includes/module.inc 24 Aug 2009 00:14:18 -0000 1.157 +++ includes/module.inc 5 Sep 2009 11:42:03 -0000 @@ -255,6 +255,9 @@ function module_enable($module_list, $di */ function module_disable($module_list) { $invoke_modules = array(); + + // Get the $cron_last variable so that we can remove the disabled modules. + $cron_last = variable_get('cron_last', array()); foreach ($module_list as $module) { if (module_exists($module)) { // Check if node_access table needs rebuilding. @@ -264,6 +267,7 @@ function module_disable($module_list) { module_load_install($module); module_invoke($module, 'disable'); + unset($cron_last[$module]); db_update('system') ->fields(array('status' => 0)) ->condition('type', 'module') @@ -274,6 +278,9 @@ function module_disable($module_list) { } } + // Store the cleaned-up version of $cron_last. + variable_set('cron_last', $cron_last); + if (!empty($invoke_modules)) { // Refresh the module list to exclude the disabled modules. module_list(TRUE); Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.383 diff -u -p -r1.383 system.install --- modules/system/system.install 29 Aug 2009 10:38:58 -0000 1.383 +++ modules/system/system.install 5 Sep 2009 11:42:08 -0000 @@ -160,9 +160,12 @@ function system_requirements($phase) { // Cron configuration help text. $help = $t('For more information, see the online handbook entry for configuring cron jobs.', array('@cron-handbook' => 'http://drupal.org/cron')); - // Determine when cron last ran. - $cron_last = variable_get('cron_last'); - if (!is_numeric($cron_last)) { + // Determine when cron last ran (even partially). + $cron_last_array = variable_get('cron_last'); + if (is_array($cron_last_array)) { + $cron_last = max($cron_last_array); + } + else { $cron_last = variable_get('install_time', 0); } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.784 diff -u -p -r1.784 system.module --- modules/system/system.module 1 Sep 2009 16:50:12 -0000 1.784 +++ modules/system/system.module 5 Sep 2009 11:42:12 -0000 @@ -3150,7 +3150,7 @@ function system_run_cron_image() { // Run cron automatically if it has never run or threshold was crossed. $cron_last = variable_get('cron_last', NULL); $cron_threshold = variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD); - if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $cron_threshold)) { + if (!isset($cron_last) || (REQUEST_TIME - min($cron_last) > $cron_threshold)) { // Lock cron threshold semaphore. variable_set('cron_threshold_semaphore', REQUEST_TIME); drupal_cron_run(); Index: modules/system/system.test =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.test,v retrieving revision 1.75 diff -u -p -r1.75 system.test --- modules/system/system.test 1 Sep 2009 16:50:12 -0000 1.75 +++ modules/system/system.test 5 Sep 2009 11:42:14 -0000 @@ -387,6 +387,51 @@ class CronRunTestCase extends DrupalWebT $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => 'cron_key=' . $key)); $this->assertResponse(200); + // Run cron with a single, valid include parameter. + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'include' => 'system'))); + $this->assertResponse(200); + + // Run cron with a single, valid exclude parameter. + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'exclude' => 'system'))); + $this->assertResponse(200); + + // Run cron with a single, invalid include parameter. + $name = $this->randomName(8); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'include' => $name))); + $this->assertResponse(200); + + // Run cron with a single, invalid exclude parameter. + $name = $this->randomName(8); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'exclude' => $name))); + $this->assertResponse(200); + + // Run cron with two include parameters where both are valid. + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'include' => 'system,node'))); + $this->assertResponse(200); + + // Run cron with two exclude parameters where both are valid. + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'exclude' => 'system,node'))); + $this->assertResponse(200); + + // Run cron with two include parameters where only one is valid. + $name = $this->randomName(8); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'include' => 'system,'.$name))); + $this->assertResponse(200); + + // Run cron with two exclude parameters where only one is valid. + $name = $this->randomName(8); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key, 'exclude' => 'system,'.$name))); + $this->assertResponse(200); + + /* + * We can test all of these much better once we get assertLogMessage() into + * DrupalWebTestCase (see issue #500394). + */ + + // Test $cron_last variable. + $cron_last = variable_get('cron_last'); + $this->assertTrue(is_array($cron_last), t('Make sure that $cron_last is an array.')); + // Execute cron directly. $this->assertTrue(drupal_cron_run(), t('Cron ran successfully.')); }