Note: You are currently viewing documentation for Moodle 3.3. Up-to-date documentation for the latest stable version of Moodle is probably available here: Plugin types.

Development:Plugin types: Difference between revisions

From MoodleDocs
 
Line 18: Line 18:
#* convert capability names like mod/quiz:attempt into the human readable version.
#* convert capability names like mod/quiz:attempt into the human readable version.
# Trigger the plugins' cron tasks.
# Trigger the plugins' cron tasks.
#* Request from Penny: implement proper scheduling, like:
#* Request from Penny: implement proper scheduling, like: http://paste.dollyfish.net.nz/5d39fa, http://paste.dollyfish.net.nz/1856a4, http://paste.dollyfish.net.nz/60ac39, http://git.mahara.org/?p=mahara.git;a=blob;f=htdocs/lib/cron.php;hb=HEAD
#** http://paste.dollyfish.net.nz/5d39fa
#** http://paste.dollyfish.net.nz/1856a4
#** http://paste.dollyfish.net.nz/60ac39
#** http://git.mahara.org/?p=mahara.git;a=blob;f=htdocs/lib/cron.php;h=master;hb=HEAD
# Go from prefix <-> path, e.g. qtype_multichoice <-> question/type/multichoice.
# Go from prefix <-> path, e.g. qtype_multichoice <-> question/type/multichoice.
# Let plugins of a particular type define extra admin settings.
# Let plugins of a particular type define extra admin settings.

Latest revision as of 08:54, 6 January 2009

These are notes to help me work out what to do for MDL-16438, MDL-13816 and how to do MDL-5106 without adding more junk to help.php (indeed it would be nice to refactor the special case code out of help.php!)

Other things to think about:

  • Third party module that wants its own sub-plugin type.
  • Non-plugin types like core/moodle and cron.

What we need to know about a plugin type

We need to be able to ...

  1. Install/upgrade plugins of that type.
    • Which possibly includes updating a list of plugins of this type in a DB table.
    • And which may include updating capability and event definitions.
    • Do we standardise things like post-instal/upgrade hooks?
  2. Respond to get_string('xxx', 'qtype_yyy'); calls, and the equivalent with help files.
  3. Get specific strings from the plugin, for example
    • get_string('modulenameplural', 'quiz'), get_string('addingmultichoice', 'qtype_multichoice');
    • convert capability names like mod/quiz:attempt into the human readable version.
  4. Trigger the plugins' cron tasks.
  5. Go from prefix <-> path, e.g. qtype_multichoice <-> question/type/multichoice.
  6. Let plugins of a particular type define extra admin settings.
  7. Have a page to manage all the plugins of a particular type - at the moment we only have this for certain types.
    • For example, do we make generic the notion of exabling and disabling plugins of a particular type.
  8. Print info about what is installed before upgrade - agina currently only done for three plugin types.

How much of this should be centralised, and how much is specific to particular plugin types?

Sanitised list of plugin types

Activity modules

Folder 'mod/'
Prefix ''
DB table 'modules'
Has DB Yes
Has caps Yes

Blocks

Folder 'blocks/'
Prefix 'block_'
DB table 'modules'
Has /db Yes
Has caps Yes

Admin reports

Assignment types

Authentication plugins

Blocks

Folder 'blocks/'
Prefix 'block_'
DB table 'modules'
Has /db Yes
Has caps Yes

Course formats

Course reports

Database fields

Database presets

Enrolment plugins

Filters

Gradebook plugins

Gradebook report

Gradebook export

Gradebook import

Portfolio Plugins

Question types

Question import/export formats

Quiz reports

Repository plugins

Resource types

Search engine adapters

Raw data

List from places_to_search_for_lang_strings

   return array(
       '__exceptions' => array('moodle', 'langconfig'),
       'assignment_' => array('mod/assignment/type'),
       'auth_' => array('auth'),
       'block_' => array('blocks'),
       'datafield_' => array('mod/data/field'),
       'datapreset_' => array('mod/data/preset'),
       'enrol_' => array('enrol'),
       'filter_' => array('filter'),
       'format_' => array('course/format'),
       'quiz_' => array('mod/quiz/report'),
       'qtype_' => array('question/type'),
       'qformat_' => array('question/format'),
       'report_' => array($CFG->admin.'/report', 'course/report'),
       'repository_'=>array('repository'),
       'resource_' => array('mod/resource/type'),
       'gradereport_' => array('grade/report'),
       'gradeimport_' => array('grade/import'),
       'gradeexport_' => array('grade/export'),
       'profilefield_' => array('user/profile/field'),
       'portfolio_' => array('portfolio/type'),
       '' => array('mod')

List from developer documentation index

Code from get_db_directories

/// First, the main one (lib/db)
   $dbdirs[] = $CFG->libdir.'/db';

/// Now, activity modules (mod/xxx/db)
   if ($plugins = get_list_of_plugins('mod')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/mod/'.$plugin.'/db';
       }
   }

/// Now, assignment submodules (mod/assignment/type/xxx/db)
   if ($plugins = get_list_of_plugins('mod/assignment/type')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/mod/assignment/type/'.$plugin.'/db';
       }
   }

/// Now, question types (question/type/xxx/db)
   if ($plugins = get_list_of_plugins('question/type')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/question/type/'.$plugin.'/db';
       }
   }

/// Now, backup/restore stuff (backup/db)
   $dbdirs[] = $CFG->dirroot.'/backup/db';

/// Now, block system stuff (blocks/db)
   $dbdirs[] = $CFG->dirroot.'/blocks/db';

/// Now, blocks (blocks/xxx/db)
   if ($plugins = get_list_of_plugins('blocks', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/blocks/'.$plugin.'/db';
       }
   }

/// Now, course formats (course/format/xxx/db)
   if ($plugins = get_list_of_plugins('course/format', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/course/format/'.$plugin.'/db';
       }
   }

/// Now, enrolment plugins (enrol/xxx/db)
   if ($plugins = get_list_of_plugins('enrol', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/enrol/'.$plugin.'/db';
       }
   }

/// Now admin report plugins (admin/report/xxx/db)
   if ($plugins = get_list_of_plugins($CFG->admin.'/report', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/'.$CFG->admin.'/report/'.$plugin.'/db';
       }
   }

/// Now quiz report plugins (mod/quiz/report/xxx/db)
   if ($plugins = get_list_of_plugins('mod/quiz/report', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot.'/mod/quiz/report/'.$plugin.'/db';
       }
   }

   if ($plugins = get_list_of_plugins('portfolio/type', 'db')) {
       foreach ($plugins as $plugin) {
           $dbdirs[] = $CFG->dirroot . '/portfolio/type/' . $plugin . '/db';
       }
   }

/// Local database changes, if the local folder exists.
   if (file_exists($CFG->dirroot . '/local')) {
       $dbdirs[] = $CFG->dirroot.'/local/db';
   }

   return $dbdirs;
}

Code from upgrade_db in adminlib.php

/// Find and check all main modules and load them up or upgrade them if necessary
/// first old *.php update and then the new upgrade.php script
   upgrade_activity_modules($return_url);  // Return here afterwards

/// Check all questiontype plugins and upgrade if necessary
/// first old *.php update and then the new upgrade.php script
/// It is important that this is done AFTER the quiz module has been upgraded
   upgrade_plugins('qtype', 'question/type', $return_url);  // Return here afterwards

/// Upgrade backup/restore system if necessary
/// first old *.php update and then the new upgrade.php script
   require_once("$CFG->dirroot/backup/lib.php");
   upgrade_backup_db($return_url);  // Return here afterwards

/// Upgrade blocks system if necessary
/// first old *.php update and then the new upgrade.php script
   require_once("$CFG->dirroot/lib/blocklib.php");
   upgrade_blocks_db($return_url);  // Return here afterwards

/// Check all blocks and load (or upgrade them if necessary)
/// first old *.php update and then the new upgrade.php script
   upgrade_blocks_plugins($return_url);  // Return here afterwards

/// Check all enrolment plugins and upgrade if necessary
/// first old *.php update and then the new upgrade.php script
   upgrade_plugins('enrol', 'enrol', $return_url);  // Return here afterwards

/// Check all auth plugins and upgrade if necessary
   upgrade_plugins('auth','auth',$return_url);

/// Check all course formats and upgrade if necessary
   upgrade_plugins('format','course/format',$return_url);

/// Check for local database customisations
/// first old *.php update and then the new upgrade.php script
   require_once("$CFG->dirroot/lib/locallib.php");
   upgrade_local_db($return_url);  // Return here afterwards

/// Check for changes to RPC functions
   require_once("$CFG->dirroot/$CFG->admin/mnet/adminlib.php");
   upgrade_RPC_functions($return_url);  // Return here afterwards

/// Upgrade all plugins for gradebook
   upgrade_plugins('gradeexport', 'grade/export', $return_url);
   upgrade_plugins('gradeimport', 'grade/import', $return_url);
   upgrade_plugins('gradereport', 'grade/report', $return_url);

/// Check all message output plugins and upgrade if necessary
   upgrade_plugins('message','message/output',$return_url);

/// Check all course report plugins and upgrade if necessary
   upgrade_plugins('coursereport', 'course/report', $return_url);

/// Check all admin report plugins and upgrade if necessary
   upgrade_plugins('report', $CFG->admin.'/report', $return_url);

/// Check all quiz report plugins and upgrade if necessary
   upgrade_plugins('quizreport', 'mod/quiz/report', $return_url);

/// Check all portfolio plugins and upgrade if necessary
   upgrade_plugins('portfolio', 'portfolio/type', $return_url);

/// Check all progress tracker plugins and upgrade if necessary
   upgrade_plugins('trackerexport', 'tracker/export', $return_url);
   upgrade_plugins('trackerimport', 'tracker/import', $return_url);
   upgrade_plugins('trackerreport', 'tracker/report', $return_url);

Code from eventslib.php

function events_load_def($component) {
   global $CFG;

   if ($component == 'moodle') {
       $defpath = $CFG->libdir.'/db/events.php';

   } else if ($component == 'unittest') {
       $defpath = $CFG->libdir.'/simpletest/fixtures/events.php';

   } else {
       $compparts = explode('/', $component);

       if ($compparts[0] == 'block') {
           // Blocks are an exception. Blocks directory is 'blocks', and not
           // 'block'. So we need to jump through hoops.
           $defpath = $CFG->dirroot.'/blocks/'.$compparts[1].'/db/events.php';

       } else if ($compparts[0] == 'format') {
           // Similar to the above, course formats are 'format' while they
           // are stored in 'course/format'.
           $defpath = $CFG->dirroot.'/course/format/'.$compparts[1].'/db/events.php';

       } else if ($compparts[0] == 'gradeimport') {
           $defpath = $CFG->dirroot.'/grade/import/'.$compparts[1].'/db/events.php';  
        
       } else if ($compparts[0] == 'gradeexport') {
           $defpath = $CFG->dirroot.'/grade/export/'.$compparts[1].'/db/events.php'; 
      
       } else if ($compparts[0] == 'gradereport') {
           $defpath = $CFG->dirroot.'/grade/report/'.$compparts[1].'/db/events.php'; 
       } else if ($compparts[0] == 'portfolio'){
           $defpath = $CFG->dirroot.'/portfolio/type/'.$compparts[1].'/db/events.php';
       } else {
           $defpath = $CFG->dirroot.'/'.$component.'/db/events.php';
       }
   }

   $handlers = array();

   if (file_exists($defpath)) {
       require($defpath);
   }

   return $handlers;
}

From accesslib.php

function get_capability_string($capabilityname) {

   // Typical capabilityname is mod/choice:readresponses

   $names = split('/', $capabilityname);
   $stringname = $names[1];                 // choice:readresponses
   $components = split(':', $stringname);
   $componentname = $components[0];               // choice

   switch ($names[0]) {
       case 'report':
           $string = get_string($stringname, 'report_'.$componentname);
       break;

       case 'mod':
           $string = get_string($stringname, $componentname);
       break;

       case 'block':
           $string = get_string($stringname, 'block_'.$componentname);
       break;

       case 'moodle':
           if ($componentname == 'local') {
               $string = get_string($stringname, 'local');
           } else {
               $string = get_string($stringname, 'role');
           }
       break;

       case 'enrol':
           $string = get_string($stringname, 'enrol_'.$componentname);
       break;

       case 'format':
           $string = get_string($stringname, 'format_'.$componentname);
       break;

       case 'gradeexport':
           $string = get_string($stringname, 'gradeexport_'.$componentname);
       break;

       case 'gradeimport':
           $string = get_string($stringname, 'gradeimport_'.$componentname);
       break;

       case 'gradereport':
           $string = get_string($stringname, 'gradereport_'.$componentname);
       break;

       case 'coursereport':
           $string = get_string($stringname, 'coursereport_'.$componentname);
       break;

       case 'quizreport':
           $string = get_string($stringname, 'quiz_'.$componentname);
       break;

       default:
           $string = get_string($stringname);
       break;

   }
   return $string;

}

admin/cron.php

/// Run all cron jobs for each module

   mtrace("Starting activity modules");
   get_mailer('buffer');
   if ($mods = $DB->get_records_select("modules", "cron > 0 AND ((? - lastcron) > cron) AND visible = 1", array($timenow))) {
       foreach ($mods as $mod) {
           $libfile = "$CFG->dirroot/mod/$mod->name/lib.php";
           if (file_exists($libfile)) {
               include_once($libfile);
               $cron_function = $mod->name."_cron";
               if (function_exists($cron_function)) {
                   mtrace("Processing module function $cron_function ...", );
                   $pre_dbqueries = null;
                   $pre_dbqueries = $DB->perf_get_queries();
                   $pre_time      = microtime(1);
                   if ($cron_function()) {
                       if (!$DB->set_field("modules", "lastcron", $timenow, array("id"=>$mod->id))) {
                           mtrace("Error: could not update timestamp for $mod->fullname");
                       }
                   }
                   if (isset($pre_dbqueries)) {
                       mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries");
                       mtrace("... used " . (microtime(1) - $pre_time) . " seconds");
                   }
               /// Reset possible changes by modules to time_limit. MDL-11597
                   @set_time_limit(0);
                   mtrace("done.");
               }
           }
       }
   }
   get_mailer('close');
   mtrace("Finished activity modules");
   mtrace("Starting blocks");
   if ($blocks = $DB->get_records_select("block", "cron > 0 AND ((? - lastcron) > cron) AND visible = 1", array($timenow))) {
       // we will need the base class.
       require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
       foreach ($blocks as $block) {
           $blockfile = $CFG->dirroot.'/blocks/'.$block->name.'/block_'.$block->name.'.php';
           if (file_exists($blockfile)) {
               require_once($blockfile);
               $classname = 'block_'.$block->name;
               $blockobj = new $classname; 
               if (method_exists($blockobj,'cron')) {
                   mtrace("Processing cron function for ".$block->name.'....',);
                   if ($blockobj->cron()) {
                       if (!$DB->set_field('block', 'lastcron', $timenow, array('id'=>$block->id))) {
                           mtrace('Error: could not update timestamp for '.$block->name);
                       }
                   }
               /// Reset possible changes by blocks to time_limit. MDL-11597
                   @set_time_limit(0);
                   mtrace('done.');
               }
           }
       }
   }
   mtrace('Finished blocks');
   mtrace("Starting quiz reports");
   if ($reports = $DB->get_records_select('quiz_report', "cron > 0 AND ((? - lastcron) > cron)", array($timenow))) {
       foreach ($reports as $report) {
           $cronfile = "$CFG->dirroot/mod/quiz/report/$report->name/cron.php";
           if (file_exists($cronfile)) {
               include_once($cronfile);
               $cron_function = 'quiz_report_'.$report->name."_cron";
               if (function_exists($cron_function)) {
                   mtrace("Processing quiz report cron function $cron_function ...", );
                   $pre_dbqueries = null;
                   $pre_dbqueries = $DB->perf_get_queries();
                   $pre_time      = microtime(1);
                   if ($cron_function()) {
                       if (!$DB->set_field('quiz_report', "lastcron", $timenow, array("id"=>$report->id))) {
                           mtrace("Error: could not update timestamp for $report->name");
                       }
                   }
                   if (isset($pre_dbqueries)) {
                       mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries");
                       mtrace("... used " . (microtime(1) - $pre_time) . " seconds");
                   }
                   mtrace("done.");
               }
           }
       }
   }
   mtrace("Finished quiz reports");
   
   mtrace('Starting admin reports');
   // Admin reports do not have a database table that lists them. Instead a
   // report includes cron.php with function report_reportname_cron() if it wishes
   // to be cronned. It is up to cron.php to handle e.g. if it only needs to
   // actually do anything occasionally.
   $reports = get_list_of_plugins($CFG->admin.'/report');
   foreach($reports as $report) {
       $cronfile = $CFG->dirroot.'/'.$CFG->admin.'/report/'.$report.'/cron.php';
       if (file_exists($cronfile)) {
           require_once($cronfile);
           $cronfunction = 'report_'.$report.'_cron';
           mtrace('Processing cron function for '.$report.'...', );
           $pre_dbqueries = null;
           $pre_dbqueries = $DB->perf_get_queries();
           $pre_time      = microtime(true);
           $cronfunction();
           if (isset($pre_dbqueries)) {
               mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries");
               mtrace("... used " . round(microtime(true) - $pre_time, 2) . " seconds");
           }
           mtrace('done.');
       }
   }
   mtrace('Finished admin reports');
   if (!empty($CFG->langcache)) {
       mtrace('Updating languages cache');
       get_list_of_languages(true);
   }
   mtrace('Removing expired enrolments ...', );     // See MDL-8785
   $timenow = time();
   $somefound = false;
   // The preferred way saves memory, datablib
   // find courses where limited enrolment is enabled
   $sql = "SELECT ra.roleid, ra.userid, ra.contextid
             FROM {course} c
             JOIN {context} cx ON cx.instanceid = c.id
             JOIN {role_assignments} ra ON ra.contextid = cx.id
            WHERE cx.contextlevel = '".CONTEXT_COURSE."'
                  AND ra.timeend > 0
                  AND ra.timeend < ?
                  AND c.enrolperiod > 0";
   if ($rs = $DB->get_recordset_sql($sql, array($timenow))) {
       foreach ($rs as $oldenrolment) {
           role_unassign($oldenrolment->roleid, $oldenrolment->userid, 0, $oldenrolment->contextid);
           $somefound = true;
       }
       $rs->close();
   }
   if ($somefound) {
       mtrace('Done');
   } else {
       mtrace('none found');
   }


   mtrace('Starting main gradebook job ...');
   grade_cron();
   mtrace('done.');


   mtrace('Starting processing the event queue...');
   events_cron();
   mtrace('done.');
   if ($CFG->enableportfolios) {
       // Portfolio cron
       mtrace('Starting the portfolio cron...');
       require_once($CFG->libdir . '/portfoliolib.php');
       portfolio_cron();
       mtrace('done');
   }

/// Run all core cron jobs, but not every time since they aren't too important. /// These don't have a timer to reduce load, so we'll use a random number /// to randomly choose the percentage of times we should run these jobs.

   srand ((double) microtime() * 10000000);
   $random100 = rand(0,100);
   if ($random100 < 20) {     // Approximately 20% of the time.
       mtrace("Running clean-up tasks...");
       /// Unenrol users who haven't logged in for $CFG->longtimenosee
       if ($CFG->longtimenosee) { // value in days
           $cuttime = $timenow - ($CFG->longtimenosee * 3600 * 24);
           $rs = $DB->get_recordset_sql ("SELECT id, userid, courseid
                                            FROM {user_lastaccess}
                                           WHERE courseid != ".SITEID."
                                                 AND timeaccess < ?", array($cuttime));
           foreach ($rs as $assign) {
               if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) {
                   if (role_unassign(0, $assign->userid, 0, $context->id)) {
                       mtrace("removing user $assign->userid from course $assign->courseid as they have not accessed the course for over $CFG->longtimenosee days");
                   }
               }
           }
           $rs->close();
       /// Execute the same query again, looking for remaining records and deleting them
       /// if the user hasn't moodle/course:view in the CONTEXT_COURSE context (orphan records)
           $rs = $DB->get_recordset_sql ("SELECT id, userid, courseid
                                            FROM {user_lastaccess}
                                           WHERE courseid != ".SITEID."
                                                 AND timeaccess < ?", array($cuttime));
           foreach ($rs as $assign) {
               if ($context = get_context_instance(CONTEXT_COURSE, $assign->courseid)) {
                   if (!has_capability('moodle/course:view', $context, $assign->userid)) {
                       $DB->delete_records('user_lastaccess', array('userid'=>$assign->userid, 'courseid'=>$assign->courseid));
                       mtrace("Deleted orphan user_lastaccess for user $assign->userid from course $assign->courseid");
                   }
               }
           }
           $rs->close();
       }
       flush();


       /// Delete users who haven't confirmed within required period
       if (!empty($CFG->deleteunconfirmed)) {
           $cuttime = $timenow - ($CFG->deleteunconfirmed * 3600);
           $rs = $DB->get_recordset_sql ("SELECT id, firstname, lastname
                                            FROM {user}
                                           WHERE confirmed = 0 AND firstaccess > 0
                                                 AND firstaccess < ?", array($cuttime));
           foreach ($rs as $user) {
               if ($DB->delete_records('user', array('id'=>$user->id))) {
                   mtrace("Deleted unconfirmed user for ".fullname($user, true)." ($user->id)");
               }
           }
           $rs->close();
       }
       flush();


       /// Delete users who haven't completed profile within required period
       if (!empty($CFG->deleteincompleteusers)) {
           $cuttime = $timenow - ($CFG->deleteincompleteusers * 3600);
           $rs = $DB->get_recordset_sql ("SELECT id, username
                                            FROM {user}
                                           WHERE confirmed = 1 AND lastaccess > 0
                                                 AND lastaccess < ? AND deleted = 0
                                                 AND (lastname =  OR firstname =  OR email = )",
                                         array($cuttime));
           foreach ($rs as $user) {
               if (delete_user($user)) {
                   mtrace("Deleted not fully setup user $user->username ($user->id)");
               }
           }
           $rs->close();
       }
       flush();


       /// Delete old logs to save space (this might need a timer to slow it down...)
       if (!empty($CFG->loglifetime)) {  // value in days
           $loglifetime = $timenow - ($CFG->loglifetime * 3600 * 24);
           if ($DB->delete_records_select("log", "time < ?", array($loglifetime))) {
               mtrace("Deleted old log records");
           }
       }
       flush();


       /// Delete old cached texts
       if (!empty($CFG->cachetext)) {   // Defined in config.php
           $cachelifetime = time() - $CFG->cachetext - 60;  // Add an extra minute to allow for really heavy sites
           if ($DB->delete_records_select('cache_text', "timemodified < ?", array($cachelifetime))) {
               mtrace("Deleted old cache_text records");
           }
       }
       flush();
       if (!empty($CFG->notifyloginfailures)) {
           notify_login_failures();
           mtrace('Notified login failured');
       }
       flush();
       sync_metacourses();
       mtrace('Synchronised metacourses');
       //
       // generate new password emails for users 
       //
       mtrace('checking for create_password');
       if ($DB->count_records('user_preferences', array('name'=>'create_password', 'value'=>'1'))) {
           mtrace('creating passwords for new users');
           $newusers = $DB->get_records_sql("SELECT u.id as id, u.email, u.firstname, 
                                                    u.lastname, u.username,
                                                    p.id as prefid 
                                               FROM {user} u 
                                               JOIN {user_preferences} p ON u.id=p.userid
                                              WHERE p.name='create_password' AND p.value=1 AND u.email != ");
           foreach ($newusers as $newuserid => $newuser) {
               $newuser->emailstop = 0; // send email regardless
               // email user                               
               if (setnew_password_and_mail($newuser)) {
                   // remove user pref
                   $DB->delete_records('user_preferences', array('id'=>$newuser->prefid));
               } else {
                   trigger_error("Could not create and mail new user password!");
               }
           }
       }
       
       if (!empty($CFG->usetags)) {
           require_once($CFG->dirroot.'/tag/lib.php');
           tag_cron();
           mtrace ('Executed tag cron');
       }
       
       // Accesslib stuff
       cleanup_contexts();
       mtrace ('Cleaned up contexts');
       gc_cache_flags();
       mtrace ('Cleaned cache flags');
       // If you suspect that the context paths are somehow corrupt
       // replace the line below with: build_context_path(true); 
       build_context_path();
       mtrace ('Built context paths');
       mtrace("Finished clean-up tasks...");
   } // End of occasional clean-up tasks


   if (empty($CFG->disablescheduledbackups)) {   // Defined in config.php
       //Execute backup's cron
       //Perhaps a long time and memory could help in large sites
       @set_time_limit(0);
       @raise_memory_limit("192M");
       if (function_exists('apache_child_terminate')) {
           // if we are running from Apache, give httpd a hint that 
           // it can recycle the process after it's done. Apache's 
           // memory management is truly awful but we can help it.
           @apache_child_terminate();
       }
       if (file_exists("$CFG->dirroot/backup/backup_scheduled.php") and
           file_exists("$CFG->dirroot/backup/backuplib.php") and
           file_exists("$CFG->dirroot/backup/lib.php") and
           file_exists("$CFG->libdir/blocklib.php")) {
           include_once("$CFG->dirroot/backup/backup_scheduled.php");
           include_once("$CFG->dirroot/backup/backuplib.php");
           include_once("$CFG->dirroot/backup/lib.php");
           require_once ("$CFG->libdir/blocklib.php");
           mtrace("Running backups if required...");
   
           if (! schedule_backup_cron()) {
               mtrace("ERROR: Something went wrong while performing backup tasks!!!");
           } else {
               mtrace("Backup tasks finished.");
           }
       }
   }
   if (!empty($CFG->enablerssfeeds)) {  //Defined in admin/variables page
       include_once("$CFG->libdir/rsslib.php");
       mtrace("Running rssfeeds if required...");
       if ( ! cron_rss_feeds()) {
           mtrace("Something went wrong while generating rssfeeds!!!");
       } else {
           mtrace("Rssfeeds finished");
       }
   }

/// Run the enrolment cron, if any

   if (!($plugins = explode(',', $CFG->enrol_plugins_enabled))) {
       $plugins = array($CFG->enrol);
   }
   require_once($CFG->dirroot .'/enrol/enrol.class.php');
   foreach ($plugins as $p) {
       $enrol = enrolment_factory::factory($p);
       if (method_exists($enrol, 'cron')) {
           $enrol->cron();
       }
       if (!empty($enrol->log)) {
           mtrace($enrol->log);
       }
       unset($enrol);
   }

/// Run the auth cron, if any

   $auths = get_enabled_auth_plugins();
   mtrace("Running auth crons if required...");
   foreach ($auths as $auth) {
       $authplugin = get_auth_plugin($auth);
       if (method_exists($authplugin, 'cron')) {
           mtrace("Running cron for auth/$auth...");
           $authplugin->cron();
           if (!empty($authplugin->log)) {
               mtrace($authplugin->log);
           }
       }
       unset($authplugin);
   }
   if (!empty($CFG->enablestats) and empty($CFG->disablestatsprocessing)) {
       require_once($CFG->dirroot.'/lib/statslib.php');
       // check we're not before our runtime
       $timetocheck = stats_get_base_daily() + $CFG->statsruntimestarthour*60*60 + $CFG->statsruntimestartminute*60;
       if (time() > $timetocheck) {
           // process configured number of days as max (defaulting to 31)
           $maxdays = empty($CFG->statsruntimedays) ? 31 : abs($CFG->statsruntimedays);
           if (stats_cron_daily($maxdays)) {
               if (stats_cron_weekly()) {
                   if (stats_cron_monthly()) {
                       stats_clean_old();
                   }
               }
           }
           @set_time_limit(0);
       } else {
           mtrace('Next stats run after:'. userdate($timetocheck));
       }
   }
   // run gradebook import/export/report cron
   if ($gradeimports = get_list_of_plugins('grade/import')) {
       foreach ($gradeimports as $gradeimport) {           
           if (file_exists($CFG->dirroot.'/grade/import/'.$gradeimport.'/lib.php')) {
               require_once($CFG->dirroot.'/grade/import/'.$gradeimport.'/lib.php');
               $cron_function = 'grade_import_'.$gradeimport.'_cron';                                    
               if (function_exists($cron_function)) {
                   mtrace("Processing gradebook import function $cron_function ...", );
                   $cron_function;  
               }
           }
       }      
   }
   if ($gradeexports = get_list_of_plugins('grade/export')) {
       foreach ($gradeexports as $gradeexport) {           
           if (file_exists($CFG->dirroot.'/grade/export/'.$gradeexport.'/lib.php')) {
               require_once($CFG->dirroot.'/grade/export/'.$gradeexport.'/lib.php');
               $cron_function = 'grade_export_'.$gradeexport.'_cron';                                    
               if (function_exists($cron_function)) {
                   mtrace("Processing gradebook export function $cron_function ...", );
                   $cron_function;  
               }
           }
       }
   }
   if ($gradereports = get_list_of_plugins('grade/report')) {
       foreach ($gradereports as $gradereport) {           
           if (file_exists($CFG->dirroot.'/grade/report/'.$gradereport.'/lib.php')) {
               require_once($CFG->dirroot.'/grade/report/'.$gradereport.'/lib.php');
               $cron_function = 'grade_report_'.$gradereport.'_cron';                                    
               if (function_exists($cron_function)) {
                   mtrace("Processing gradebook report function $cron_function ...", );
                   $cron_function;  
               }
           }
       }
   }
   
   // run any customized cronjobs, if any
   // looking for functions in lib/local/cron.php
   if (file_exists($CFG->dirroot.'/local/cron.php')) {
       mtrace('Processing customized cron script ...', );
       include_once($CFG->dirroot.'/local/cron.php');
       mtrace('done.');
   }