MDL-29670 cron cleanup and minor fixing
authorPetr Skoda <commits@skodak.org>
Sat, 22 Oct 2011 12:28:18 +0000 (14:28 +0200)
committerPetr Skoda <commits@skodak.org>
Sat, 22 Oct 2011 12:31:18 +0000 (14:31 +0200)
Auth and enrol is moved to the top because other plugin types depend on accurate user list and enrolments. Passwords and failed login messages are generated during every cron execution.  Contexts are build properly in each execution. Fixed deleting of unconfirmed users. And minor phpdocs and comments improvements.

lib/cronlib.php
lib/messagelib.php
lib/moodlelib.php
message/lib.php

index 22cef4c..e27e52a 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
@@ -24,6 +23,9 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+/**
+ * Execute cron tasks
+ */
 function cron_run() {
     global $DB, $CFG, $OUTPUT;
 
@@ -51,26 +53,195 @@ function cron_run() {
     set_time_limit(0);
     $starttime = microtime();
 
-/// increase memory limit
+    // Increase memory limit
     raise_memory_limit(MEMORY_EXTRA);
 
-/// emulate normal session
+    // Emulate normal session - we use admin accoutn by default
     cron_setup_user();
 
-/// Start output log
-
+    // Start output log
     $timenow  = time();
-
     mtrace("Server Time: ".date('r',$timenow)."\n\n");
 
 
-/// Session gc
+    // Run cleanup 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...");
+
+        // Delete users who haven't confirmed within required period
+        if (!empty($CFG->deleteunconfirmed)) {
+            $cuttime = $timenow - ($CFG->deleteunconfirmed * 3600);
+            $rs = $DB->get_recordset_sql ("SELECT *
+                                             FROM {user}
+                                            WHERE confirmed = 0 AND firstaccess > 0
+                                                  AND firstaccess < ?", array($cuttime));
+            foreach ($rs as $user) {
+                delete_user($user); // we MUST delete user properly first
+                $DB->delete_records('user', array('id'=>$user->id)); // this is a bloody hack, but it might work
+                mtrace(" Deleted unconfirmed user for ".fullname($user, true)." ($user->id)");
+            }
+            $rs->close();
+        }
+
+
+        // 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 *
+                                             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) {
+                delete_user($user);
+                mtrace(" Deleted not fully setup user $user->username ($user->id)");
+            }
+            $rs->close();
+        }
+
+
+        // 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);
+            $DB->delete_records_select("log", "time < ?", array($loglifetime));
+            mtrace(" Deleted old log records");
+        }
+
+
+        // Delete old backup_controllers and logs
+        if (!empty($CFG->loglifetime)) {  // value in days
+            $loglifetime = $timenow - ($CFG->loglifetime * 3600 * 24);
+            // Delete child records from backup_logs
+            $DB->execute("DELETE FROM {backup_logs}
+                           WHERE EXISTS (
+                               SELECT 'x'
+                                 FROM {backup_controllers} bc
+                                WHERE bc.backupid = {backup_logs}.backupid
+                                  AND bc.timecreated < ?)", array($loglifetime));
+            // Delete records from backup_controllers
+            $DB->execute("DELETE FROM {backup_controllers}
+                          WHERE timecreated < ?", array($loglifetime));
+            mtrace(" Deleted old backup records");
+        }
+
+
+        // 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
+            $DB->delete_records_select('cache_text', "timemodified < ?", array($cachelifetime));
+            mtrace(" Deleted old cache_text records");
+        }
+
+
+        if (!empty($CFG->usetags)) {
+            require_once($CFG->dirroot.'/tag/lib.php');
+            tag_cron();
+            mtrace(' Executed tag cron');
+        }
+
+
+        // Context maintenance stuff
+        context_helper::cleanup_instances();
+        mtrace(' Cleaned up context instances');
+        context_helper::build_all_paths(false);
+        // If you suspect that the context paths are somehow corrupt
+        // replace the line below with: context_helper::build_all_paths(true);
+        mtrace(' Built context paths');
+
+
+        // Remove expired cache flags
+        gc_cache_flags();
+        mtrace(' Cleaned cache flags');
+
+
+        // Cleanup messaging
+        if (!empty($CFG->messagingdeletereadnotificationsdelay)) {
+            $notificationdeletetime = time() - $CFG->messagingdeletereadnotificationsdelay;
+            $DB->delete_records_select('message_read', 'notification=1 AND timeread<:notificationdeletetime', array('notificationdeletetime'=>$notificationdeletetime));
+            mtrace(' Cleaned up read notifications');
+        }
+
+        mtrace("...finished clean-up tasks");
+
+    } // End of occasional clean-up tasks
+
+
+    // Send login failures notification - brute force protection in moodle is weak,
+    // we should at least send notices early in each cron execution
+    if (!empty($CFG->notifyloginfailures)) {
+        notify_login_failures();
+        mtrace(' Notified login failured');
+    }
+
+
+    // Make sure all context instances are properly created - they may be required in auth, enrol, etc.
+    context_helper::create_instances();
+    mtrace(' Created missing context instances');
+
 
-    mtrace("Cleaning up stale sessions");
+    // Session gc
     session_gc();
+    mtrace("Cleaned up stale user sessions");
 
-/// Run all cron jobs for each module
 
+    // Run the auth cron, if any before enrolments
+    // because it might add users that will be needed in enrol plugins
+    $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);
+    }
+    // Generate new password emails for users - ppl expect these generated asap
+    if ($DB->count_records('user_preferences', array('name'=>'create_password', 'value'=>'1'))) {
+        mtrace('Creating passwords for new users...');
+        $newusers = $DB->get_recordset_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 $newuser) {
+            if (setnew_password_and_mail($newuser)) {
+                unset_user_preference('create_password', $newuser);
+                set_user_preference('auth_forcepasswordchange', 1, $newuser);
+            } else {
+                trigger_error("Could not create and mail new user password!");
+            }
+        }
+        $newusers->close();
+    }
+
+
+    // It is very important to run enrol early
+    // because other plugins depend on correct enrolment info.
+    mtrace("Running enrol crons if required...");
+    $enrols = enrol_get_plugins(true);
+    foreach($enrols as $ename=>$enrol) {
+        // do this for all plugins, disabled plugins might want to cleanup stuff such as roles
+        if (!$enrol->is_cron_required()) {
+            continue;
+        }
+        mtrace("Running cron for enrol_$ename...");
+        $enrol->cron();
+        $enrol->set_config('lastcron', time());
+    }
+
+
+    // 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))) {
@@ -91,7 +262,7 @@ function cron_run() {
                         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
+                    // Reset possible changes by modules to time_limit. MDL-11597
                     @set_time_limit(0);
                     mtrace("done.");
                 }
@@ -101,9 +272,10 @@ function cron_run() {
     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.
+        // 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';
@@ -116,7 +288,7 @@ function cron_run() {
                     if ($blockobj->cron()) {
                         $DB->set_field('block', 'lastcron', $timenow, array('id'=>$block->id));
                     }
-                /// Reset possible changes by blocks to time_limit. MDL-11597
+                    // Reset possible changes by blocks to time_limit. MDL-11597
                     @set_time_limit(0);
                     mtrace('done.');
                 }
@@ -126,6 +298,8 @@ function cron_run() {
     }
     mtrace('Finished blocks');
 
+
+    //TODO: get rid of this bloody hardcoded quiz module stuff, this must be done from quiz_cron()!
     mtrace("Starting quiz reports");
     if ($reports = $DB->get_records_select('quiz_reports', "cron > 0 AND ((? - lastcron) > cron)", array($timenow))) {
         foreach ($reports as $report) {
@@ -152,11 +326,13 @@ function cron_run() {
     }
     mtrace("Finished quiz reports");
 
+
     mtrace('Starting admin reports');
     cron_execute_plugin_type('report');
     mtrace('Finished admin reports');
 
-    mtrace('Starting main gradebook job ...');
+
+    mtrace('Starting main gradebook job...');
     grade_cron();
     mtrace('done.');
 
@@ -183,215 +359,17 @@ function cron_run() {
         mtrace('done');
     }
 
+
     //now do plagiarism checks
     require_once($CFG->libdir.'/plagiarismlib.php');
     plagiarism_cron();
 
-/// 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...");
-
-        /// 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 *
-                                             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 backup_controllers and logs
-
-        if (!empty($CFG->loglifetime)) {  // value in days
-            $loglifetime = $timenow - ($CFG->loglifetime * 3600 * 24);
-            // Delete child records from backup_logs
-            $DB->execute("DELETE FROM {backup_logs}
-                           WHERE EXISTS (
-                               SELECT 'x'
-                                 FROM {backup_controllers} bc
-                                WHERE bc.backupid = {backup_logs}.backupid
-                                  AND bc.timecreated < ?)", array($loglifetime));
-            // Delete records from backup_controllers
-            $DB->execute("DELETE FROM {backup_controllers}
-                          WHERE timecreated < ?", array($loglifetime));
-            mtrace("Deleted old backup 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();
-
-        //
-        // 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_recordset_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 $newuser) {
-                // email user
-                if (setnew_password_and_mail($newuser)) {
-                    unset_user_preference('create_password', $newuser);
-                    set_user_preference('auth_forcepasswordchange', 1, $newuser);
-                } else {
-                    trigger_error("Could not create and mail new user password!");
-                }
-            }
-            $newusers->close();
-        }
-
-        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');
-
-        if (!empty($CFG->messagingdeletereadnotificationsdelay)) {
-            $notificationdeletetime = time() - $CFG->messagingdeletereadnotificationsdelay;
-            $DB->delete_records_select('message_read', 'notification=1 AND timeread<:notificationdeletetime', array('notificationdeletetime'=>$notificationdeletetime));
-            mtrace('Cleaned up read notifications');
-        }
-
-        mtrace("Finished clean-up tasks...");
-
-    } // End of occasional clean-up tasks
-
-    // Run automated backups if required.
-    require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php');
-    require_once($CFG->dirroot.'/backup/util/helper/backup_cron_helper.class.php');
-    backup_cron_automated_helper::run_automated_backup();
-
-/// Run the auth cron, if any
-/// before enrolments because it might add users that will be needed in enrol plugins
-    $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);
-    }
-
-    mtrace("Running enrol crons if required...");
-    $enrols = enrol_get_plugins(true);
-    foreach($enrols as $ename=>$enrol) {
-        // do this for all plugins, disabled plugins might want to cleanup stuff such as roles
-        if (!$enrol->is_cron_required()) {
-            continue;
-        }
-        mtrace("Running cron for enrol_$ename...");
-        $enrol->cron();
-        $enrol->set_config('lastcron', time());
-    }
-
-    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));
-        }
-    }
-
 
     mtrace('Starting course reports');
     cron_execute_plugin_type('coursereport');
     mtrace('Finished course reports');
 
+
     // run gradebook import/export/report cron
     mtrace('Starting gradebook plugins');
     cron_execute_plugin_type('gradeimport');
@@ -399,6 +377,7 @@ function cron_run() {
     cron_execute_plugin_type('gradereport');
     mtrace('Finished gradebook plugins');
 
+
     // Run external blog cron if needed
     if ($CFG->useexternalblogs) {
         require_once($CFG->dirroot . '/blog/lib.php');
@@ -411,7 +390,6 @@ function cron_run() {
         }
         mtrace('done.');
     }
-
     // Run blog associations cleanup
     if ($CFG->useblogassociations) {
         require_once($CFG->dirroot . '/blog/lib.php');
@@ -421,6 +399,7 @@ function cron_run() {
         mtrace('done.');
     }
 
+
     //Run registration updated cron
     mtrace(get_string('siteupdatesstart', 'hub'));
     require_once($CFG->dirroot . '/admin/registration/lib.php');
@@ -428,9 +407,6 @@ function cron_run() {
     $registrationmanager->cron();
     mtrace(get_string('siteupdatesend', 'hub'));
 
-    // cleanup file trash
-    $fs = get_file_storage();
-    $fs->cron();
 
     //cleanup old session linked tokens
     //deletes the session linked tokens that are over a day old.
@@ -439,6 +415,7 @@ function cron_run() {
                     array('onedayago' => time() - DAYSECS, 'tokentype' => EXTERNAL_TOKEN_EMBEDDED));
     mtrace('done.');
 
+
     // all other plugins
     cron_execute_plugin_type('message', 'message plugins');
     cron_execute_plugin_type('filter', 'filters');
@@ -454,6 +431,7 @@ function cron_run() {
     cron_execute_plugin_type('theme', 'themes');
     cron_execute_plugin_type('tool', 'admin tools');
 
+
     // and finally run any local cronjobs, if any
     if ($locals = get_plugin_list('local')) {
         mtrace('Processing customized cron scripts ...', '');
@@ -468,6 +446,41 @@ function cron_run() {
         mtrace('done.');
     }
 
+
+    // Run automated backups if required - these may take a long time to execute
+    require_once($CFG->dirroot.'/backup/util/includes/backup_includes.php');
+    require_once($CFG->dirroot.'/backup/util/helper/backup_cron_helper.class.php');
+    backup_cron_automated_helper::run_automated_backup();
+
+
+    // Run stats as at the end because they are known to take very long time on large sites
+    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));
+        }
+    }
+
+
+    // cleanup file trash - not very important
+    $fs = get_file_storage();
+    $fs->cron();
+
+
     mtrace("Cron script completed correctly");
 
     $difftime = microtime_diff($starttime, microtime());
@@ -476,6 +489,7 @@ function cron_run() {
 
 /**
  * Executes cron functions for a specific type of plugin.
+ *
  * @param string $plugintype Plugin type (e.g. 'report')
  * @param string $description If specified, will display 'Starting (whatever)'
  *   and 'Finished (whatever)' lines, otherwise does not display
@@ -541,6 +555,7 @@ function cron_execute_plugin_type($plugintype, $description = null) {
  * Used to add in old-style cron functions within plugins that have not been converted to the
  * new standard API. (The standard API is frankenstyle_name_cron() in lib.php; some types used
  * cron.php and some used a different name.)
+ *
  * @param string $plugintype Plugin type e.g. 'report'
  * @param array $plugins Array from plugin name (e.g. 'report_frog') to function name (e.g.
  *   'report_frog_cron') for plugin cron functions that were already found using the new API
@@ -595,4 +610,119 @@ function cron_bc_hack_plugin_functions($plugintype, $plugins) {
     }
 
     return $plugins;
-}
\ No newline at end of file
+}
+
+
+/**
+ * Notify admin users or admin user of any failed logins (since last notification).
+ *
+ * Note that this function must be only executed from the cron script
+ * It uses the cache_flags system to store temporary records, deleting them
+ * by name before finishing
+ */
+function notify_login_failures() {
+    global $CFG, $DB, $OUTPUT;
+
+    $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config');
+
+    if (empty($CFG->lastnotifyfailure)) {
+        $CFG->lastnotifyfailure=0;
+    }
+
+    // we need to deal with the threshold stuff first.
+    if (empty($CFG->notifyloginthreshold)) {
+        $CFG->notifyloginthreshold = 10; // default to something sensible.
+    }
+
+    // Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
+    // and insert them into the cache_flags temp table
+    $sql = "SELECT ip, COUNT(*)
+              FROM {log}
+             WHERE module = 'login' AND action = 'error'
+                   AND time > ?
+          GROUP BY ip
+            HAVING COUNT(*) >= ?";
+    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
+    $rs = $DB->get_recordset_sql($sql, $params);
+    foreach ($rs as $iprec) {
+        if (!empty($iprec->ip)) {
+            set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0);
+        }
+    }
+    $rs->close();
+
+    // Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
+    // and insert them into the cache_flags temp table
+    $sql = "SELECT info, count(*)
+              FROM {log}
+             WHERE module = 'login' AND action = 'error'
+                   AND time > ?
+          GROUP BY info
+            HAVING count(*) >= ?";
+    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
+    $rs = $DB->get_recordset_sql($sql, $params);
+    foreach ($rs as $inforec) {
+        if (!empty($inforec->info)) {
+            set_cache_flag('login_failure_by_info', $inforec->info, '1', 0);
+        }
+    }
+    $rs->close();
+
+    // Now, select all the login error logged records belonging to the ips and infos
+    // since lastnotifyfailure, that we have stored in the cache_flags table
+    $sql = "SELECT l.*, u.firstname, u.lastname
+              FROM {log} l
+              JOIN {cache_flags} cf ON l.ip = cf.name
+         LEFT JOIN {user} u         ON l.userid = u.id
+             WHERE l.module = 'login' AND l.action = 'error'
+                   AND l.time > ?
+                   AND cf.flagtype = 'login_failure_by_ip'
+        UNION ALL
+            SELECT l.*, u.firstname, u.lastname
+              FROM {log} l
+              JOIN {cache_flags} cf ON l.info = cf.name
+         LEFT JOIN {user} u         ON l.userid = u.id
+             WHERE l.module = 'login' AND l.action = 'error'
+                   AND l.time > ?
+                   AND cf.flagtype = 'login_failure_by_info'
+          ORDER BY time DESC";
+    $params = array($CFG->lastnotifyfailure, $CFG->lastnotifyfailure);
+
+    // Init some variables
+    $count = 0;
+    $messages = '';
+    // Iterate over the logs recordset
+    $rs = $DB->get_recordset_sql($sql, $params);
+    foreach ($rs as $log) {
+        $log->time = userdate($log->time);
+        $messages .= get_string('notifyloginfailuresmessage','',$log)."\n";
+        $count++;
+    }
+    $rs->close();
+
+    // If we haven't run in the last hour and
+    // we have something useful to report and we
+    // are actually supposed to be reporting to somebody
+    if ((time() - HOURSECS) > $CFG->lastnotifyfailure && $count > 0 && is_array($recip) && count($recip) > 0) {
+        $site = get_site();
+        $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
+        // Calculate the complete body of notification (start + messages + end)
+        $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) .
+                (($CFG->lastnotifyfailure != 0) ? '('.userdate($CFG->lastnotifyfailure).')' : '')."\n\n" .
+                $messages .
+                "\n\n".get_string('notifyloginfailuresmessageend','',$CFG->wwwroot)."\n\n";
+
+        // For each destination, send mail
+        mtrace('Emailing admins about '. $count .' failed login attempts');
+        foreach ($recip as $admin) {
+            //emailing the admins directly rather than putting these through the messaging system
+            email_to_user($admin,get_admin(), $subject, $body);
+        }
+
+        // Update lastnotifyfailure with current time
+        set_config('lastnotifyfailure', time());
+    }
+
+    // Finally, delete all the temp records we have created in cache_flags
+    $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
+}
index ec2970c..5fb8588 100644 (file)
@@ -126,7 +126,7 @@ function message_send($eventdata) {
         } else {
             //MDL-25114 They supplied an $eventdata->component $eventdata->name combination which doesn't
             //exist in the message_provider table (thus there is no default settings for them)
-            $preferrormsg = get_string('couldnotfindpreference', 'message', $preferencename);
+            $preferrormsg = get_string('couldnotfindpreference', 'message', $preferencename); //TODO: undefined $preferencename
             throw new coding_exception($preferrormsg,'blah');
         }
 
index 68100a5..436d884 100644 (file)
@@ -8320,124 +8320,6 @@ function upgrade_set_timeout($max_execution_time=300) {
 
 /// MISCELLANEOUS ////////////////////////////////////////////////////////////////////
 
-/**
- * Notify admin users or admin user of any failed logins (since last notification).
- *
- * Note that this function must be only executed from the cron script
- * It uses the cache_flags system to store temporary records, deleting them
- * by name before finishing
- *
- * @global object
- * @global object
- * @uses HOURSECS
- */
-function notify_login_failures() {
-    global $CFG, $DB, $OUTPUT;
-
-    $recip = get_users_from_config($CFG->notifyloginfailures, 'moodle/site:config');
-
-    if (empty($CFG->lastnotifyfailure)) {
-        $CFG->lastnotifyfailure=0;
-    }
-
-    // we need to deal with the threshold stuff first.
-    if (empty($CFG->notifyloginthreshold)) {
-        $CFG->notifyloginthreshold = 10; // default to something sensible.
-    }
-
-/// Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure
-/// and insert them into the cache_flags temp table
-    $sql = "SELECT ip, COUNT(*)
-              FROM {log}
-             WHERE module = 'login' AND action = 'error'
-                   AND time > ?
-          GROUP BY ip
-            HAVING COUNT(*) >= ?";
-    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
-    $rs = $DB->get_recordset_sql($sql, $params);
-    foreach ($rs as $iprec) {
-        if (!empty($iprec->ip)) {
-            set_cache_flag('login_failure_by_ip', $iprec->ip, '1', 0);
-        }
-    }
-    $rs->close();
-
-/// Get all the INFOs with more than notifyloginthreshold failures since lastnotifyfailure
-/// and insert them into the cache_flags temp table
-    $sql = "SELECT info, count(*)
-              FROM {log}
-             WHERE module = 'login' AND action = 'error'
-                   AND time > ?
-          GROUP BY info
-            HAVING count(*) >= ?";
-    $params = array($CFG->lastnotifyfailure, $CFG->notifyloginthreshold);
-    $rs = $DB->get_recordset_sql($sql, $params);
-    foreach ($rs as $inforec) {
-        if (!empty($inforec->info)) {
-            set_cache_flag('login_failure_by_info', $inforec->info, '1', 0);
-        }
-    }
-    $rs->close();
-
-/// Now, select all the login error logged records belonging to the ips and infos
-/// since lastnotifyfailure, that we have stored in the cache_flags table
-    $sql = "SELECT l.*, u.firstname, u.lastname
-              FROM {log} l
-              JOIN {cache_flags} cf ON l.ip = cf.name
-         LEFT JOIN {user} u         ON l.userid = u.id
-             WHERE l.module = 'login' AND l.action = 'error'
-                   AND l.time > ?
-                   AND cf.flagtype = 'login_failure_by_ip'
-        UNION ALL
-            SELECT l.*, u.firstname, u.lastname
-              FROM {log} l
-              JOIN {cache_flags} cf ON l.info = cf.name
-         LEFT JOIN {user} u         ON l.userid = u.id
-             WHERE l.module = 'login' AND l.action = 'error'
-                   AND l.time > ?
-                   AND cf.flagtype = 'login_failure_by_info'
-          ORDER BY time DESC";
-    $params = array($CFG->lastnotifyfailure, $CFG->lastnotifyfailure);
-
-/// Init some variables
-    $count = 0;
-    $messages = '';
-/// Iterate over the logs recordset
-    $rs = $DB->get_recordset_sql($sql, $params);
-    foreach ($rs as $log) {
-        $log->time = userdate($log->time);
-        $messages .= get_string('notifyloginfailuresmessage','',$log)."\n";
-        $count++;
-    }
-    $rs->close();
-
-/// If we haven't run in the last hour and
-/// we have something useful to report and we
-/// are actually supposed to be reporting to somebody
-    if ((time() - HOURSECS) > $CFG->lastnotifyfailure && $count > 0 && is_array($recip) && count($recip) > 0) {
-        $site = get_site();
-        $subject = get_string('notifyloginfailuressubject', '', format_string($site->fullname));
-    /// Calculate the complete body of notification (start + messages + end)
-        $body = get_string('notifyloginfailuresmessagestart', '', $CFG->wwwroot) .
-                (($CFG->lastnotifyfailure != 0) ? '('.userdate($CFG->lastnotifyfailure).')' : '')."\n\n" .
-                $messages .
-                "\n\n".get_string('notifyloginfailuresmessageend','',$CFG->wwwroot)."\n\n";
-
-    /// For each destination, send mail
-        mtrace('Emailing admins about '. $count .' failed login attempts');
-        foreach ($recip as $admin) {
-            //emailing the admins directly rather than putting these through the messaging system
-            email_to_user($admin,get_admin(), $subject, $body);
-        }
-
-    /// Update lastnotifyfailure with current time
-        set_config('lastnotifyfailure', time());
-    }
-
-/// Finally, delete all the temp records we have created in cache_flags
-    $DB->delete_records_select('cache_flags', "flagtype IN ('login_failure_by_ip', 'login_failure_by_info')");
-}
-
 /**
  * Sets the system locale
  *
index 7ad36cf..a9c8fff 100644 (file)
@@ -29,6 +29,7 @@ define ('MESSAGE_SHORTLENGTH', 300);
 
 //$PAGE isnt set if we're being loaded by cron which doesnt display popups anyway
 if (isset($PAGE)) {
+    //TODO: this is a mega crazy hack - it is not acceptable to call anything when including lib!!! (skodak)
     $PAGE->set_popup_notification_allowed(false); // We are in a message window (so don't pop up a new one)
 }
 
@@ -77,6 +78,7 @@ define('MESSAGE_PERMITTED_MASK', 0x0c); // 1100
  */
 define('MESSAGE_DEFAULT_PERMITTED', 'permitted');
 
+//TODO: defaults must be initialised via settings - this is a bad hack! (skodak)
 if (!isset($CFG->message_contacts_refresh)) {  // Refresh the contacts list every 60 seconds
     $CFG->message_contacts_refresh = 60;
 }