| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php // $Id: cron.php,v 1.126.2.14 2008/10/13 21:45:24 stronk7 Exp $ 2 3 /// This script looks through all the module directories for cron.php files 4 /// and runs them. These files can contain cleanup functions, email functions 5 /// or anything that needs to be run on a regular basis. 6 /// 7 /// This file is best run from cron on the host system (ie outside PHP). 8 /// The script can either be invoked via the web server or via a standalone 9 /// version of PHP compiled for CGI. 10 /// 11 /// eg wget -q -O /dev/null 'http://moodle.somewhere.edu/admin/cron.php' 12 /// or php /web/moodle/admin/cron.php 13 set_time_limit(0); 14 $starttime = microtime(); 15 16 /// The following is a hack necessary to allow this script to work well 17 /// from the command line. 18 19 define('FULLME', 'cron'); 20 21 22 /// Do not set moodle cookie because we do not need it here, it is better to emulate session 23 $nomoodlecookie = true; 24 25 /// The current directory in PHP version 4.3.0 and above isn't necessarily the 26 /// directory of the script when run from the command line. The require_once() 27 /// would fail, so we'll have to chdir() 28 29 if (!isset($_SERVER['REMOTE_ADDR']) && isset($_SERVER['argv'][0])) { 30 chdir(dirname($_SERVER['argv'][0])); 31 } 32 33 require_once(dirname(__FILE__) . '/../config.php'); 34 require_once($CFG->libdir.'/adminlib.php'); 35 require_once($CFG->libdir.'/gradelib.php'); 36 37 /// Extra debugging (set in config.php) 38 if (!empty($CFG->showcronsql)) { 39 $db->debug = true; 40 } 41 if (!empty($CFG->showcrondebugging)) { 42 $CFG->debug = DEBUG_DEVELOPER; 43 $CFG->displaydebug = true; 44 } 45 46 /// extra safety 47 @session_write_close(); 48 49 /// check if execution allowed 50 if (isset($_SERVER['REMOTE_ADDR'])) { // if the script is accessed via the web. 51 if (!empty($CFG->cronclionly)) { 52 // This script can only be run via the cli. 53 print_error('cronerrorclionly', 'admin'); 54 exit; 55 } 56 // This script is being called via the web, so check the password if there is one. 57 if (!empty($CFG->cronremotepassword)) { 58 $pass = optional_param('password', '', PARAM_RAW); 59 if($pass != $CFG->cronremotepassword) { 60 // wrong password. 61 print_error('cronerrorpassword', 'admin'); 62 exit; 63 } 64 } 65 } 66 67 68 /// emulate normal session 69 $SESSION = new object(); 70 $USER = get_admin(); /// Temporarily, to provide environment for this script 71 72 /// ignore admins timezone, language and locale - use site deafult instead! 73 $USER->timezone = $CFG->timezone; 74 $USER->lang = ''; 75 $USER->theme = ''; 76 course_setup(SITEID); 77 78 /// send mime type and encoding 79 if (check_browser_version('MSIE')) { 80 //ugly IE hack to work around downloading instead of viewing 81 @header('Content-Type: text/html; charset=utf-8'); 82 echo "<xmp>"; //<pre> is not good enough for us here 83 } else { 84 //send proper plaintext header 85 @header('Content-Type: text/plain; charset=utf-8'); 86 } 87 88 /// no more headers and buffers 89 while(@ob_end_flush()); 90 91 /// increase memory limit (PHP 5.2 does different calculation, we need more memory now) 92 @raise_memory_limit('128M'); 93 94 /// Start output log 95 96 $timenow = time(); 97 98 mtrace("Server Time: ".date('r',$timenow)."\n\n"); 99 100 /// Run all cron jobs for each module 101 102 mtrace("Starting activity modules"); 103 get_mailer('buffer'); 104 if ($mods = get_records_select("modules", "cron > 0 AND (($timenow - lastcron) > cron) AND visible = 1 ")) { 105 foreach ($mods as $mod) { 106 $libfile = "$CFG->dirroot/mod/$mod->name/lib.php"; 107 if (file_exists($libfile)) { 108 include_once($libfile); 109 $cron_function = $mod->name."_cron"; 110 if (function_exists($cron_function)) { 111 mtrace("Processing module function $cron_function ...", ''); 112 $pre_dbqueries = null; 113 if (!empty($PERF->dbqueries)) { 114 $pre_dbqueries = $PERF->dbqueries; 115 $pre_time = microtime(1); 116 } 117 if ($cron_function()) { 118 if (! set_field("modules", "lastcron", $timenow, "id", $mod->id)) { 119 mtrace("Error: could not update timestamp for $mod->fullname"); 120 } 121 } 122 if (isset($pre_dbqueries)) { 123 mtrace("... used " . ($PERF->dbqueries - $pre_dbqueries) . " dbqueries"); 124 mtrace("... used " . (microtime(1) - $pre_time) . " seconds"); 125 } 126 /// Reset possible changes by modules to time_limit. MDL-11597 127 @set_time_limit(0); 128 mtrace("done."); 129 } 130 } 131 } 132 } 133 get_mailer('close'); 134 mtrace("Finished activity modules"); 135 136 mtrace("Starting blocks"); 137 if ($blocks = get_records_select("block", "cron > 0 AND (($timenow - lastcron) > cron) AND visible = 1")) { 138 // we will need the base class. 139 require_once($CFG->dirroot.'/blocks/moodleblock.class.php'); 140 foreach ($blocks as $block) { 141 $blockfile = $CFG->dirroot.'/blocks/'.$block->name.'/block_'.$block->name.'.php'; 142 if (file_exists($blockfile)) { 143 require_once($blockfile); 144 $classname = 'block_'.$block->name; 145 $blockobj = new $classname; 146 if (method_exists($blockobj,'cron')) { 147 mtrace("Processing cron function for ".$block->name.'....',''); 148 if ($blockobj->cron()) { 149 if (!set_field('block','lastcron',$timenow,'id',$block->id)) { 150 mtrace('Error: could not update timestamp for '.$block->name); 151 } 152 } 153 /// Reset possible changes by blocks to time_limit. MDL-11597 154 @set_time_limit(0); 155 mtrace('done.'); 156 } 157 } 158 159 } 160 } 161 mtrace('Finished blocks'); 162 163 mtrace('Starting admin reports'); 164 // Admin reports do not have a database table that lists them. Instead a 165 // report includes cron.php with function report_reportname_cron() if it wishes 166 // to be cronned. It is up to cron.php to handle e.g. if it only needs to 167 // actually do anything occasionally. 168 $reports = get_list_of_plugins($CFG->admin.'/report'); 169 foreach($reports as $report) { 170 $cronfile = $CFG->dirroot.'/'.$CFG->admin.'/report/'.$report.'/cron.php'; 171 if (file_exists($cronfile)) { 172 require_once($cronfile); 173 $cronfunction = 'report_'.$report.'_cron'; 174 mtrace('Processing cron function for '.$report.'...', ''); 175 $pre_dbqueries = null; 176 if (!empty($PERF->dbqueries)) { 177 $pre_dbqueries = $PERF->dbqueries; 178 $pre_time = microtime(true); 179 } 180 $cronfunction(); 181 if (isset($pre_dbqueries)) { 182 mtrace("... used " . ($PERF->dbqueries - $pre_dbqueries) . " dbqueries"); 183 mtrace("... used " . round(microtime(true) - $pre_time, 2) . " seconds"); 184 } 185 mtrace('done.'); 186 } 187 } 188 mtrace('Finished admin reports'); 189 190 if (!empty($CFG->langcache)) { 191 mtrace('Updating languages cache'); 192 get_list_of_languages(true); 193 } 194 195 mtrace('Removing expired enrolments ...', ''); // See MDL-8785 196 $timenow = time(); 197 $somefound = false; 198 // The preferred way saves memory, dmllib.php 199 // find courses where limited enrolment is enabled 200 global $CFG; 201 $rs_enrol = get_recordset_sql("SELECT ra.roleid, ra.userid, ra.contextid 202 FROM {$CFG->prefix}course c 203 INNER JOIN {$CFG->prefix}context cx ON cx.instanceid = c.id 204 INNER JOIN {$CFG->prefix}role_assignments ra ON ra.contextid = cx.id 205 WHERE cx.contextlevel = '".CONTEXT_COURSE."' 206 AND ra.timeend > 0 207 AND ra.timeend < '$timenow' 208 AND c.enrolperiod > 0 209 "); 210 while ($oldenrolment = rs_fetch_next_record($rs_enrol)) { 211 role_unassign($oldenrolment->roleid, $oldenrolment->userid, 0, $oldenrolment->contextid); 212 $somefound = true; 213 } 214 rs_close($rs_enrol); 215 if($somefound) { 216 mtrace('Done'); 217 } else { 218 mtrace('none found'); 219 } 220 221 222 mtrace('Starting main gradebook job ...'); 223 grade_cron(); 224 mtrace('done.'); 225 226 227 /// Run all core cron jobs, but not every time since they aren't too important. 228 /// These don't have a timer to reduce load, so we'll use a random number 229 /// to randomly choose the percentage of times we should run these jobs. 230 231 srand ((double) microtime() * 10000000); 232 $random100 = rand(0,100); 233 234 if ($random100 < 20) { // Approximately 20% of the time. 235 mtrace("Running clean-up tasks..."); 236 237 /// Unenrol users who haven't logged in for $CFG->longtimenosee 238 239 if ($CFG->longtimenosee) { // value in days 240 $cuttime = $timenow - ($CFG->longtimenosee * 3600 * 24); 241 $rs = get_recordset_sql ("SELECT id, userid, courseid 242 FROM {$CFG->prefix}user_lastaccess 243 WHERE courseid != ".SITEID." 244 AND timeaccess < $cuttime "); 245 while ($assign = rs_fetch_next_record($rs)) { 246 if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) { 247 if (role_unassign(0, $assign->userid, 0, $context->id)) { 248 mtrace("Deleted assignment for user $assign->userid from course $assign->courseid"); 249 } 250 } 251 } 252 rs_close($rs); 253 /// Execute the same query again, looking for remaining records and deleting them 254 /// if the user hasn't moodle/course:view in the CONTEXT_COURSE context (orphan records) 255 $rs = get_recordset_sql ("SELECT id, userid, courseid 256 FROM {$CFG->prefix}user_lastaccess 257 WHERE courseid != ".SITEID." 258 AND timeaccess < $cuttime "); 259 while ($assign = rs_fetch_next_record($rs)) { 260 if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) { 261 if (!has_capability('moodle/course:view', $context, $assign->userid)) { 262 delete_records('user_lastaccess', 'userid', $assign->userid, 'courseid', $assign->courseid); 263 mtrace("Deleted orphan user_lastaccess for user $assign->userid from course $assign->courseid"); 264 } 265 } 266 } 267 rs_close($rs); 268 } 269 flush(); 270 271 272 /// Delete users who haven't confirmed within required period 273 274 if (!empty($CFG->deleteunconfirmed)) { 275 $cuttime = $timenow - ($CFG->deleteunconfirmed * 3600); 276 $rs = get_recordset_sql ("SELECT id, firstname, lastname 277 FROM {$CFG->prefix}user 278 WHERE confirmed = 0 279 AND firstaccess > 0 280 AND firstaccess < $cuttime"); 281 while ($user = rs_fetch_next_record($rs)) { 282 if (delete_records('user', 'id', $user->id)) { 283 mtrace("Deleted unconfirmed user for ".fullname($user, true)." ($user->id)"); 284 } 285 } 286 rs_close($rs); 287 } 288 flush(); 289 290 291 /// Delete users who haven't completed profile within required period 292 293 if (!empty($CFG->deleteincompleteusers)) { 294 $cuttime = $timenow - ($CFG->deleteincompleteusers * 3600); 295 $rs = get_recordset_sql ("SELECT id, username 296 FROM {$CFG->prefix}user 297 WHERE confirmed = 1 298 AND lastaccess > 0 299 AND lastaccess < $cuttime 300 AND deleted = 0 301 AND (lastname = '' OR firstname = '' OR email = '')"); 302 while ($user = rs_fetch_next_record($rs)) { 303 if (delete_user($user)) { 304 mtrace("Deleted not fully setup user $user->username ($user->id)"); 305 } 306 } 307 rs_close($rs); 308 } 309 flush(); 310 311 312 /// Delete old logs to save space (this might need a timer to slow it down...) 313 314 if (!empty($CFG->loglifetime)) { // value in days 315 $loglifetime = $timenow - ($CFG->loglifetime * 3600 * 24); 316 if (delete_records_select("log", "time < '$loglifetime'")) { 317 mtrace("Deleted old log records"); 318 } 319 } 320 flush(); 321 322 323 /// Delete old cached texts 324 325 if (!empty($CFG->cachetext)) { // Defined in config.php 326 $cachelifetime = time() - $CFG->cachetext - 60; // Add an extra minute to allow for really heavy sites 327 if (delete_records_select('cache_text', "timemodified < '$cachelifetime'")) { 328 mtrace("Deleted old cache_text records"); 329 } 330 } 331 flush(); 332 333 if (!empty($CFG->notifyloginfailures)) { 334 notify_login_failures(); 335 mtrace('Notified login failured'); 336 } 337 flush(); 338 339 sync_metacourses(); 340 mtrace('Synchronised metacourses'); 341 342 // 343 // generate new password emails for users 344 // 345 mtrace('checking for create_password'); 346 if (count_records('user_preferences', 'name', 'create_password', 'value', '1')) { 347 mtrace('creating passwords for new users'); 348 $newusers = get_records_sql("SELECT u.id as id, u.email, u.firstname, 349 u.lastname, u.username, 350 p.id as prefid 351 FROM {$CFG->prefix}user u 352 JOIN {$CFG->prefix}user_preferences p ON u.id=p.userid 353 WHERE p.name='create_password' AND p.value=1 AND u.email !='' "); 354 355 foreach ($newusers as $newuserid => $newuser) { 356 $newuser->emailstop = 0; // send email regardless 357 // email user 358 if (setnew_password_and_mail($newuser)) { 359 // remove user pref 360 delete_records('user_preferences', 'id', $newuser->prefid); 361 } else { 362 trigger_error("Could not create and mail new user password!"); 363 } 364 } 365 } 366 367 if (!empty($CFG->usetags)) { 368 require_once($CFG->dirroot.'/tag/lib.php'); 369 tag_cron(); 370 mtrace ('Executed tag cron'); 371 } 372 373 // Accesslib stuff 374 cleanup_contexts(); 375 mtrace ('Cleaned up contexts'); 376 gc_cache_flags(); 377 mtrace ('Cleaned cache flags'); 378 // If you suspect that the context paths are somehow corrupt 379 // replace the line below with: build_context_path(true); 380 build_context_path(); 381 mtrace ('Built context paths'); 382 383 mtrace("Finished clean-up tasks..."); 384 385 } // End of occasional clean-up tasks 386 387 388 if (empty($CFG->disablescheduledbackups)) { // Defined in config.php 389 //Execute backup's cron 390 //Perhaps a long time and memory could help in large sites 391 @set_time_limit(0); 392 @raise_memory_limit("192M"); 393 if (function_exists('apache_child_terminate')) { 394 // if we are running from Apache, give httpd a hint that 395 // it can recycle the process after it's done. Apache's 396 // memory management is truly awful but we can help it. 397 @apache_child_terminate(); 398 } 399 if (file_exists("$CFG->dirroot/backup/backup_scheduled.php") and 400 file_exists("$CFG->dirroot/backup/backuplib.php") and 401 file_exists("$CFG->dirroot/backup/lib.php") and 402 file_exists("$CFG->libdir/blocklib.php")) { 403 include_once("$CFG->dirroot/backup/backup_scheduled.php"); 404 include_once("$CFG->dirroot/backup/backuplib.php"); 405 include_once("$CFG->dirroot/backup/lib.php"); 406 require_once ("$CFG->libdir/blocklib.php"); 407 mtrace("Running backups if required..."); 408 409 if (! schedule_backup_cron()) { 410 mtrace("ERROR: Something went wrong while performing backup tasks!!!"); 411 } else { 412 mtrace("Backup tasks finished."); 413 } 414 } 415 } 416 417 if (!empty($CFG->enablerssfeeds)) { //Defined in admin/variables page 418 include_once("$CFG->libdir/rsslib.php"); 419 mtrace("Running rssfeeds if required..."); 420 421 if ( ! cron_rss_feeds()) { 422 mtrace("Something went wrong while generating rssfeeds!!!"); 423 } else { 424 mtrace("Rssfeeds finished"); 425 } 426 } 427 428 /// Run the enrolment cron, if any 429 if (!($plugins = explode(',', $CFG->enrol_plugins_enabled))) { 430 $plugins = array($CFG->enrol); 431 } 432 require_once($CFG->dirroot .'/enrol/enrol.class.php'); 433 foreach ($plugins as $p) { 434 $enrol = enrolment_factory::factory($p); 435 if (method_exists($enrol, 'cron')) { 436 $enrol->cron(); 437 } 438 if (!empty($enrol->log)) { 439 mtrace($enrol->log); 440 } 441 unset($enrol); 442 } 443 444 /// Run the auth cron, if any 445 $auths = get_enabled_auth_plugins(); 446 447 mtrace("Running auth crons if required..."); 448 foreach ($auths as $auth) { 449 $authplugin = get_auth_plugin($auth); 450 if (method_exists($authplugin, 'cron')) { 451 mtrace("Running cron for auth/$auth..."); 452 $authplugin->cron(); 453 if (!empty($authplugin->log)) { 454 mtrace($authplugin->log); 455 } 456 } 457 unset($authplugin); 458 } 459 460 if (!empty($CFG->enablestats) and empty($CFG->disablestatsprocessing)) { 461 require_once($CFG->dirroot.'/lib/statslib.php'); 462 // check we're not before our runtime 463 $timetocheck = stats_get_base_daily() + $CFG->statsruntimestarthour*60*60 + $CFG->statsruntimestartminute*60; 464 465 if (time() > $timetocheck) { 466 // process configured number of days as max (defaulting to 31) 467 $maxdays = empty($CFG->statsruntimedays) ? 31 : abs($CFG->statsruntimedays); 468 if (stats_cron_daily($maxdays)) { 469 if (stats_cron_weekly()) { 470 if (stats_cron_monthly()) { 471 stats_clean_old(); 472 } 473 } 474 } 475 @set_time_limit(0); 476 } else { 477 mtrace('Next stats run after:'. userdate($timetocheck)); 478 } 479 } 480 481 // run gradebook import/export/report cron 482 if ($gradeimports = get_list_of_plugins('grade/import')) { 483 foreach ($gradeimports as $gradeimport) { 484 if (file_exists($CFG->dirroot.'/grade/import/'.$gradeimport.'/lib.php')) { 485 require_once($CFG->dirroot.'/grade/import/'.$gradeimport.'/lib.php'); 486 $cron_function = 'grade_import_'.$gradeimport.'_cron'; 487 if (function_exists($cron_function)) { 488 mtrace("Processing gradebook import function $cron_function ...", ''); 489 $cron_function; 490 } 491 } 492 } 493 } 494 495 if ($gradeexports = get_list_of_plugins('grade/export')) { 496 foreach ($gradeexports as $gradeexport) { 497 if (file_exists($CFG->dirroot.'/grade/export/'.$gradeexport.'/lib.php')) { 498 require_once($CFG->dirroot.'/grade/export/'.$gradeexport.'/lib.php'); 499 $cron_function = 'grade_export_'.$gradeexport.'_cron'; 500 if (function_exists($cron_function)) { 501 mtrace("Processing gradebook export function $cron_function ...", ''); 502 $cron_function; 503 } 504 } 505 } 506 } 507 508 if ($gradereports = get_list_of_plugins('grade/report')) { 509 foreach ($gradereports as $gradereport) { 510 if (file_exists($CFG->dirroot.'/grade/report/'.$gradereport.'/lib.php')) { 511 require_once($CFG->dirroot.'/grade/report/'.$gradereport.'/lib.php'); 512 $cron_function = 'grade_report_'.$gradereport.'_cron'; 513 if (function_exists($cron_function)) { 514 mtrace("Processing gradebook report function $cron_function ...", ''); 515 $cron_function; 516 } 517 } 518 } 519 } 520 521 // run any customized cronjobs, if any 522 // looking for functions in lib/local/cron.php 523 if (file_exists($CFG->dirroot.'/local/cron.php')) { 524 mtrace('Processing customized cron script ...', ''); 525 include_once($CFG->dirroot.'/local/cron.php'); 526 mtrace('done.'); 527 } 528 529 530 //Unset session variables and destroy it 531 @session_unset(); 532 @session_destroy(); 533 534 mtrace("Cron script completed correctly"); 535 536 $difftime = microtime_diff($starttime, microtime()); 537 mtrace("Execution took ".$difftime." seconds"); 538 539 /// finish the IE hack 540 if (check_browser_version('MSIE')) { 541 echo "</xmp>"; 542 } 543 544 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |