[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/admin/ -> cron.php (source)

   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  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7