Merge branch 'MDL-29854_b' of git://github.com/timhunt/moodle
authorAparup Banerjee <aparup@moodle.com>
Wed, 26 Oct 2011 03:23:09 +0000 (11:23 +0800)
committerAparup Banerjee <aparup@moodle.com>
Wed, 26 Oct 2011 03:23:09 +0000 (11:23 +0800)
162 files changed:
admin/settings/security.php
blocks/online_users/block_online_users.php
blocks/quiz_results/backup/moodle2/restore_quiz_results_block_task.class.php
blocks/quiz_results/block_quiz_results.php
blocks/quiz_results/edit_form.php
blocks/quiz_results/lang/en/block_quiz_results.php
blocks/quiz_results/styles.css
blocks/quiz_results/version.php
course/externallib.php
course/lib.php
enrol/database/lib.php
enrol/externallib.php
enrol/manual/db/services.php
enrol/manual/externallib.php
enrol/manual/locallib.php
enrol/manual/version.php
enrol/meta/db/events.php
enrol/meta/locallib.php
enrol/meta/version.php
enrol/upgrade.txt
files/externallib.php
group/externallib.php
lang/en/admin.php
lang/en/moodle.php
lang/en/webservice.php
lib/accesslib.php
lib/base32.php [deleted file]
lib/cronlib.php
lib/csshover.htc [deleted file]
lib/db/events.php
lib/db/services.php
lib/db/upgrade.php
lib/dml/simpletest/testdml.php
lib/enrollib.php
lib/filestorage/stored_file.php
lib/kses.php [deleted file]
lib/md5.js [deleted file]
lib/messagelib.php
lib/moodlelib.php
lib/odbc.php [deleted file]
lib/overlib/overlib.js [deleted file]
lib/overlib/overlib_anchor.js [deleted file]
lib/overlib/overlib_centerpopup.js [deleted file]
lib/overlib/overlib_crossframe.js [deleted file]
lib/overlib/overlib_cssstyle.js [deleted file]
lib/overlib/overlib_debug.js [deleted file]
lib/overlib/overlib_exclusive.js [deleted file]
lib/overlib/overlib_followscroll.js [deleted file]
lib/overlib/overlib_hideform.js [deleted file]
lib/overlib/overlib_setonoff.js [deleted file]
lib/overlib/overlib_shadow.js [deleted file]
lib/pear/Console/Getopt.php [deleted file]
lib/pear/Console/README [deleted file]
lib/pear/PHP/CodeSniffer.php [deleted file]
lib/pear/PHP/CodeSniffer/CLI.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/AbstractDocElement.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/AbstractParser.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/ClassCommentParser.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/CommentElement.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/DocElement.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/FunctionCommentParser.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/MemberCommentParser.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/PairElement.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/ParameterElement.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/ParserException.php [deleted file]
lib/pear/PHP/CodeSniffer/CommentParser/SingleElement.php [deleted file]
lib/pear/PHP/CodeSniffer/DocGenerators/Generator.php [deleted file]
lib/pear/PHP/CodeSniffer/DocGenerators/HTML.php [deleted file]
lib/pear/PHP/CodeSniffer/DocGenerators/Text.php [deleted file]
lib/pear/PHP/CodeSniffer/Exception.php [deleted file]
lib/pear/PHP/CodeSniffer/File.php [deleted file]
lib/pear/PHP/CodeSniffer/MoodleCLI.php [deleted file]
lib/pear/PHP/CodeSniffer/Sniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/AbstractPatternSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/AbstractScopeSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/AbstractVariableSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/CodingStandard.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/IncorrectPatternException.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/MoodleCodingStandard.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Classes/ClassDeclarationSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/EmptyStatementSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Commenting/ClassCommentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Commenting/FileCommentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Commenting/FunctionCommentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Commenting/InlineCommentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/ControlStructures/ControlSignatureSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/ControlStructures/ElseIfDeclarationSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/ControlStructures/InlineControlStructureSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Files/ClosingPHPTagSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Files/IncludingFileSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Files/LineEndingsSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Files/LineLengthSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Formatting/SpaceAfterCastSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Functions/FunctionCallSignatureSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Functions/FunctionDeclarationSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Functions/ValidDefaultValueSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/NamingConventions/ValidClassNameSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/NamingConventions/ValidFunctionNameSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/NamingConventions/ValidVariableNameSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/PHP/DisallowShortOpenTagSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/PHP/LowerCaseConstantSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/PHP/LowercasePHPFunctionsSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Strings/DoubleQuoteUsageSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/Strings/EchoedStringsSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/WhiteSpace/ControlStructureBlankLineSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/WhiteSpace/DisallowTabIndentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/WhiteSpace/MemberVarSpacingSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Standards/Moodle/Sniffs/WhiteSpace/ScopeIndentSniff.php [deleted file]
lib/pear/PHP/CodeSniffer/Tokenizers/JS.php [deleted file]
lib/pear/PHP/CodeSniffer/Tokenizers/PHP.php [deleted file]
lib/pear/PHP/CodeSniffer/Tokens.php [deleted file]
lib/pear/PHP/MoodleCodeSniffer.php [deleted file]
lib/pear/PHP/runsniffer [deleted file]
lib/pear/README.txt
lib/pear/README_MOODLE.txt
lib/profilerlib.php [deleted file]
lib/resourcelib.php
lib/setup.php
lib/setuplib.php
lib/simpletest/testpurifier.php
lib/simpletest/testweblib.php
lib/swfobject/swfobject.js [deleted file]
lib/thirdpartylibs.xml
lib/typo3/class.t3lib_cs.php
lib/typo3/class.t3lib_div.php
lib/typo3/readme_moodle.txt
lib/weblib.php
login/token.php
message/externallib.php
message/lib.php
mod/assignment/renderer.php
mod/feedback/backup/moodle2/restore_feedback_activity_task.class.php
mod/lesson/locallib.php
mod/lesson/pagetypes/matching.php
mod/quiz/report/statistics/statistics_table.php
mod/quiz/review.php
mod/resource/lib.php
mod/scorm/userreport.php
mod/url/lang/en/url.php
mod/url/view.php
notes/externallib.php
question/engine/datalib.php
question/type/multichoice/edit_multichoice_form.php
question/type/multichoice/lang/en/qtype_multichoice.php
rss/renderer.php
user/externallib.php
version.php
webservice/amf/testclient/index.php
webservice/externallib.php
webservice/lib.php
webservice/rest/locallib.php

index b72333c..de44e51 100644 (file)
@@ -33,9 +33,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $params->displaysize = display_size($defaultuserquota);
     $temp->add(new admin_setting_configtext('userquota', get_string('userquota', 'admin'), get_string('configuserquota', 'admin', $params), $defaultuserquota));
 
-    $item = new admin_setting_configcheckbox('enablehtmlpurifier', get_string('enablehtmlpurifier', 'admin'), get_string('configenablehtmlpurifier', 'admin'), 1);
-    $item->set_updatedcallback('reset_text_filters_cache');
-    $temp->add($item);
     $temp->add(new admin_setting_configcheckbox('allowobjectembed', get_string('allowobjectembed', 'admin'), get_string('configallowobjectembed', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('enabletrusttext', get_string('enabletrusttext', 'admin'), get_string('configenabletrusttext', 'admin'), 0));
     $temp->add(new admin_setting_configselect('maxeditingtime', get_string('maxeditingtime','admin'), get_string('configmaxeditingtime','admin'), 1800,
index 622f96b..cbf1dac 100644 (file)
@@ -62,11 +62,10 @@ class block_online_users extends block_base {
                   GROUP BY $userfields
                   ORDER BY lastaccess DESC ";
 
-           $csql = "SELECT COUNT(u.id), u.id
+           $csql = "SELECT COUNT(u.id)
                       FROM {user} u $groupmembers
                      WHERE u.lastaccess > $timefrom
-                           $groupselect
-                  GROUP BY u.id";
+                           $groupselect";
 
         } else {
             // Course level - show only enrolled users for now
@@ -85,14 +84,13 @@ class block_online_users extends block_base {
                   GROUP BY $userfields
                   ORDER BY lastaccess DESC";
 
-           $csql = "SELECT u.id
+           $csql = "SELECT COUNT(u.id)
                       FROM {user_lastaccess} ul $groupmembers, {user} u
                       JOIN ($esqljoin) euj ON euj.id = u.id
                      WHERE ul.timeaccess > $timefrom
                            AND u.id = ul.userid
                            AND ul.courseid = :courseid
-                           $groupselect
-                  GROUP BY u.id";
+                           $groupselect";
 
             $params['courseid'] = $this->page->course->id;
         }
index 6e6e730..1ba4334 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * @package moodlecore
+ * @package    moodlecore
  * @subpackage backup-moodle2
- * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @copyright  2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+
+defined('MOODLE_INTERNAL') || die();
+
+
 /**
  * Specialised restore task for the quiz_results block
  * (using execute_after_tasks for recoding of target quiz)
  *
  * TODO: Finish phpdocs
+ *
+ * @copyright  2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 class restore_quiz_results_block_task extends restore_block_task {
 
index a6bb602..a8d24e5 100644 (file)
@@ -1,5 +1,45 @@
 <?php
-
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Classes to enforce the various access rules that can apply to a quiz.
+ *
+ * @package    block
+ * @subpackage quiz_results
+ * @copyright  2009 Tim Hunt
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/mod/quiz/lib.php');
+
+
+/**
+ * Block quiz_results class definition.
+ *
+ * This block can be added to a course page or a quiz page to display of list of
+ * the best/worst students/groups in a particular quiz.
+ *
+ * @package    block
+ * @subpackage quiz_results
+ * @copyright  2009 Tim Hunt
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 define('B_QUIZRESULTS_NAME_FORMAT_FULL', 1);
 define('B_QUIZRESULTS_NAME_FORMAT_ID',   2);
 define('B_QUIZRESULTS_NAME_FORMAT_ANON', 3);
index 94f58b8..1f1db86 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Form for editing Quiz results block instances.
+ * Defines the form for editing Quiz results block instances.
  *
  * @package   moodlecore
  * @copyright 2009 Tim Hunt
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+defined('MOODLE_INTERNAL') || die();
+
+
 /**
  * Form for editing Quiz results block instances.
  *
index 7ae20a3..b3bda7f 100644 (file)
 /**
  * Strings for component 'block_quiz_results', language 'en', branch 'MOODLE_20_STABLE'
  *
- * @package   block_quiz_results
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package    block
+ * @subpackage quiz_results
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 $string['bestgrade'] = 'The highest grade:';
index 1a3fabc..0f2dda9 100644 (file)
@@ -3,4 +3,4 @@
 .block_quiz_results table.grades {text-align: left;width: 100%;}
 .block_quiz_results table.grades .number,
 .block_quiz_results table.grades .grade {text-align: right;width: 10%;}
-.block_quiz_results table.grades caption {margin: 1em 0px 0px 0px;border-bottom-width: 1px;border-bottom-style: solid;font-weight: bold;}
\ No newline at end of file
+.block_quiz_results table.grades caption {margin: 1em 0px 0px 0px;border-bottom-width: 1px;border-bottom-style: solid;font-weight: bold;}
index c9abcfe..117b311 100644 (file)
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-$plugin->version = 2007101509;
+/**
+ * Version information for the block_quiz_results plugin.
+ *
+ * @package    block
+ * @subpackage quiz_results
+ * @copyright  2011 The Open University
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+
+$plugin->version = 2011100300;
+$plugin->requires  = 2011091600;
+$plugin->component = 'block_quiz_results';
index 7d9e6d6..3724e30 100644 (file)
@@ -28,7 +28,10 @@ defined('MOODLE_INTERNAL') || die;
 
 require_once("$CFG->libdir/externallib.php");
 
-class moodle_course_external extends external_api {
+/**
+ * Course functions
+ */
+class core_course_external extends external_api {
 
     /**
      * Returns description of method parameters
@@ -363,4 +366,68 @@ class moodle_course_external extends external_api {
         );
     }
 
+}
+
+/**
+ * Deprecated course functions
+ * @deprecated since Moodle 2.2 please use core_course_external instead
+ */
+class moodle_course_external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_course_external::get_courses_parameters instead
+     * @return external_function_parameters
+     */
+    public static function get_courses_parameters() {
+        return core_course_external::get_courses_parameters();
+    }
+
+    /**
+     * Get courses
+     * @param array $options
+     * @deprecated since Moodle 2.2 please use core_course_external::get_courses instead
+     * @return array
+     */
+    public static function get_courses($options) {
+        return core_course_external::get_courses($options);
+    }
+
+    /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_course_external::get_courses_returns instead
+     * @return external_description
+     */
+    public static function get_courses_returns() {
+        return core_course_external::get_courses_returns();
+    }
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_course_external::create_courses_parameters instead
+     * @return external_function_parameters
+     */
+    public static function create_courses_parameters() {
+        return core_course_external::create_courses_parameters();
+    }
+
+    /**
+     * Create  courses
+     * @deprecated since Moodle 2.2 please use core_course_external::create_courses instead
+     * @param array $courses
+     * @return array courses (id and shortname only)
+     */
+    public static function create_courses($courses) {
+        return core_course_external::create_courses($courses);
+    }
+
+    /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_course_external::create_courses_returns instead
+     * @return external_description
+     */
+    public static function create_courses_returns() {
+        return core_course_external::create_courses_returns();
+    }
+
 }
\ No newline at end of file
index 5fb1ae6..79ccf91 100644 (file)
@@ -2454,59 +2454,46 @@ function print_course($course, $highlightterms = '') {
     if (!empty($CFG->coursecontact)) {
         $managerroles = explode(',', $CFG->coursecontact);
         $namesarray = array();
-        if (isset($course->managers)) {
-            if (count($course->managers)) {
-                $rusers = $course->managers;
-                $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
-
-                 /// Rename some of the role names if needed
-                if (isset($context)) {
-                    $aliasnames = $DB->get_records('role_names', array('contextid'=>$context->id), '', 'roleid,contextid,name');
-                }
-
-                // keep a note of users displayed to eliminate duplicates
-                $usersshown = array();
-                foreach ($rusers as $ra) {
-
-                    // if we've already displayed user don't again
-                    if (in_array($ra->user->id,$usersshown)) {
-                        continue;
-                    }
-                    $usersshown[] = $ra->user->id;
+        $rusers = array();
 
-                    $fullname = fullname($ra->user, $canviewfullnames);
-
-                    if (isset($aliasnames[$ra->roleid])) {
-                        $ra->rolename = $aliasnames[$ra->roleid]->name;
-                    }
-
-                    $namesarray[] = format_string($ra->rolename).': '.
-                                    html_writer::link(new moodle_url('/user/view.php', array('id'=>$ra->user->id, 'course'=>SITEID)), $fullname);
-                }
-            }
+        if (!isset($course->managers)) {
+            $rusers = get_role_users($managerroles, $context, true,
+                'ra.id AS raid, u.id, u.username, u.firstname, u.lastname,
+                 r.name AS rolename, r.sortorder, r.id AS roleid',
+                'r.sortorder ASC, u.lastname ASC');
         } else {
-            $rusers = get_role_users($managerroles, $context,
-                                     true, '', 'r.sortorder ASC, u.lastname ASC');
-            if (is_array($rusers) && count($rusers)) {
-                $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
-
-                /// Rename some of the role names if needed
-                if (isset($context)) {
-                    $aliasnames = $DB->get_records('role_names', array('contextid'=>$context->id), '', 'roleid,contextid,name');
-                }
+            //  use the managers array if we have it for perf reasosn
+            //  populate the datastructure like output of get_role_users();
+            foreach ($course->managers as $manager) {
+                $u = new stdClass();
+                $u = $manager->user;
+                $u->roleid = $manager->roleid;
+                $u->rolename = $manager->rolename;
+
+                $rusers[] = $u;
+            }
+        }
 
-                foreach ($rusers as $teacher) {
-                    $fullname = fullname($teacher, $canviewfullnames);
+        /// Rename some of the role names if needed
+        if (isset($context)) {
+            $aliasnames = $DB->get_records('role_names', array('contextid'=>$context->id), '', 'roleid,contextid,name');
+        }
 
-                    /// Apply role names
-                    if (isset($aliasnames[$teacher->roleid])) {
-                        $teacher->rolename = $aliasnames[$teacher->roleid]->name;
-                    }
+        $namesarray = array();
+        $canviewfullnames = has_capability('moodle/site:viewfullnames', $context);
+        foreach ($rusers as $ra) {
+            if (isset($namesarray[$ra->id])) {
+                //  only display a user once with the higest sortorder role
+                continue;
+            }
 
-                    $namesarray[] = format_string($teacher->rolename).': '.
-                                    html_writer::link(new moodle_url('/user/view.php', array('id'=>$teacher->id, 'course'=>SITEID)), $fullname);
-                }
+            if (isset($aliasnames[$ra->roleid])) {
+                $ra->rolename = $aliasnames[$ra->roleid]->name;
             }
+
+            $fullname = fullname($ra, $canviewfullnames);
+            $namesarray[$ra->id] = format_string($ra->rolename).': '.
+                html_writer::link(new moodle_url('/user/view.php', array('id'=>$ra->id, 'course'=>SITEID)), $fullname);
         }
 
         if (!empty($namesarray)) {
index f7606b6..306f8b3 100644 (file)
@@ -170,11 +170,11 @@ class enrol_database_plugin extends enrol_plugin {
             if ($e = $DB->get_record('user_enrolments', array('userid'=>$user->id, 'enrolid'=>$instance->id))) {
                 // reenable enrolment when previously disable enrolment refreshed
                 if ($e->status == ENROL_USER_SUSPENDED) {
-                    $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid'=>$instance->id, 'userid'=>$user->id));
+                    $this->update_user_enrol($instance, $user->id, ENROL_USER_ACTIVE);
                 }
             } else {
                 $roleid = reset($roles);
-                $this->enrol_user($instance, $user->id, $roleid);
+                $this->enrol_user($instance, $user->id, $roleid, 0, 0, ENROL_USER_ACTIVE);
             }
 
             if (!$context = get_context_instance(CONTEXT_COURSE, $instance->courseid)) {
@@ -231,7 +231,7 @@ class enrol_database_plugin extends enrol_plugin {
             } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND or $unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                 // disable
                 if ($instance->ustatus != ENROL_USER_SUSPENDED) {
-                    $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid'=>$instance->id, 'userid'=>$user->id));
+                    $this->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
                 }
                 if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
                     role_unassign_all(array('contextid'=>$context->id, 'userid'=>$user->id, 'component'=>'enrol_database', 'itemid'=>$instance->id));
@@ -455,7 +455,7 @@ class enrol_database_plugin extends enrol_plugin {
             foreach ($requested_roles as $userid=>$userroles) {
                 foreach ($userroles as $roleid) {
                     if (empty($current_roles[$userid])) {
-                        $this->enrol_user($instance, $userid, $roleid);
+                        $this->enrol_user($instance, $userid, $roleid, 0, 0, ENROL_USER_ACTIVE);
                         $current_roles[$userid][$roleid] = $roleid;
                         $current_status[$userid] = ENROL_USER_ACTIVE;
                         if ($verbose) {
@@ -488,7 +488,7 @@ class enrol_database_plugin extends enrol_plugin {
 
                 // reenable enrolment when previously disable enrolment refreshed
                 if ($current_status[$userid] == ENROL_USER_SUSPENDED) {
-                    $DB->set_field('user_enrolments', 'status', ENROL_USER_ACTIVE, array('enrolid'=>$instance->id, 'userid'=>$userid));
+                    $this->update_user_enrol($instance, $userid, ENROL_USER_ACTIVE);
                     if ($verbose) {
                         mtrace("  unsuspending: $userid ==> $course->shortname");
                     }
@@ -520,7 +520,7 @@ class enrol_database_plugin extends enrol_plugin {
                         continue;
                     }
                     if ($status != ENROL_USER_SUSPENDED) {
-                        $DB->set_field('user_enrolments', 'status', ENROL_USER_SUSPENDED, array('enrolid'=>$instance->id, 'userid'=>$userid));
+                        $this->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
                         if ($verbose) {
                             mtrace("  suspending: $userid ==> $course->shortname");
                         }
index b11271c..11d6074 100644 (file)
@@ -31,12 +31,415 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once("$CFG->libdir/externallib.php");
 
+/**
+ * Enrol functions
+ */
+class core_enrol_external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function get_users_courses_parameters() {
+        return new external_function_parameters(
+            array(
+                'userid' => new external_value(PARAM_INT, 'user id'),
+            )
+        );
+    }
+
+    /**
+     * Get list of courses user is enrolled in (only active enrolments are returned).
+     *
+     * Please note the current user must be able to access the course, otherwise the course is not included.
+     *
+     * @param int $userid
+     * @return array of courses
+     */
+    public static function get_users_courses($userid) {
+        global $USER;
+
+        // Do basic automatic PARAM checks on incoming data, using params description
+        // If any problems are found then exceptions are thrown with helpful error messages
+        $params = self::validate_parameters(self::get_users_courses_parameters(), array('userid'=>$userid));
+
+        $courses = enrol_get_users_courses($params['userid'], true, 'id, shortname, fullname, idnumber, visible');
+        $result = array();
+
+        foreach ($courses as $course) {
+            $context = get_context_instance(CONTEXT_COURSE, $course->id);
+            try {
+                self::validate_context($context);
+            } catch (Exception $e) {
+                // current user can not access this course, sorry we can not disclose who is enrolled in this course!
+                continue;
+            }
+            if ($userid != $USER->id and !has_capability('moodle/course:viewparticipants', $context)) {
+                // we need capability to view participants
+                continue;
+            }
+
+            $result[] = array('id'=>$course->id, 'shortname'=>$course->shortname, 'fullname'=>$course->fullname, 'idnumber'=>$course->idnumber,'visible'=>$course->visible);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns description of method result value
+     * @return external_description
+     */
+    public static function get_users_courses_returns() {
+        return new external_multiple_structure(
+            new external_single_structure(
+                array(
+                    'id'        => new external_value(PARAM_INT, 'id of course'),
+                    'shortname' => new external_value(PARAM_RAW, 'short name of course'),
+                    'fullname'  => new external_value(PARAM_RAW, 'long name of course'),
+                    'idnumber'  => new external_value(PARAM_RAW, 'id number of course'),
+                    'visible'   => new external_value(PARAM_INT, '1 means visible, 0 means hidden course'),
+                )
+            )
+        );
+    }
+
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function get_enrolled_users_parameters() {
+        return new external_function_parameters(
+            array(
+                'courseid' => new external_value(PARAM_INT, 'course id'),
+                'options'  => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'name'  => new external_value(PARAM_ALPHANUMEXT, 'option name'),
+                            'value' => new external_value(PARAM_RAW, 'option value')
+                        )
+                    ), 'method options'),
+            )
+        );
+    }
+
+    /**
+     * Get course participants details
+     * @param int $courseid  course id
+     * @param array $options options {
+     *          'name' => option name
+     *          'value' => option value
+     * }
+     * @return array An array of users
+     */
+    public static function get_enrolled_users($courseid, $options) {
+        global $CFG, $USER, $DB;
+        require_once($CFG->dirroot . "/user/lib.php");
+
+        $params = self::validate_parameters(
+            self::get_users_by_course_id_parameters(),
+            array(
+                'courseid'=>$courseid,
+                'options'=>$options
+            )
+        );
+        $withcapability = '';
+        $groupid        = 0;
+        $onlyactive     = false;
+        foreach ($options as $option) {
+            switch ($option['name']) {
+            case 'withcapability':
+                $withcapability = $option['value'];
+                break;
+            case 'groupid':
+                $groupid = (int)$option['value'];
+                break;
+            case 'onlyactive':
+                $onlyactive = !empty($option['value']);
+                break;
+            }
+        }
+
+        // to overwrite this parameter, you need role:review capability
+        if ($withcapability) {
+            require_capability('moodle/role:review', $coursecontext);
+        }
+        // need accessallgroups capability if you want to overwrite this option
+        if (!empty($groupid) && groups_is_member($groupid)) {
+            require_capability('moodle/site:accessallgroups', $context);
+        }
+        // to overwrite this option, you need course:enrolereview permission
+        if ($onlyactive) {
+            require_capability('moodle/course:enrolreview', $coursecontext);
+        }
+
+        list($coursectxselect, $coursectxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
+        $coursesql = "SELECT c.* $coursectxselect
+                        FROM {course} c $coursectxjoin
+                       WHERE c.id = $courseid";
+        $course = $DB->get_record_sql($coursesql);
+        context_instance_preload($course);
+        $coursecontext = get_context_instance(CONTEXT_COURSE, $params['courseid']);
+        if ($courseid == SITEID) {
+            $context = get_system_context();
+        } else {
+            $context = $coursecontext;
+        }
+        try {
+            self::validate_context($context);
+        } catch (Exception $e) {
+            $exceptionparam = new stdClass();
+            $exceptionparam->message = $e->getMessage();
+            $exceptionparam->courseid = $params['courseid'];
+            throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam));
+        }
+
+        list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, $withcapability, $groupid, $onlyactive);
+        list($ctxselect, $ctxjoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
+        $records = $DB->get_records_sql($enrolledsql, $enrolledparams);
+        $sqlparams['courseid'] = $courseid;
+        $sql = "SELECT u.* $ctxselect
+                  FROM {user} u $ctxjoin
+                 WHERE u.id IN ($enrolledsql)
+                 ORDER BY u.id ASC";
+        $enrolledusers = $DB->get_recordset_sql($sql, $enrolledparams);
+        $users = array();
+        foreach ($enrolledusers as $user) {
+            if (!empty($user->deleted)) {
+                continue;
+            }
+            context_instance_preload($user);
+            if ($userdetails = user_get_user_details($user, $course)) {
+                $users[] = $userdetails;
+            }
+        }
+        $enrolledusers->close();
+
+        return $users;
+    }
+
+    /**
+     * Returns description of method result value
+     * @return external_description
+     */
+    public static function get_enrolled_users_returns() {
+        return new external_multiple_structure(
+            new external_single_structure(
+                array(
+                    'id'    => new external_value(PARAM_NUMBER, 'ID of the user'),
+                    'username'    => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config', VALUE_OPTIONAL),
+                    'firstname'   => new external_value(PARAM_NOTAGS, 'The first name(s) of the user', VALUE_OPTIONAL),
+                    'lastname'    => new external_value(PARAM_NOTAGS, 'The family name of the user', VALUE_OPTIONAL),
+                    'fullname'    => new external_value(PARAM_NOTAGS, 'The fullname of the user'),
+                    'email'       => new external_value(PARAM_TEXT, 'An email address - allow email as root@localhost', VALUE_OPTIONAL),
+                    'address'     => new external_value(PARAM_MULTILANG, 'Postal address', VALUE_OPTIONAL),
+                    'phone1'      => new external_value(PARAM_NOTAGS, 'Phone 1', VALUE_OPTIONAL),
+                    'phone2'      => new external_value(PARAM_NOTAGS, 'Phone 2', VALUE_OPTIONAL),
+                    'icq'         => new external_value(PARAM_NOTAGS, 'icq number', VALUE_OPTIONAL),
+                    'skype'       => new external_value(PARAM_NOTAGS, 'skype id', VALUE_OPTIONAL),
+                    'yahoo'       => new external_value(PARAM_NOTAGS, 'yahoo id', VALUE_OPTIONAL),
+                    'aim'         => new external_value(PARAM_NOTAGS, 'aim id', VALUE_OPTIONAL),
+                    'msn'         => new external_value(PARAM_NOTAGS, 'msn number', VALUE_OPTIONAL),
+                    'department'  => new external_value(PARAM_TEXT, 'department', VALUE_OPTIONAL),
+                    'institution' => new external_value(PARAM_TEXT, 'institution', VALUE_OPTIONAL),
+                    'interests'   => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL),
+                    'firstaccess' => new external_value(PARAM_INT, 'first access to the site (0 if never)', VALUE_OPTIONAL),
+                    'lastaccess'  => new external_value(PARAM_INT, 'last access to the site (0 if never)', VALUE_OPTIONAL),
+                    'description' => new external_value(PARAM_RAW, 'User profile description', VALUE_OPTIONAL),
+                    'descriptionformat' => new external_value(PARAM_INT, 'User profile description format', VALUE_OPTIONAL),
+                    'city'        => new external_value(PARAM_NOTAGS, 'Home city of the user', VALUE_OPTIONAL),
+                    'url'         => new external_value(PARAM_URL, 'URL of the user', VALUE_OPTIONAL),
+                    'country'     => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL),
+                    'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'),
+                    'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'),
+                    'customfields' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'type'  => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'),
+                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
+                                'name' => new external_value(PARAM_RAW, 'The name of the custom field'),
+                                'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'),
+                            )
+                        ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL),
+                    'groups' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'id'  => new external_value(PARAM_INT, 'group id'),
+                                'name' => new external_value(PARAM_RAW, 'group name'),
+                                'description' => new external_value(PARAM_RAW, 'group description'),
+                            )
+                        ), 'user groups', VALUE_OPTIONAL),
+                    'roles' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'roleid'       => new external_value(PARAM_INT, 'role id'),
+                                'name'         => new external_value(PARAM_RAW, 'role name'),
+                                'shortname'    => new external_value(PARAM_ALPHANUMEXT, 'role shortname'),
+                                'sortorder'    => new external_value(PARAM_INT, 'role sortorder')
+                            )
+                        ), 'user roles', VALUE_OPTIONAL),
+                    'preferences' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'name'  => new external_value(PARAM_ALPHANUMEXT, 'The name of the preferences'),
+                                'value' => new external_value(PARAM_RAW, 'The value of the custom field'),
+                            )
+                    ), 'User preferences', VALUE_OPTIONAL),
+                    'enrolledcourses' => new external_multiple_structure(
+                        new external_single_structure(
+                            array(
+                                'id'  => new external_value(PARAM_INT, 'Id of the course'),
+                                'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'),
+                                'shortname' => new external_value(PARAM_RAW, 'Shortname of the course')
+                            )
+                    ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL)
+                )
+            )
+        );
+    }
+
+}
+
+/**
+ * Role functions
+ */
+class core_role_external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function assign_roles_parameters() {
+        return new external_function_parameters(
+            array(
+                'assignments' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'roleid'    => new external_value(PARAM_INT, 'Role to assign to the user'),
+                            'userid'    => new external_value(PARAM_INT, 'The user that is going to be assigned'),
+                            'contextid' => new external_value(PARAM_INT, 'The context to assign the user role in'),
+                        )
+                    )
+                )
+            )
+        );
+    }
+
+    /**
+     * Manual role assignments to users
+     *
+     * @param array $assignment  An array of manual role assignment
+     * @return null
+     */
+    public static function assign_roles($assignments) {
+        global $DB;
+
+        // Do basic automatic PARAM checks on incoming data, using params description
+        // If any problems are found then exceptions are thrown with helpful error messages
+        $params = self::validate_parameters(self::assign_roles_parameters(), array('assignments'=>$assignments));
+
+        $transaction = $DB->start_delegated_transaction();
+
+        foreach ($params['assignments'] as $assignment) {
+            // Ensure the current user is allowed to run this function in the enrolment context
+            $context = get_context_instance_by_id($assignment['contextid']);
+            self::validate_context($context);
+            require_capability('moodle/role:assign', $context);
+
+            // throw an exception if user is not able to assign the role in this context
+            $roles = get_assignable_roles($context, ROLENAME_SHORT);
+
+            if (!key_exists($assignment['roleid'], $roles)) {
+                throw new invalid_parameter_exception('Can not assign roleid='.$assignment['roleid'].' in contextid='.$assignment['contextid']);
+            }
+
+            role_assign($assignment['roleid'], $assignment['userid'], $assignment['contextid']);
+        }
+
+        $transaction->allow_commit();
+    }
 
+    /**
+     * Returns description of method result value
+     * @return external_description
+     */
+    public static function assign_roles_returns() {
+        return null;
+    }
+
+
+    /**
+     * Returns description of method parameters
+     * @return external_function_parameters
+     */
+    public static function unassign_roles_parameters() {
+        return new external_function_parameters(
+            array(
+                'unassignments' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'roleid'    => new external_value(PARAM_INT, 'Role to assign to the user'),
+                            'userid'    => new external_value(PARAM_INT, 'The user that is going to be assigned'),
+                            'contextid' => new external_value(PARAM_INT, 'The context to unassign the user role from'),
+                        )
+                    )
+                )
+            )
+        );
+    }
+
+     /**
+     * Unassign roles from users
+     *
+     * @param array $unassignment  An array of unassignment
+     * @return null
+     */
+    public static function unassign_roles($unassignments) {
+         global $DB;
+
+        // Do basic automatic PARAM checks on incoming data, using params description
+        // If any problems are found then exceptions are thrown with helpful error messages
+        $params = self::validate_parameters(self::unassign_roles_parameters(), array('unassignments'=>$unassignments));
+
+        $transaction = $DB->start_delegated_transaction();
+
+        foreach ($params['unassignments'] as $unassignment) {
+            // Ensure the current user is allowed to run this function in the unassignment context
+            $context = get_context_instance_by_id($unassignment['contextid']);
+            self::validate_context($context);
+            require_capability('moodle/role:assign', $context);
+
+            // throw an exception if user is not able to unassign the role in this context
+            $roles = get_assignable_roles($context, ROLENAME_SHORT);
+            if (!key_exists($unassignment['roleid'], $roles)) {
+                throw new invalid_parameter_exception('Can not unassign roleid='.$unassignment['roleid'].' in contextid='.$unassignment['contextid']);
+            }
+
+            role_unassign($unassignment['roleid'], $unassignment['userid'], $unassignment['contextid']);
+        }
+
+        $transaction->allow_commit();
+    }
+
+   /**
+     * Returns description of method result value
+     * @return null
+     */
+    public static function unassign_roles_returns() {
+        return null;
+    }
+}
+
+
+/**
+ * Deprecated enroll and role functions
+ * @deprecated since Moodle 2.2 please use core_enrol_external or core_role_external instead
+ */
 class moodle_enrol_external extends external_api {
 
 
     /**
      * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_enrolled_users_parameters() instead
      * @return external_function_parameters
      */
     public static function get_enrolled_users_parameters() {
@@ -52,7 +455,7 @@ class moodle_enrol_external extends external_api {
 
     /**
      * Get list of course participants.
-     *
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_enrolled_users() instead
      * @param int $courseid
      * @param text $withcapability
      * @param int $groupid
@@ -143,6 +546,7 @@ class moodle_enrol_external extends external_api {
 
     /**
      * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_enrolled_users_returns() instead
      * @return external_description
      */
     public static function get_enrolled_users_returns() {
@@ -164,192 +568,89 @@ class moodle_enrol_external extends external_api {
 
     /**
      * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_users_courses_parameters() instead
      * @return external_function_parameters
      */
     public static function get_users_courses_parameters() {
-        return new external_function_parameters(
-            array(
-                'userid' => new external_value(PARAM_INT, 'user id'),
-            )
-        );
+        return core_enrol_external::get_users_courses_parameters();
     }
 
     /**
      * Get list of courses user is enrolled in (only active enrolments are returned).
      *
      * Please note the current user must be able to access the course, otherwise the course is not included.
-     *
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_users_courses() instead
      * @param int $userid
      * @return array of courses
      */
     public static function get_users_courses($userid) {
-        global $USER;
-
-        // Do basic automatic PARAM checks on incoming data, using params description
-        // If any problems are found then exceptions are thrown with helpful error messages
-        $params = self::validate_parameters(self::get_users_courses_parameters(), array('userid'=>$userid));
-
-        $courses = enrol_get_users_courses($params['userid'], true, 'id, shortname, fullname, idnumber, visible');
-        $result = array();
-
-        foreach ($courses as $course) {
-            $context = get_context_instance(CONTEXT_COURSE, $course->id);
-            try {
-                self::validate_context($context);
-            } catch (Exception $e) {
-                // current user can not access this course, sorry we can not disclose who is enrolled in this course!
-                continue;
-            }
-            if ($userid != $USER->id and !has_capability('moodle/course:viewparticipants', $context)) {
-                // we need capability to view participants
-                continue;
-            }
-
-            $result[] = array('id'=>$course->id, 'shortname'=>$course->shortname, 'fullname'=>$course->fullname, 'idnumber'=>$course->idnumber,'visible'=>$course->visible);
-        }
-
-        return $result;
+        return core_enrol_external::get_users_courses($userid);
     }
 
     /**
      * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_enrol_external::get_users_courses_returns() instead
      * @return external_description
      */
     public static function get_users_courses_returns() {
-        return new external_multiple_structure(
-            new external_single_structure(
-                array(
-                    'id'        => new external_value(PARAM_INT, 'id of course'),
-                    'shortname' => new external_value(PARAM_RAW, 'short name of course'),
-                    'fullname'  => new external_value(PARAM_RAW, 'long name of course'),
-                    'idnumber'  => new external_value(PARAM_RAW, 'id number of course'),
-                    'visible'   => new external_value(PARAM_INT, '1 means visible, 0 means hidden course'),
-                )
-            )
-        );
+        return core_enrol_external::get_users_courses_returns();
     }
 
 
     /**
      * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_role_external::assign_roles_parameters() instead
      * @return external_function_parameters
      */
     public static function role_assign_parameters() {
-        return new external_function_parameters(
-            array(
-                'assignments' => new external_multiple_structure(
-                    new external_single_structure(
-                        array(
-                            'roleid'    => new external_value(PARAM_INT, 'Role to assign to the user'),
-                            'userid'    => new external_value(PARAM_INT, 'The user that is going to be assigned'),
-                            'contextid' => new external_value(PARAM_INT, 'The context to assign the user role in'),
-                        )
-                    )
-                )
-            )
-        );
+        return core_role_external::assign_roles_parameters();
     }
 
     /**
      * Manual role assignments to users
-     *
+     * @deprecated since Moodle 2.2 please use core_role_external::assign_roles() instead
      * @param array $assignment  An array of manual role assignment
      * @return null
      */
     public static function role_assign($assignments) {
-        global $DB;
-
-        // Do basic automatic PARAM checks on incoming data, using params description
-        // If any problems are found then exceptions are thrown with helpful error messages
-        $params = self::validate_parameters(self::role_assign_parameters(), array('assignments'=>$assignments));
-
-        $transaction = $DB->start_delegated_transaction();
-
-        foreach ($params['assignments'] as $assignment) {
-            // Ensure the current user is allowed to run this function in the enrolment context
-            $context = get_context_instance_by_id($assignment['contextid']);
-            self::validate_context($context);
-            require_capability('moodle/role:assign', $context);
-
-            // throw an exception if user is not able to assign the role in this context
-            $roles = get_assignable_roles($context, ROLENAME_SHORT);
-            if (!key_exists($assignment['roleid'], $roles)) {
-                throw new invalid_parameter_exception('Can not assign roleid='.$assignment['roleid'].' in contextid='.$assignment['contextid']);
-            }
-
-            role_assign($assignment['roleid'], $assignment['userid'], $assignment['contextid']);
-        }
-
-        $transaction->allow_commit();
+        return core_role_external::assign_roles($assignments);
     }
 
     /**
      * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_role_external::assign_roles_returns() instead
      * @return external_description
      */
     public static function role_assign_returns() {
-        return null;
+        return core_role_external::assign_roles_returns();
     }
 
 
     /**
      * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_role_external::unassign_roles_parameters() instead
      * @return external_function_parameters
      */
     public static function role_unassign_parameters() {
-        return new external_function_parameters(
-            array(
-                'unassignments' => new external_multiple_structure(
-                    new external_single_structure(
-                        array(
-                            'roleid'    => new external_value(PARAM_INT, 'Role to assign to the user'),
-                            'userid'    => new external_value(PARAM_INT, 'The user that is going to be assigned'),
-                            'contextid' => new external_value(PARAM_INT, 'The context to unassign the user role from'),
-                        )
-                    )
-                )
-            )
-        );
+        return core_role_external::unassign_roles_parameters();
     }
 
      /**
      * Unassign roles from users
-     *
+     * @deprecated since Moodle 2.2 please use core_role_external::unassign_roles() instead
      * @param array $unassignment  An array of unassignment
      * @return null
      */
     public static function role_unassign($unassignments) {
-         global $DB;
-
-        // Do basic automatic PARAM checks on incoming data, using params description
-        // If any problems are found then exceptions are thrown with helpful error messages
-        $params = self::validate_parameters(self::role_unassign_parameters(), array('unassignments'=>$unassignments));
-
-        $transaction = $DB->start_delegated_transaction();
-
-        foreach ($params['unassignments'] as $unassignment) {
-            // Ensure the current user is allowed to run this function in the unassignment context
-            $context = get_context_instance_by_id($unassignment['contextid']);
-            self::validate_context($context);
-            require_capability('moodle/role:assign', $context);
-
-            // throw an exception if user is not able to unassign the role in this context
-            $roles = get_assignable_roles($context, ROLENAME_SHORT);
-            if (!key_exists($unassignment['roleid'], $roles)) {
-                throw new invalid_parameter_exception('Can not unassign roleid='.$unassignment['roleid'].' in contextid='.$unassignment['contextid']);
-            }
-
-            role_unassign($unassignment['roleid'], $unassignment['userid'], $unassignment['contextid']);
-        }
-
-        $transaction->allow_commit();
+         return core_role_external::unassign_roles($unassignments);
     }
 
    /**
      * Returns description of method result value
+    * @deprecated since Moodle 2.2 please use core_role_external::unassign_roles_returns() instead
      * @return external_description
      */
     public static function role_unassign_returns() {
-        return null;
+        return core_role_external::unassign_roles_returns();
     }
 }
index cd49d1b..4b41d24 100644 (file)
@@ -28,8 +28,17 @@ $functions = array(
 
     // === enrol related functions ===
     'moodle_enrol_manual_enrol_users' => array(
-        'classname'   => 'moodle_enrol_manual_external',
-        'methodname'  => 'manual_enrol_users',
+        'classname'   => 'enrol_manual_external',
+        'methodname'  => 'enrol_users',
+        'classpath'   => 'enrol/manual/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as enrol_manual_enrol_users()',
+        'capabilities'=> 'enrol/manual:enrol',
+        'type'        => 'write',
+    ),
+
+    'enrol_manual_enrol_users' => array(
+        'classname'   => 'enrol_manual_external',
+        'methodname'  => 'enrol_users',
         'classpath'   => 'enrol/manual/externallib.php',
         'description' => 'Manual enrol users',
         'capabilities'=> 'enrol/manual:enrol',
index 2edc992..f2daf62 100644 (file)
@@ -29,13 +29,16 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once("$CFG->libdir/externallib.php");
 
-class moodle_enrol_manual_external extends external_api {
+/**
+ * Manual enrolment functions
+ */
+class enrol_manual_external extends external_api {
 
     /**
      * Returns description of method parameters
      * @return external_function_parameters
      */
-    public static function manual_enrol_users_parameters() {
+    public static function enrol_users_parameters() {
         return new external_function_parameters(
                 array(
                     'enrolments' => new external_multiple_structure(
@@ -60,12 +63,12 @@ class moodle_enrol_manual_external extends external_api {
      * @param array $enrolments  An array of user enrolment
      * @return null
      */
-    public static function manual_enrol_users($enrolments) {
+    public static function enrol_users($enrolments) {
         global $DB, $CFG;
 
         require_once($CFG->libdir . '/enrollib.php');
 
-        $params = self::validate_parameters(self::manual_enrol_users_parameters(),
+        $params = self::validate_parameters(self::enrol_users_parameters(),
                 array('enrolments' => $enrolments));
 
         $transaction = $DB->start_delegated_transaction(); //rollback all enrolment if an error occurs
@@ -134,10 +137,47 @@ class moodle_enrol_manual_external extends external_api {
 
     /**
      * Returns description of method result value
+     * @return null
+     */
+    public static function enrol_users_returns() {
+        return null;
+    }
+
+}
+
+/**
+ * Deprecated manual enrolment functions
+ * @deprecated since Moodle 2.2 please use enrol_manual_external instead
+ */
+class moodle_enrol_manual_external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use enrol_manual_external::enrol_users_parameters instead
+     * @return external_function_parameters
+     */
+    public static function manual_enrol_users_parameters() {
+        return enrol_manual_external::enrol_users_parameters();
+    }
+
+    /**
+     * Enrolment of users
+     * Function throw an exception at the first error encountered.
+     * @deprecated since Moodle 2.2 please use enrol_manual_external::enrol_users instead
+     * @param array $enrolments  An array of user enrolment
+     * @return null
+     */
+    public static function manual_enrol_users($enrolments) {
+        return enrol_manual_external::enrol_users($enrolments);
+    }
+
+    /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use enrol_manual_external::enrol_users_returns instead
      * @return external_description
      */
     public static function manual_enrol_users_returns() {
-        return null;
+        return enrol_manual_external::enrol_users_returns();
     }
 
 }
index ab5a3b2..b2bfb82 100644 (file)
@@ -258,7 +258,7 @@ class enrol_manual_editselectedusers_operation extends enrol_bulk_enrolment_oper
                 foreach ($user->enrolments as $enrolment) {
                     $enrolment->courseid  = $enrolment->enrolmentinstance->courseid;
                     $enrolment->enrol     = 'manual';
-                    events_trigger('user_unenrol_modified', $enrolment);
+                    events_trigger('user_enrol_modified', $enrolment);
                 }
             }
             return true;
index 5f2e9e6..e011c76 100644 (file)
@@ -26,4 +26,4 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2010071201;
+$plugin->version = 2010071201.02;
index 16e5d59..6e4152e 100644 (file)
@@ -56,6 +56,13 @@ $handlers = array (
         'internal'         => 1,
     ),
 
+    'user_enrol_modified' => array (
+        'handlerfile'      => '/enrol/meta/locallib.php',
+        'handlerfunction'  => array('enrol_meta_handler', 'user_enrol_modified'),
+        'schedule'         => 'instant',
+        'internal'         => 1,
+    ),
+
     'course_deleted' => array (
         'handlerfile'      => '/enrol/meta/locallib.php',
         'handlerfunction'  => array('enrol_meta_handler', 'course_deleted'),
index c8676dd..0b1e04f 100644 (file)
@@ -139,8 +139,20 @@ class enrol_meta_handler {
 
         $plugin = enrol_get_plugin('meta');
         foreach ($enrols as $enrol) {
+            if ($ue->status == ENROL_USER_ACTIVE) {
+                $status = ENROL_USER_ACTIVE;
+            } else {
+                $context = get_context_instance(CONTEXT_COURSE, $enrol->courseid);
+                if (is_enrolled($context, $ue->userid)) {
+                    // user already has active enrolment, do not change it
+                    $status = ENROL_USER_ACTIVE;
+                } else {
+                    $status = $ue->status;
+                }
+
+            }
             // no problem if already enrolled
-            $plugin->enrol_user($enrol, $ue->userid);
+            $plugin->enrol_user($enrol, $ue->userid, $status);
         }
 
         return true;
@@ -171,6 +183,33 @@ class enrol_meta_handler {
         return true;
     }
 
+    public function user_enrol_modified($ue) {
+        global $DB;
+
+        // update enrolment status if necessary
+
+        if (!enrol_is_enabled('meta')) {
+            return true;
+        }
+
+        if ($ue->enrol === 'meta') {
+            // prevent circular dependencies - we can not sync meta enrolments recursively
+            return true;
+        }
+
+        // does anything want to sync with this parent?
+        if (!$enrols = $DB->get_records('enrol', array('customint1'=>$ue->courseid, 'enrol'=>'meta'), 'id ASC')) {
+            return true;
+        }
+
+        $plugin = enrol_get_plugin('meta');
+        foreach ($enrols as $enrol) {
+            $plugin->update_user_enrol($enrol, $ue->userid, $ue->status);
+        }
+
+        return true;
+    }
+
     public function course_deleted($course) {
         global $DB;
 
@@ -207,6 +246,8 @@ function enrol_meta_sync($courseid = NULL) {
     // unfortunately this may take a loooong time
     @set_time_limit(0); //if this fails during upgrade we can continue from cron, no big deal
 
+    $instances = array(); //cache
+
     $meta = enrol_get_plugin('meta');
 
     $onecourse = $courseid ? "AND e.courseid = :courseid" : "";
@@ -214,10 +255,8 @@ function enrol_meta_sync($courseid = NULL) {
     // iterate through all not enrolled yet users
     if (enrol_is_enabled('meta')) {
         list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
-        $onecourse = "";
         if ($courseid) {
             $params['courseid'] = $courseid;
-            $onecourse = "AND e.courseid = :courseid";
         }
         $sql = "SELECT pue.userid, e.id AS enrolid
                   FROM {user_enrolments} pue
@@ -229,7 +268,6 @@ function enrol_meta_sync($courseid = NULL) {
         $params['courseid'] = $courseid;
 
         $rs = $DB->get_recordset_sql($sql, $params);
-        $instances = array(); //cache
         foreach($rs as $ue) {
             if (!isset($instances[$ue->enrolid])) {
                 $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
@@ -237,7 +275,6 @@ function enrol_meta_sync($courseid = NULL) {
             $meta->enrol_user($instances[$ue->enrolid], $ue->userid);
         }
         $rs->close();
-        unset($instances);
     }
 
     // unenrol as necessary - ignore enabled flag, we want to get rid of all
@@ -251,7 +288,6 @@ function enrol_meta_sync($courseid = NULL) {
              WHERE pue.courseid IS NULL";
     //TODO: this may use a bit of SQL optimisation
     $rs = $DB->get_recordset_sql($sql, array('courseid'=>$courseid));
-    $instances = array(); //cache
     foreach($rs as $ue) {
         if (!isset($instances[$ue->enrolid])) {
             $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
@@ -259,7 +295,6 @@ function enrol_meta_sync($courseid = NULL) {
         $meta->unenrol_user($instances[$ue->enrolid], $ue->userid);
     }
     $rs->close();
-    unset($instances);
 
     // now assign all necessary roles
     if (enrol_is_enabled('meta')) {
@@ -320,4 +355,61 @@ function enrol_meta_sync($courseid = NULL) {
     }
     $rs->close();
 
+    // sync enrolment status
+    if (enrol_is_enabled('meta')) {
+        list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+        if ($courseid) {
+            $params['courseid'] = $courseid;
+        }
+        //note: this will probably take a long time on mysql...
+        $sql = "SELECT ue.userid, e.id AS enrolid
+                  FROM {user_enrolments} ue
+                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
+                 WHERE ue.status = :activestatus1
+                       AND NOT EXISTS (SELECT 'x'
+                                         FROM {user_enrolments} pue
+                                         JOIN {enrol} pe ON (pe.courseid = e.customint1 AND pe.enrol <> 'meta' AND pe.enrol $enabled)
+                                        WHERE pue.enrolid = pe.id AND pue.userid = ue.userid AND pue.status = :activestatus2)";
+        $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
+        $params['activestatus1'] = ENROL_USER_ACTIVE;
+        $params['activestatus2'] = ENROL_USER_ACTIVE;
+        $params['courseid'] = $courseid;
+
+        $rs = $DB->get_recordset_sql($sql, $params);
+        foreach($rs as $ue) {
+            if (!isset($instances[$ue->enrolid])) {
+                $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+            }
+            $meta->update_user_enrol($instances[$ue->enrolid], $ue->userid, ENROL_USER_SUSPENDED);
+        }
+        $rs->close();
+
+        list($enabled, $params) = $DB->get_in_or_equal(explode(',', $CFG->enrol_plugins_enabled), SQL_PARAMS_NAMED, 'e');
+        if ($courseid) {
+            $params['courseid'] = $courseid;
+        }
+        //note: this will probably take a long time on mysql...
+        $sql = "SELECT ue.userid, e.id AS enrolid
+                  FROM {user_enrolments} ue
+                  JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'meta' AND e.status = :statusenabled $onecourse)
+                 WHERE ue.status = :suspendedstatus
+                       AND EXISTS (SELECT 'x'
+                                     FROM {user_enrolments} pue
+                                     JOIN {enrol} pe ON (pe.courseid = e.customint1 AND pe.enrol <> 'meta' AND pe.enrol $enabled)
+                                    WHERE pue.enrolid = pe.id AND pue.userid = ue.userid AND pue.status = :activestatus)";
+        $params['statusenabled'] = ENROL_INSTANCE_ENABLED;
+        $params['suspendedstatus'] = ENROL_USER_SUSPENDED;
+        $params['activestatus'] = ENROL_USER_ACTIVE;
+        $params['courseid'] = $courseid;
+        $rs = $DB->get_recordset_sql($sql, $params);
+        foreach($rs as $ue) {
+            if (!isset($instances[$ue->enrolid])) {
+                $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
+            }
+            $meta->update_user_enrol($instances[$ue->enrolid], $ue->userid, ENROL_USER_ACTIVE);
+        }
+        $rs->close();
+
+    }
+
 }
index 86366f0..a25f379 100644 (file)
@@ -26,5 +26,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2010073100;
+$plugin->version = 2010073101;
 $plugin->cron    = 60;
\ No newline at end of file
index 4fb4c49..55eecf1 100644 (file)
@@ -6,3 +6,4 @@ information provided here is intended especially for developers.
 required changes in code:
 * load_temp_role() is deprecated, use load_temp_course_role() instead, temp role not loaded
 * remove_temp_role() is deprecated, use remove_temp_course_roles() instead
+* 'user_unenrol_modified' event was renamed to 'user_enrol_modified'
index d71cb72..530f18d 100644 (file)
 require_once("$CFG->libdir/externallib.php");
 require_once("$CFG->libdir/filelib.php");
 
-class moodle_file_external extends external_api {
+/**
+ * Files functions
+ */
+class core_files_external extends external_api {
 
     /**
      * Returns description of get_files parameters
@@ -296,3 +299,77 @@ class moodle_file_external extends external_api {
         );
     }
 }
+
+/**
+ * Deprecated files functions
+ * @deprecated since Moodle 2.2 please use core_files_external instead
+ */
+class moodle_file_external extends external_api {
+
+    /**
+     * Returns description of get_files parameters
+     * @deprecated since Moodle 2.2 please use core_files_external::get_files_parameters instead
+     * @return external_function_parameters
+     */
+    public static function get_files_parameters() {
+        return core_files_external::get_files_parameters();
+    }
+
+    /**
+     * Return moodle files listing
+     * @deprecated since Moodle 2.2 please use core_files_external::get_files instead
+     * @param int $contextid
+     * @param int $component
+     * @param int $filearea
+     * @param int $itemid
+     * @param string $filepath
+     * @param string $filename
+     * @return array
+     */
+    public static function get_files($contextid, $component, $filearea, $itemid, $filepath, $filename) {
+        return core_files_external::get_files($contextid, $component, $filearea, $itemid, $filepath, $filename);
+    }
+
+    /**
+     * Returns description of get_files returns
+     * @deprecated since Moodle 2.2 please use core_files_external::get_files_returns instead
+     * @return external_multiple_structure
+     */
+    public static function get_files_returns() {
+        return core_files_external::get_files_returns();
+    }
+
+    /**
+     * Returns description of upload parameters
+     * @deprecated since Moodle 2.2 please use core_files_external::upload_parameters instead
+     * @return external_function_parameters
+     */
+    public static function upload_parameters() {
+        return core_files_external::upload_parameters();
+    }
+
+    /**
+     * Uploading a file to moodle
+     * @deprecated since Moodle 2.2 please use core_files_external::upload instead
+     * @param int $contextid
+     * @param string $component
+     * @param string $filearea
+     * @param int $itemid
+     * @param string $filepath
+     * @param string $filename
+     * @param string $filecontent
+     * @return array
+     */
+    public static function upload($contextid, $component, $filearea, $itemid, $filepath, $filename, $filecontent) {
+        return core_files_external::upload($contextid, $component, $filearea, $itemid, $filepath, $filename, $filecontent);
+    }
+
+    /**
+     * Returns description of upload returns
+     * @deprecated since Moodle 2.2 please use core_files_external::upload_returns instead
+     * @return external_multiple_structure
+     */
+    public static function upload_returns() {
+        return core_files_external::upload_returns();
+    }
+}
index a37cf64..160dcbf 100644 (file)
 
 require_once("$CFG->libdir/externallib.php");
 
-class moodle_group_external extends external_api {
+/**
+ * Group functions
+ */
+class core_group_external extends external_api {
 
     /**
      * Returns description of method parameters
@@ -305,7 +308,7 @@ class moodle_group_external extends external_api {
      * Returns description of method parameters
      * @return external_function_parameters
      */
-    public static function get_groupmembers_parameters() {
+    public static function get_group_members_parameters() {
         return new external_function_parameters(
             array(
                 'groupids' => new external_multiple_structure(new external_value(PARAM_INT, 'Group ID')),
@@ -318,10 +321,10 @@ class moodle_group_external extends external_api {
      * @param array $groupids array of group ids
      * @return array with  group id keys containing arrays of user ids
      */
-    public static function get_groupmembers($groupids) {
+    public static function get_group_members($groupids) {
         $members = array();
 
-        $params = self::validate_parameters(self::get_groupmembers_parameters(), array('groupids'=>$groupids));
+        $params = self::validate_parameters(self::get_group_members_parameters(), array('groupids'=>$groupids));
 
         foreach ($params['groupids'] as $groupid) {
             // validate params
@@ -351,7 +354,7 @@ class moodle_group_external extends external_api {
      * Returns description of method result value
      * @return external_description
      */
-    public static function get_groupmembers_returns() {
+    public static function get_group_members_returns() {
         return new external_multiple_structure(
             new external_single_structure(
                 array(
@@ -367,7 +370,7 @@ class moodle_group_external extends external_api {
      * Returns description of method parameters
      * @return external_function_parameters
      */
-    public static function add_groupmembers_parameters() {
+    public static function add_group_members_parameters() {
         return new external_function_parameters(
             array(
                 'members'=> new external_multiple_structure(
@@ -387,11 +390,11 @@ class moodle_group_external extends external_api {
      * @param array $members of arrays with keys userid, groupid
      * @return void
      */
-    public static function add_groupmembers($members) {
+    public static function add_group_members($members) {
         global $CFG, $DB;
         require_once("$CFG->dirroot/group/lib.php");
 
-        $params = self::validate_parameters(self::add_groupmembers_parameters(), array('members'=>$members));
+        $params = self::validate_parameters(self::add_group_members_parameters(), array('members'=>$members));
 
         $transaction = $DB->start_delegated_transaction();
         foreach ($params['members'] as $member) {
@@ -429,9 +432,9 @@ class moodle_group_external extends external_api {
 
    /**
      * Returns description of method result value
-     * @return external_description
+     * @return null
      */
-    public static function add_groupmembers_returns() {
+    public static function add_group_members_returns() {
         return null;
     }
 
@@ -440,7 +443,7 @@ class moodle_group_external extends external_api {
      * Returns description of method parameters
      * @return external_function_parameters
      */
-    public static function delete_groupmembers_parameters() {
+    public static function delete_group_members_parameters() {
         return new external_function_parameters(
             array(
                 'members'=> new external_multiple_structure(
@@ -460,11 +463,11 @@ class moodle_group_external extends external_api {
      * @param array $members of arrays with keys userid, groupid
      * @return void
      */
-    public static function delete_groupmembers($members) {
+    public static function delete_group_members($members) {
         global $CFG, $DB;
         require_once("$CFG->dirroot/group/lib.php");
 
-        $params = self::validate_parameters(self::delete_groupmembers_parameters(), array('members'=>$members));
+        $params = self::validate_parameters(self::delete_group_members_parameters(), array('members'=>$members));
 
         $transaction = $DB->start_delegated_transaction();
 
@@ -497,10 +500,217 @@ class moodle_group_external extends external_api {
 
    /**
      * Returns description of method result value
-     * @return external_description
+     * @return null
      */
-    public static function delete_groupmembers_returns() {
+    public static function delete_group_members_returns() {
         return null;
     }
 
 }
+
+/**
+ * Deprecated group functions
+ * @deprecated since Moodle 2.2 please use core_group_external instead
+ */
+class moodle_group_external extends external_api {
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::create_groups_parameters instead
+     * @return external_function_parameters
+     */
+    public static function create_groups_parameters() {
+        return core_group_external::create_groups_parameters();
+    }
+
+    /**
+     * Create groups
+     * @deprecated since Moodle 2.2 please use core_group_external::create_groups instead
+     * @param array $groups array of group description arrays (with keys groupname and courseid)
+     * @return array of newly created groups
+     */
+    public static function create_groups($groups) {
+        return core_group_external::create_groups($groups);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::create_groups_returns instead
+     * @return external_description
+     */
+    public static function create_groups_returns() {
+        return core_group_external::create_groups_returns();
+    }
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::get_groups_parameters instead
+     * @return external_function_parameters
+     */
+    public static function get_groups_parameters() {
+        return core_group_external::get_groups_parameters();
+    }
+
+    /**
+     * Get groups definition specified by ids
+     * @deprecated since Moodle 2.2 please use core_group_external::get_groups instead
+     * @param array $groupids arrays of group ids
+     * @return array of group objects (id, courseid, name, enrolmentkey)
+     */
+    public static function get_groups($groupids) {
+        return core_group_external::get_groups($groupids);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::get_groups_returns instead
+     * @return external_description
+     */
+    public static function get_groups_returns() {
+        return core_group_external::get_groups_returns();
+    }
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::get_course_groups_parameters instead
+     * @return external_function_parameters
+     */
+    public static function get_course_groups_parameters() {
+        return core_group_external::get_course_groups_parameters();
+    }
+
+    /**
+     * Get all groups in the specified course
+     * @deprecated since Moodle 2.2 please use core_group_external::get_course_groups instead
+     * @param int $courseid id of course
+     * @return array of group objects (id, courseid, name, enrolmentkey)
+     */
+    public static function get_course_groups($courseid) {
+        return core_group_external::get_course_groups($courseid);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::get_course_groups_returns instead
+     * @return external_description
+     */
+    public static function get_course_groups_returns() {
+        return core_group_external::get_course_groups_returns();
+    }
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::delete_group_members_parameters instead
+     * @return external_function_parameters
+     */
+    public static function delete_groups_parameters() {
+        return core_group_external::delete_group_members_parameters();
+    }
+
+    /**
+     * Delete groups
+     * @deprecated since Moodle 2.2 please use core_group_external::delete_groups instead
+     * @param array $groupids array of group ids
+     * @return void
+     */
+    public static function delete_groups($groupids) {
+        return core_group_external::delete_groups($groupids);
+    }
+
+   /**
+     * Returns description of method result value
+    * @deprecated since Moodle 2.2 please use core_group_external::delete_group_members_returns instead
+     * @return external_description
+     */
+    public static function delete_groups_returns() {
+        return core_group_external::delete_group_members_returns();
+    }
+
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::get_group_members_parameters instead
+     * @return external_function_parameters
+     */
+    public static function get_groupmembers_parameters() {
+        return core_group_external::get_group_members_parameters();
+    }
+
+    /**
+     * Return all members for a group
+     * @deprecated since Moodle 2.2 please use core_group_external::get_group_members instead
+     * @param array $groupids array of group ids
+     * @return array with  group id keys containing arrays of user ids
+     */
+    public static function get_groupmembers($groupids) {
+        return core_group_external::get_group_members($groupids);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::get_group_members_returns instead
+     * @return external_description
+     */
+    public static function get_groupmembers_returns() {
+        return core_group_external::get_group_members_returns();
+    }
+
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::add_group_members_parameters instead
+     * @return external_function_parameters
+     */
+    public static function add_groupmembers_parameters() {
+        return core_group_external::add_group_members_parameters();
+    }
+
+    /**
+     * Add group members
+     * @deprecated since Moodle 2.2 please use core_group_external::add_group_members instead
+     * @param array $members of arrays with keys userid, groupid
+     * @return void
+     */
+    public static function add_groupmembers($members) {
+        return core_group_external::add_group_members($members);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::add_group_members_returns instead
+     * @return external_description
+     */
+    public static function add_groupmembers_returns() {
+        return core_group_external::add_group_members_returns();
+    }
+
+
+    /**
+     * Returns description of method parameters
+     * @deprecated since Moodle 2.2 please use core_group_external::delete_group_members_parameters instead
+     * @return external_function_parameters
+     */
+    public static function delete_groupmembers_parameters() {
+        return core_group_external::delete_group_members_parameters();
+    }
+
+    /**
+     * Delete group members
+     * @deprecated since Moodle 2.2 please use core_group_external::delete_group_members instead
+     * @param array $members of arrays with keys userid, groupid
+     * @return void
+     */
+    public static function delete_groupmembers($members) {
+        return core_group_external::delete_group_members($members);
+    }
+
+   /**
+     * Returns description of method result value
+     * @deprecated since Moodle 2.2 please use core_group_external::delete_group_members_returns instead
+     * @return external_description
+     */
+    public static function delete_groupmembers_returns() {
+        return core_group_external::delete_group_members_returns();
+    }
+
+}
\ No newline at end of file
index 0f626f8..1ca55e4 100644 (file)
@@ -191,7 +191,6 @@ $string['configenablecomments'] = 'Enable comments';
 $string['configenablecourserequests'] = 'This will allow any user to request a course be created.';
 $string['configenableglobalsearch'] = 'This setting enables global text searching in resources and activities, it is not compatible with PHP 4.';
 $string['configenablegroupmembersonly'] = 'If enabled, access to activities can be restricted to group members only. This may result in an increased server load. In addition, gradebook categories must be set up in a certain way to ensure that activities are hidden from non-group members.';
-$string['configenablehtmlpurifier'] = 'Use HTML Purifier instead of KSES for cleaning of untrusted text. HTML Purifier is actively developed and is believed to be more secure, but it is more resource intensive. Expect minor visual differences in the resulting html code. Please note that embed and object tags can not be enabled, MathML tags and old lang tags are not supported.';
 $string['configenablemobilewebservice'] = 'Enable mobile service for the official Moodle app or other app requesting it. For more information, read the {$a}';
 $string['configenablerssfeeds'] = 'This switch will enable RSS feeds from across the site.  To actually see any change you will need to enable RSS feeds in the individual modules too - go to the Modules settings under Admin Configuration.';
 $string['configenablerssfeedsdisabled'] = 'It is not available because RSS feeds are disabled in all the Site. To enable them, go to the Variables settings under Admin Configuration.';
@@ -473,7 +472,6 @@ $string['enableglobalsearch'] = 'Enable global search';
 $string['enablegravatar'] = 'Enable Gravatar';
 $string['enablegravatar_help'] = 'When enabled Moodle will attempt to fetch a user profile picture from Gravatar if the user has not uploaded an image.';
 $string['enablegroupmembersonly'] = 'Enable group members only';
-$string['enablehtmlpurifier'] = 'Enable HTML Purifier';
 $string['enablemobilewebservice'] = 'Enable mobile web service';
 $string['enablerecordcache'] = 'Enable record cache';
 $string['enablerssfeeds'] = 'Enable RSS feeds';
index dc1bc8f..446e8d7 100644 (file)
@@ -1391,6 +1391,7 @@ $string['rssarticles'] = 'Number of RSS recent articles';
 $string['rsserror'] = 'Error reading RSS data';
 $string['rsserrorauth'] = 'Your RSS link does not contain a valid authentication token.';
 $string['rsserrorguest'] = 'This feed uses guest access to access the data, but guest does not have permission to read the data. Visit the original location that this feed comes from (URL) as a valid user and get a new RSS link from there.';
+$string['rsskeyshelp'] = 'To ensure security and privacy, RSS feed URLs contain a special token that identifies the user they are for. This prevents other users from accessing areas of Moodle they shouldn\'t have access to via RSS feeds.</p><p>This token is automatically created the first time you access an area of Moodle that produces an RSS feed. If you feel that your RSS feed token has been compromised in some way you can request a new one by clicking the Reset link here. Please note that your current RSS feed URLs will then become invalid.';
 $string['rsstype'] = 'RSS feed for this activity';
 $string['saveandnext'] = 'Save and show next';
 $string['savedat'] = 'Saved at:';
index 075ca23..4876027 100644 (file)
@@ -24,7 +24,6 @@
  */
 
 $string['accessexception'] = 'Access control exception';
-$string['accessnotallowed'] = 'Access to web service not allowed';
 $string['actwebserviceshhdr'] = 'Active web service protocols';
 $string['accesstofunctionnotallowed'] = 'Access to the function {$a}() is not allowed. Please check if a service containing the function is enabled. In the service settings: if the service is restricted check that the user is listed. Still in the service settings check for IP restriction or if the service requires a capability.';
 $string['addaservice'] = 'Add service';
@@ -43,7 +42,7 @@ $string['apiexplorer'] = 'API explorer';
 $string['apiexplorernotavalaible'] = 'API explorer not available yet.';
 $string['arguments'] = 'Arguments';
 $string['authmethod'] = 'Authentication method';
-$string['cannotcreatemobiletoken'] = 'No permission to create web service token for mobile access.';
+$string['cannotcreatetoken'] = 'No permission to create web service token for the service {$a}.';
 $string['configwebserviceplugins'] = 'For security reasons, only protocols that are in use should be enabled.';
 $string['context'] = 'Context';
 $string['createservicedescription'] = 'A service is a set of web service functions. You will allow the user to access to a new service. On the <strong>Add service</strong> page check \'Enable\' and \'Authorised users\' options. Select \'No required capability\'.';
@@ -111,6 +110,7 @@ $string['managetokens'] = 'Manage tokens';
 $string['missingcaps'] = 'Missing capabilities';
 $string['missingcaps_help'] = 'List of required capabilities for the service which the selected user does not have. Missing capabilities must be added to the user\'s role in order to use the service.';
 $string['missingpassword'] = 'Missing password';
+$string['missingrequiredcapability'] = 'The capability {$a} is required.';
 $string['missingusername'] = 'Missing username';
 $string['missingversionfile'] = 'Coding error: version.php file is missing for the component {$a}';
 $string['mobilewsdisabled'] = 'Disabled';
@@ -130,6 +130,7 @@ $string['potusers'] = 'Not authorised users';
 $string['potusersmatching'] = 'Not authorised users matching';
 $string['print'] = 'Print all';
 $string['protocol'] = 'Protocol';
+$string['protocolnotallowed'] = 'You are not allowed to use the {$a} protocol (missing capability: webservice/{$a}:use)';
 $string['removefunction'] = 'Remove';
 $string['removefunctionconfirm'] = 'Do you really want to remove function "{$a->function}" from service "{$a->service}"?';
 $string['requireauthentication'] = 'This method requires authentication with xxx permission.';
index 21ba4b4..6ef78db 100644 (file)
@@ -986,6 +986,8 @@ function load_role_access_by_context($roleid, context $context, &$accessdata) {
 
 /**
  * Returns empty accessdata structure.
+ *
+ * @private
  * @return array empt accessdata
  */
 function get_empty_accessdata() {
@@ -1163,6 +1165,7 @@ function reload_all_capabilities() {
  * Adds a temp role to current USER->access array.
  *
  * Useful for the "temporary guest" access we grant to logged-in users.
+ * @since 2.2
  *
  * @param context_course $coursecontext
  * @param int $roleid
@@ -1198,6 +1201,7 @@ function load_temp_course_role(context_course $coursecontext, $roleid) {
 
 /**
  * Removes any extra guest roles from current USER->access array.
+ * @since 2.2
  *
  * @param context_course $coursecontext
  * @return void
@@ -1533,7 +1537,6 @@ function get_roles_with_capability($capability, $permission = null, $context = n
     return $DB->get_records_sql($sql, $params);
 }
 
-
 /**
  * This function makes a role-assignment (a role for a user in a particular context)
  *
@@ -2271,7 +2274,7 @@ function load_capability_def($component) {
         if (!empty(${$component.'_capabilities'})) {
             // BC capability array name
             // since 2.0 we prefer $capabilities instead - it is easier to use and matches db/* files
-            debugging('componentname_capabilities array is deprecated, please use capabilities array only in access.php files');
+            debugging('componentname_capabilities array is deprecated, please use $capabilities array only in access.php files');
             $capabilities = ${$component.'_capabilities'};
         }
     }
@@ -2500,12 +2503,6 @@ function capabilities_cleanup($component, $newcapdef = null) {
     return $removedcount;
 }
 
-
-
-//////////////////
-// UI FUNCTIONS //
-//////////////////
-
 /**
  * Returns an array of all the known types of risk
  * The array keys can be used, for example as CSS class names, or in calls to
@@ -3843,7 +3840,6 @@ function get_roles_on_exact_context(context $context) {
                                    FROM {role_assignments} ra, {role} r
                                   WHERE ra.roleid = r.id AND ra.contextid = ?",
                                 array($context->id));
-
 }
 
 /**
@@ -4426,241 +4422,11 @@ function role_change_permission($roleid, $context, $capname, $permission) {
 }
 
 
-/**
- * Context maintenance and helper methods.
- *
- * This is "extends context" is a bloody hack that tires to work around the deficiencies
- * in the "protected" keyword in PHP, this helps us to hide all the internals of context
- * level implementation from the rest of code, the code completion returns what developers need.
- *
- * Thank you Tim Hunt for helping me with this nasty trick.
- *
- * @author Petr Skoda
- */
-class context_helper extends context {
-
-    private static $alllevels = array(
-            CONTEXT_SYSTEM    => 'context_system',
-            CONTEXT_USER      => 'context_user',
-            CONTEXT_COURSECAT => 'context_coursecat',
-            CONTEXT_COURSE    => 'context_course',
-            CONTEXT_MODULE    => 'context_module',
-            CONTEXT_BLOCK     => 'context_block',
-    );
-
-    /**
-     * Instance does not make sense here, only static use
-     */
-    protected function __construct() {
-    }
-
-    /**
-     * Returns a class name of the context level class
-     *
-     * @static
-     * @param int $contextlevel (CONTEXT_SYSTEM, etc.)
-     * @return string class name of the context class
-     */
-    public static function get_class_for_level($contextlevel) {
-        if (isset(self::$alllevels[$contextlevel])) {
-            return self::$alllevels[$contextlevel];
-        } else {
-            throw new coding_exception('Invalid context level specified');
-        }
-    }
-
-    /**
-     * Returns a list of all context levels
-     *
-     * @static
-     * @return array int=>string (level=>level class name)
-     */
-    public static function get_all_levels() {
-        return self::$alllevels;
-    }
-
-    /**
-     * Remove stale contexts that belonged to deleted instances.
-     * Ideally all code should cleanup contexts properly, unfortunately accidents happen...
-     *
-     * @static
-     * @return void
-     */
-    public static function cleanup_instances() {
-        global $DB;
-        $sqls = array();
-        foreach (self::$alllevels as $level=>$classname) {
-            $sqls[] = $classname::get_cleanup_sql();
-        }
-
-        $sql = implode(" UNION ", $sqls);
-
-        // it is probably better to use transactions, it might be faster too
-        $transaction = $DB->start_delegated_transaction();
-
-        $rs = $DB->get_recordset_sql($sql);
-        foreach ($rs as $record) {
-            $context = context::create_instance_from_record($record);
-            $context->delete();
-        }
-        $rs->close();
-
-        $transaction->allow_commit();
-    }
-
-    /**
-     * Create all context instances at the given level and above.
-     *
-     * @static
-     * @param int $contextlevel null means all levels
-     * @param bool $buildpaths
-     * @return void
-     */
-    public static function create_instances($contextlevel = null, $buildpaths = true) {
-        foreach (self::$alllevels as $level=>$classname) {
-            if ($contextlevel and $level > $contextlevel) {
-                // skip potential sub-contexts
-                continue;
-            }
-            $classname::create_level_instances();
-            if ($buildpaths) {
-                $classname::build_paths(false);
-            }
-        }
-    }
-
-    /**
-     * Rebuild paths and depths in all context levels.
-     *
-     * @static
-     * @param bool $force false means add missing only
-     * @return void
-     */
-    public static function build_all_paths($force = false) {
-        foreach (self::$alllevels as $classname) {
-            $classname::build_paths($force);
-        }
-
-        // reset static course cache - it might have incorrect cached data
-        accesslib_clear_all_caches(true);
-    }
-
-    /**
-     * Resets the cache to remove all data.
-     * @static
-     */
-    public static function reset_caches() {
-        context::reset_caches();
-    }
-
-    /**
-     * Returns all fields necessary for context preloading from user $rec.
-     *
-     * This helps with performance when dealing with hundreds of contexts.
-     *
-     * @static
-     * @param string $tablealias context table alias in the query
-     * @return array (table.column=>alias, ...)
-     */
-    public static function get_preload_record_columns($tablealias) {
-        return array("$tablealias.id"=>"ctxid", "$tablealias.path"=>"ctxpath", "$tablealias.depth"=>"ctxdepth", "$tablealias.contextlevel"=>"ctxlevel", "$tablealias.instanceid"=>"ctxinstance");
-    }
-
-    /**
-     * Returns all fields necessary for context preloading from user $rec.
-     *
-     * This helps with performance when dealing with hundreds of contexts.
-     *
-     * @static
-     * @param string $tablealias context table alias in the query
-     * @return string
-     */
-    public static function get_preload_record_columns_sql($tablealias) {
-        return "$tablealias.id AS ctxid, $tablealias.path AS ctxpath, $tablealias.depth AS ctxdepth, $tablealias.contextlevel AS ctxlevel, $tablealias.instanceid AS ctxinstance";
-    }
-
-    /**
-     * Preloads context information from db record and strips the cached info.
-     *
-     * The db request has to contain all columns from context_helper::get_preload_record_columns().
-     *
-     * @static
-     * @param stdClass $rec
-     * @return void (modifies $rec)
-     */
-     public static function preload_from_record(stdClass $rec) {
-         context::preload_from_record($rec);
-     }
-
-    /**
-     * Preload all contexts instances from course.
-     *
-     * To be used if you expect multiple queries for course activities...
-     *
-     * @static
-     * @param $courseid
-     */
-    public static function preload_course($courseid) {
-        // Users can call this multiple times without doing any harm
-        if (isset(context::$cache_preloaded[$courseid])) {
-            return;
-        }
-        $coursecontext = context_course::instance($courseid);
-        $coursecontext->get_child_contexts();
-
-        context::$cache_preloaded[$courseid] = true;
-    }
-
-    /**
-     * Delete context instance
-     *
-     * @static
-     * @param int $contextlevel
-     * @param int $instanceid
-     * @return void
-     */
-    public static function delete_instance($contextlevel, $instanceid) {
-        global $DB;
-
-        // double check the context still exists
-        if ($record = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) {
-            $context = context::create_instance_from_record($record);
-            $context->delete();
-        } else {
-            // we should try to purge the cache anyway
-        }
-    }
-
-    /**
-     * Returns the name of specified context level
-     *
-     * @static
-     * @param int $contextlevel
-     * @return string name of the context level
-     */
-    public static function get_level_name($contextlevel) {
-        $classname = context_helper::get_class_for_level($contextlevel);
-        return $classname::get_level_name();
-    }
-
-    /**
-     * not used
-     */
-    public function get_url() {
-    }
-
-    /**
-     * not used
-     */
-    public function get_capabilities() {
-    }
-}
-
-
 /**
  * Basic moodle context abstraction class.
  *
  * @author Petr Skoda
+ * @since 2.2
  *
  * @property-read int $id context id
  * @property-read int $contextlevel CONTEXT_SYSTEM, CONTEXT_COURSE, etc.
@@ -4696,6 +4462,7 @@ abstract class context extends stdClass {
 
     /**
      * Resets the cache to remove all data.
+     * @static
      */
     protected static function reset_caches() {
         self::$cache_contextsbyid = array();
@@ -4893,6 +4660,7 @@ abstract class context extends stdClass {
 
     /**
      * This function is also used to work around 'protected' keyword problems in context_helper.
+     * @static
      * @param stdClass $record
      * @return context instance
      */
@@ -5393,9 +5161,242 @@ abstract class context extends stdClass {
 }
 
 
+/**
+ * Context maintenance and helper methods.
+ *
+ * This is "extends context" is a bloody hack that tires to work around the deficiencies
+ * in the "protected" keyword in PHP, this helps us to hide all the internals of context
+ * level implementation from the rest of code, the code completion returns what developers need.
+ *
+ * Thank you Tim Hunt for helping me with this nasty trick.
+ *
+ * @author Petr Skoda
+ * @since 2.2
+ */
+class context_helper extends context {
+
+    private static $alllevels = array(
+            CONTEXT_SYSTEM    => 'context_system',
+            CONTEXT_USER      => 'context_user',
+            CONTEXT_COURSECAT => 'context_coursecat',
+            CONTEXT_COURSE    => 'context_course',
+            CONTEXT_MODULE    => 'context_module',
+            CONTEXT_BLOCK     => 'context_block',
+    );
+
+    /**
+     * Instance does not make sense here, only static use
+     */
+    protected function __construct() {
+    }
+
+    /**
+     * Returns a class name of the context level class
+     *
+     * @static
+     * @param int $contextlevel (CONTEXT_SYSTEM, etc.)
+     * @return string class name of the context class
+     */
+    public static function get_class_for_level($contextlevel) {
+        if (isset(self::$alllevels[$contextlevel])) {
+            return self::$alllevels[$contextlevel];
+        } else {
+            throw new coding_exception('Invalid context level specified');
+        }
+    }
+
+    /**
+     * Returns a list of all context levels
+     *
+     * @static
+     * @return array int=>string (level=>level class name)
+     */
+    public static function get_all_levels() {
+        return self::$alllevels;
+    }
+
+    /**
+     * Remove stale contexts that belonged to deleted instances.
+     * Ideally all code should cleanup contexts properly, unfortunately accidents happen...
+     *
+     * @static
+     * @return void
+     */
+    public static function cleanup_instances() {
+        global $DB;
+        $sqls = array();
+        foreach (self::$alllevels as $level=>$classname) {
+            $sqls[] = $classname::get_cleanup_sql();
+        }
+
+        $sql = implode(" UNION ", $sqls);
+
+        // it is probably better to use transactions, it might be faster too
+        $transaction = $DB->start_delegated_transaction();
+
+        $rs = $DB->get_recordset_sql($sql);
+        foreach ($rs as $record) {
+            $context = context::create_instance_from_record($record);
+            $context->delete();
+        }
+        $rs->close();
+
+        $transaction->allow_commit();
+    }
+
+    /**
+     * Create all context instances at the given level and above.
+     *
+     * @static
+     * @param int $contextlevel null means all levels
+     * @param bool $buildpaths
+     * @return void
+     */
+    public static function create_instances($contextlevel = null, $buildpaths = true) {
+        foreach (self::$alllevels as $level=>$classname) {
+            if ($contextlevel and $level > $contextlevel) {
+                // skip potential sub-contexts
+                continue;
+            }
+            $classname::create_level_instances();
+            if ($buildpaths) {
+                $classname::build_paths(false);
+            }
+        }
+    }
+
+    /**
+     * Rebuild paths and depths in all context levels.
+     *
+     * @static
+     * @param bool $force false means add missing only
+     * @return void
+     */
+    public static function build_all_paths($force = false) {
+        foreach (self::$alllevels as $classname) {
+            $classname::build_paths($force);
+        }
+
+        // reset static course cache - it might have incorrect cached data
+        accesslib_clear_all_caches(true);
+    }
+
+    /**
+     * Resets the cache to remove all data.
+     * @static
+     */
+    public static function reset_caches() {
+        context::reset_caches();
+    }
+
+    /**
+     * Returns all fields necessary for context preloading from user $rec.
+     *
+     * This helps with performance when dealing with hundreds of contexts.
+     *
+     * @static
+     * @param string $tablealias context table alias in the query
+     * @return array (table.column=>alias, ...)
+     */
+    public static function get_preload_record_columns($tablealias) {
+        return array("$tablealias.id"=>"ctxid", "$tablealias.path"=>"ctxpath", "$tablealias.depth"=>"ctxdepth", "$tablealias.contextlevel"=>"ctxlevel", "$tablealias.instanceid"=>"ctxinstance");
+    }
+
+    /**
+     * Returns all fields necessary for context preloading from user $rec.
+     *
+     * This helps with performance when dealing with hundreds of contexts.
+     *
+     * @static
+     * @param string $tablealias context table alias in the query
+     * @return string
+     */
+    public static function get_preload_record_columns_sql($tablealias) {
+        return "$tablealias.id AS ctxid, $tablealias.path AS ctxpath, $tablealias.depth AS ctxdepth, $tablealias.contextlevel AS ctxlevel, $tablealias.instanceid AS ctxinstance";
+    }
+
+    /**
+     * Preloads context information from db record and strips the cached info.
+     *
+     * The db request has to contain all columns from context_helper::get_preload_record_columns().
+     *
+     * @static
+     * @param stdClass $rec
+     * @return void (modifies $rec)
+     */
+     public static function preload_from_record(stdClass $rec) {
+         context::preload_from_record($rec);
+     }
+
+    /**
+     * Preload all contexts instances from course.
+     *
+     * To be used if you expect multiple queries for course activities...
+     *
+     * @static
+     * @param $courseid
+     */
+    public static function preload_course($courseid) {
+        // Users can call this multiple times without doing any harm
+        if (isset(context::$cache_preloaded[$courseid])) {
+            return;
+        }
+        $coursecontext = context_course::instance($courseid);
+        $coursecontext->get_child_contexts();
+
+        context::$cache_preloaded[$courseid] = true;
+    }
+
+    /**
+     * Delete context instance
+     *
+     * @static
+     * @param int $contextlevel
+     * @param int $instanceid
+     * @return void
+     */
+    public static function delete_instance($contextlevel, $instanceid) {
+        global $DB;
+
+        // double check the context still exists
+        if ($record = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) {
+            $context = context::create_instance_from_record($record);
+            $context->delete();
+        } else {
+            // we should try to purge the cache anyway
+        }
+    }
+
+    /**
+     * Returns the name of specified context level
+     *
+     * @static
+     * @param int $contextlevel
+     * @return string name of the context level
+     */
+    public static function get_level_name($contextlevel) {
+        $classname = context_helper::get_class_for_level($contextlevel);
+        return $classname::get_level_name();
+    }
+
+    /**
+     * not used
+     */
+    public function get_url() {
+    }
+
+    /**
+     * not used
+     */
+    public function get_capabilities() {
+    }
+}
+
+
 /**
  * Basic context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_system extends context {
     /**
@@ -5632,6 +5633,7 @@ class context_system extends context {
 /**
  * User context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_user extends context {
     /**
@@ -5799,6 +5801,7 @@ class context_user extends context {
 /**
  * Course category context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_coursecat extends context {
     /**
@@ -6018,6 +6021,7 @@ class context_coursecat extends context {
 /**
  * Course context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_course extends context {
     /**
@@ -6232,6 +6236,7 @@ class context_course extends context {
 /**
  * Course module context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_module extends context {
     /**
@@ -6471,6 +6476,7 @@ class context_module extends context {
 /**
  * Block context class
  * @author Petr Skoda (http://skodak.org)
+ * @since 2.2
  */
 class context_block extends context {
     /**
@@ -6681,12 +6687,20 @@ class context_block extends context {
 }
 
 
-// ============== DEPRECATED ========================
+// ============== DEPRECATED FUNCTIONS ==========================================
+// Old context related functions were deprecated in 2.0, it is recommended
+// to use context classes in new code. Old function can be used when
+// creating patches that are supposed to be backported to older stable branches.
+// These deprecated functions will not be removed in near future,
+// before removing devs will be warned with a debugging message first,
+// then we will add error message and only after that we can remove the functions
+// completely.
 
 
 /**
- * Use load_temp_course_role() instead.
- * @deprecated
+ * Not available any more, use load_temp_course_role() instead.
+ *
+ * @deprecated since 2.2
  * @param stdClass $context
  * @param int $roleid
  * @param array $accessdata
@@ -6698,8 +6712,9 @@ function load_temp_role($context, $roleid, array $accessdata) {
 }
 
 /**
- * Use remove_temp_course_roles() instead
- * @deprecated
+ * Not available any more, use remove_temp_course_roles() instead.
+ *
+ * @deprecated since 2.2
  * @param object $context
  * @param array $accessdata
  * @return array access data
@@ -6712,7 +6727,7 @@ function remove_temp_roles($context, array $accessdata) {
 /**
  * Returns system context or null if can not be created yet.
  *
- * @deprecated
+ * @deprecated since 2.2, use context_system::instance()
  * @param bool $cache use caching
  * @return context system context (null if context table not created yet)
  */
@@ -6724,7 +6739,7 @@ function get_system_context($cache = true) {
  * Get the context instance as an object. This function will create the
  * context instance if it does not exist yet.
  *
- * @deprecated
+ * @deprecated since 2.2, use context_course::instance() or other relevant class instead
  * @param integer $contextlevel The context level, for example CONTEXT_COURSE, or CONTEXT_MODULE.
  * @param integer $instance The instance id. For $level = CONTEXT_COURSE, this would be $course->id,
  *      for $level = CONTEXT_MODULE, this would be $cm->id. And so on. Defaults to 0
@@ -6753,7 +6768,7 @@ function get_context_instance($contextlevel, $instance = 0, $strictness = IGNORE
 /**
  * Get a context instance as an object, from a given context id.
  *
- * @deprecated
+ * @deprecated since 2.2, use context::instance_by_id($id) instead
  * @param int $id context id
  * @param int $strictness IGNORE_MISSING means compatible mode, false returned if record not found, debug message if more found;
  *                        MUST_EXIST means throw exception if no record or multiple records found
@@ -6768,7 +6783,7 @@ function get_context_instance_by_id($id, $strictness = IGNORE_MISSING) {
  * and return the array in reverse order, i.e. parent first, then grand
  * parent, etc.
  *
- * @deprecated
+ * @deprecated since 2.2, use $context->get_parent_context_ids() instead
  * @param context $context
  * @param bool $includeself optional, defaults to false
  * @return array
@@ -6781,7 +6796,7 @@ function get_parent_contexts(context $context, $includeself = false) {
  * Return the id of the parent of this context, or false if there is no parent (only happens if this
  * is the site context.)
  *
- * @deprecated
+ * @deprecated since 2.2, use $context->get_parent_context() instead
  * @param context $context
  * @return integer the id of the parent context.
  */
@@ -6806,7 +6821,7 @@ function get_parent_contextid(context $context) {
  * If called on a user/course/module context it _will_ populate the cache with the appropriate
  * contexts ;-)
  *
- * @deprecated
+ * @deprecated since 2.2, use $context->get_child_contexts() instead
  * @param context $context.
  * @return array Array of child records
  */
@@ -6817,7 +6832,7 @@ function get_child_contexts(context $context) {
 /**
  * Precreates all contexts including all parents
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param int $contextlevel empty means all
  * @param bool $buildpaths update paths and depths
  * @return void
@@ -6829,7 +6844,7 @@ function create_contexts($contextlevel = null, $buildpaths = true) {
 /**
  * Remove stale context records
  *
- * @deprecated
+ * @deprecated since 2.2, use context_helper::cleanup_instances() instead
  * @return bool
  */
 function cleanup_contexts() {
@@ -6840,7 +6855,7 @@ function cleanup_contexts() {
 /**
  * Populate context.path and context.depth where missing.
  *
- * @deprecated
+ * @deprecated since 2.2, use context_helper::build_all_paths() instead
  * @param bool $force force a complete rebuild of the path and depth fields, defaults to false
  * @return void
  */
@@ -6867,7 +6882,7 @@ function rebuild_contexts(array $fixcontexts) {
  * are no longer loaded here. The contexts for all the blocks on the current
  * page are now efficiently loaded by {@link block_manager::load_blocks()}.
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param int $courseid Course ID
  * @return void
  */
@@ -6895,7 +6910,7 @@ function context_instance_preload_sql($joinon, $contextlevel, $tablealias) {
  * Preloads context information from db record and strips the cached info.
  * The db request has to contain both the $join and $select from context_instance_preload_sql()
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param stdClass $rec
  * @return void (modifies $rec)
  */
@@ -6906,9 +6921,7 @@ function context_instance_preload(stdClass $rec) {
 /**
  * Mark a context as dirty (with timestamp) so as to force reloading of the context.
  *
- * NOTE: use $context->mark_dirty() instead
- *
- * @deprecated
+ * @deprecated since 2.2, use $context->mark_dirty() instead
  * @param string $path context path
  */
 function mark_context_dirty($path) {
@@ -6949,7 +6962,7 @@ function mark_context_dirty($path) {
  * DB efficient as possible. This op can have a
  * massive impact in the DB.
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param context $context context obj
  * @param context $newparent new parent obj
  * @return void
@@ -6962,7 +6975,7 @@ function context_moved(context $context, context $newparent) {
  * Remove a context record and any dependent entries,
  * removes context from static context cache too
  *
- * @deprecated
+ * @deprecated since 2.2, use $context->delete_content() instead
  * @param int $contextlevel
  * @param int $instanceid
  * @param bool $deleterecord false means keep record for now
@@ -6982,8 +6995,8 @@ function delete_context($contextlevel, $instanceid, $deleterecord = true) {
 }
 
 /**
- *
- * @deprecated
+ * Returns context level name
+ * @deprecated since 2.2
  * @param integer $contextlevel $context->context level. One of the CONTEXT_... constants.
  * @return string the name for this type of context.
  */
@@ -6994,7 +7007,7 @@ function get_contextlevel_name($contextlevel) {
 /**
  * Prints human readable context identifier.
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param context $context the context.
  * @param boolean $withprefix whether to prefix the name of the context with the
  *      type of context, e.g. User, Course, Forum, etc.
@@ -7011,7 +7024,7 @@ function print_context_name(context $context, $withprefix = true, $short = false
  * CONTEXT_COURSE, this is the course page. For CONTEXT_USER it is the
  * user profile page.
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param context $context the context.
  * @return moodle_url
  */
@@ -7023,7 +7036,7 @@ function get_context_url(context $context) {
  * Is this context part of any course? if yes return course context,
  * if not return null or throw exception.
  *
- * @deprecated
+ * @deprecated since 2.2, use $context->get_course_context() instead
  * @param context $context
  * @return course_context context of the enclosing course, null if not found or exception
  */
@@ -7034,7 +7047,7 @@ function get_course_context(context $context) {
 /**
  * Returns current course id or null if outside of course based on context parameter.
  *
- * @deprecated
+ * @deprecated since 2.2, use  $context->get_course_context instead
  * @param context $context
  * @return int|bool related course id or false
  */
@@ -7050,7 +7063,7 @@ function get_courseid_from_context(context $context) {
  * Get an array of courses where cap requested is available
  * and user is enrolled, this can be relatively slow.
  *
- * @deprecated
+ * @deprecated since 2.2, use enrol_get_users_courses() instead
  * @param int    $userid A user id. By default (null) checks the permissions of the current user.
  * @param string $cap - name of the capability
  * @param array  $accessdata_ignored
@@ -7085,7 +7098,7 @@ function get_user_courses_bycap($userid, $cap, $accessdata_ignored, $doanything_
  * `contextlevel` int(10) NOT NULL,
  * `component` varchar(100) NOT NULL,
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param context $context
  * @return array
  */
@@ -7100,7 +7113,7 @@ function fetch_context_capabilities(context $context) {
  * for the purpose of $select, you need to know that the context table has been
  * aliased to ctx, so for example, you can call get_sorted_contexts('ctx.depth = 3');
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param string $select the contents of the WHERE clause. Remember to do ctx.fieldname.
  * @param array $params any parameters required by $select.
  * @return array the requested context records.
@@ -7129,7 +7142,7 @@ function get_sorted_contexts($select, $params = array()) {
 /**
  * This is really slow!!! do not use above course context level
  *
- * @deprecated
+ * @deprecated since 2.2
  * @param int $roleid
  * @param context $context
  * @return array
@@ -7175,7 +7188,7 @@ function get_role_context_caps($roleid, context $context) {
  *
  * NOTE: use $DB->get_in_or_equal($context->get_parent_context_ids()...
  *
- * @deprecated
+ * @deprecated since 2.2, $context->use get_parent_context_ids() instead
  * @param context $context
  * @return string
  */
diff --git a/lib/base32.php b/lib/base32.php
deleted file mode 100644 (file)
index 831c712..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-//
-// +----------------------------------------------------------------------+
-// | Base32 Library                                                     |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 2001 The PHP Group                                     |
-// +----------------------------------------------------------------------+
-// | This source file is dual-licensed. It is available under the terms   | 
-// | of the GNU GPL v2.0 and under the terms of the PHP license version   |
-// | 2.02,  available at through the world-wide-web at                    |
-// | available at through the world-wide-web at                           |
-// | http://www.php.net/license/2_02.txt.                                 |
-// +----------------------------------------------------------------------+
-// |  Minor fixes and additional functions by Allan Hansen.               |
-// |  Moodle porting work by Martin Langhoff                              |
-// +----------------------------------------------------------------------+
-// | base32.php - based on race.php  - RACE encode and decode strings.    |
-// +----------------------------------------------------------------------+
-// | Authors: Allan Hansen  <All@nHansen.dk>                              |
-// |          Arjan Wekking <a.wekking@synantics.nl>                      |
-// |          Martin Langhoff <martin@catalyst.net.nz>                    |
-// +----------------------------------------------------------------------+
-//
-
-/**
- * @package moodlecore
- * @copyright (c) 2001 The PHP Group
- * @license GNU GPL v2.0 http://www.php.net/license/2_02.txt
- */
-
-/**
- * Base32 encode a binary string
- *
- * @param    $inString   Binary string to base32 encode
- *
- * @return   $outString  Base32 encoded $inString
- *
- * @access   private
- *
- */
-
-function base32_encode ($inString) 
-{ 
-    $outString = ""; 
-    $compBits = ""; 
-    $BASE32_TABLE = array( 
-                          '00000' => 0x61, 
-                          '00001' => 0x62, 
-                          '00010' => 0x63, 
-                          '00011' => 0x64, 
-                          '00100' => 0x65, 
-                          '00101' => 0x66, 
-                          '00110' => 0x67, 
-                          '00111' => 0x68, 
-                          '01000' => 0x69, 
-                          '01001' => 0x6a, 
-                          '01010' => 0x6b, 
-                          '01011' => 0x6c, 
-                          '01100' => 0x6d, 
-                          '01101' => 0x6e, 
-                          '01110' => 0x6f, 
-                          '01111' => 0x70, 
-                          '10000' => 0x71, 
-                          '10001' => 0x72, 
-                          '10010' => 0x73, 
-                          '10011' => 0x74, 
-                          '10100' => 0x75, 
-                          '10101' => 0x76, 
-                          '10110' => 0x77, 
-                          '10111' => 0x78, 
-                          '11000' => 0x79, 
-                          '11001' => 0x7a, 
-                          '11010' => 0x32, 
-                          '11011' => 0x33, 
-                          '11100' => 0x34, 
-                          '11101' => 0x35, 
-                          '11110' => 0x36, 
-                          '11111' => 0x37, 
-                          ); 
-    
-    /* Turn the compressed string into a string that represents the bits as 0 and 1. */
-    for ($i = 0; $i < strlen($inString); $i++) {
-        $compBits .= str_pad(decbin(ord(substr($inString,$i,1))), 8, '0', STR_PAD_LEFT);
-    }
-    
-    /* Pad the value with enough 0's to make it a multiple of 5 */
-    if((strlen($compBits) % 5) != 0) {
-        $compBits = str_pad($compBits, strlen($compBits)+(5-(strlen($compBits)%5)), '0', STR_PAD_RIGHT);
-    }
-    
-    /* Create an array by chunking it every 5 chars */
-    $fiveBitsArray = explode("\n",rtrim(chunk_split($compBits, 5, "\n"))); 
-    
-    /* Look-up each chunk and add it to $outstring */
-    foreach($fiveBitsArray as $fiveBitsString) { 
-        $outString .= chr($BASE32_TABLE[$fiveBitsString]); 
-    } 
-    
-    return $outString; 
-} 
-
-
-
-/**
- * Base32 decode to a binary string
- *
- * @param    $inString   String to base32 decode
- *
- * @return   $outString  Base32 decoded $inString
- *
- * @access   private
- *
- */
-
-function Base32_decode($inString) {
-    /* declaration */
-    $inputCheck = null;
-    $deCompBits = null;
-    
-    $BASE32_TABLE = array( 
-                          0x61 => '00000', 
-                          0x62 => '00001', 
-                          0x63 => '00010', 
-                          0x64 => '00011', 
-                          0x65 => '00100', 
-                          0x66 => '00101', 
-                          0x67 => '00110', 
-                          0x68 => '00111', 
-                          0x69 => '01000', 
-                          0x6a => '01001', 
-                          0x6b => '01010', 
-                          0x6c => '01011', 
-                          0x6d => '01100', 
-                          0x6e => '01101', 
-                          0x6f => '01110', 
-                          0x70 => '01111', 
-                          0x71 => '10000', 
-                          0x72 => '10001', 
-                          0x73 => '10010', 
-                          0x74 => '10011', 
-                          0x75 => '10100', 
-                          0x76 => '10101', 
-                          0x77 => '10110', 
-                          0x78 => '10111', 
-                          0x79 => '11000', 
-                          0x7a => '11001', 
-                          0x32 => '11010', 
-                          0x33 => '11011', 
-                          0x34 => '11100', 
-                          0x35 => '11101', 
-                          0x36 => '11110', 
-                          0x37 => '11111', 
-                          ); 
-    
-    /* Step 1 */
-    $inputCheck = strlen($inString) % 8;
-    if(($inputCheck == 1)||($inputCheck == 3)||($inputCheck == 6)) { 
-        trigger_error('input to Base32Decode was a bad mod length: '.$inputCheck);
-        return false; 
-        //return $this->raiseError('input to Base32Decode was a bad mod length: '.$inputCheck, null, 
-        // PEAR_ERROR_DIE, null, null, 'Net_RACE_Error', false );
-    }
-    
-    /* $deCompBits is a string that represents the bits as 0 and 1.*/
-    for ($i = 0; $i < strlen($inString); $i++) {
-        $inChar = ord(substr($inString,$i,1));
-        if(isset($BASE32_TABLE[$inChar])) {
-            $deCompBits .= $BASE32_TABLE[$inChar];
-        } else {
-            trigger_error('input to Base32Decode had a bad character: '.$inChar);
-            return false;
-            //return $this->raiseError('input to Base32Decode had a bad character: '.$inChar, null, 
-            //    PEAR_ERROR_DIE, null, null, 'Net_RACE_Error', false );
-        }
-    }
-    
-    /* Step 5 */
-    $padding = strlen($deCompBits) % 8;
-    $paddingContent = substr($deCompBits, (strlen($deCompBits) - $padding));
-    if(substr_count($paddingContent, '1')>0) { 
-        trigger_error('found non-zero padding in Base32Decode');
-        return false;
-        //return $this->raiseError('found non-zero padding in Base32Decode', null, 
-        //    PEAR_ERROR_DIE, null, null, 'Net_RACE_Error', false );
-    }
-    
-    /* Break the decompressed string into octets for returning */
-    $deArr = array();
-    for($i = 0; $i < (int)(strlen($deCompBits) / 8); $i++) {
-        $deArr[$i] = chr(bindec(substr($deCompBits, $i*8, 8)));
-    }
-    
-    $outString = join('',$deArr);
-    
-    return $outString;
-}
index 22cef4c..a2ab61e 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) {
@@ -145,6 +319,7 @@ function cron_run() {
                         mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries");
                         mtrace("... used " . (microtime(1) - $pre_time) . " seconds");
                     }
+                    @set_time_limit(0);
                     mtrace("done.");
                 }
             }
@@ -152,11 +327,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 +360,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 +378,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 +391,6 @@ function cron_run() {
         }
         mtrace('done.');
     }
-
     // Run blog associations cleanup
     if ($CFG->useblogassociations) {
         require_once($CFG->dirroot . '/blog/lib.php');
@@ -421,6 +400,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 +408,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 +416,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 +432,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 +447,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 +490,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
@@ -530,6 +545,7 @@ function cron_execute_plugin_type($plugintype, $description = null) {
                 round(microtime(true) - $pre_time, 2) . " seconds)");
 
         set_config('lastcron', time(), $component);
+        @set_time_limit(0);
     }
 
     if ($description) {
@@ -541,6 +557,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 +612,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')");
+}
diff --git a/lib/csshover.htc b/lib/csshover.htc
deleted file mode 100644 (file)
index f00536d..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<attach event="ondocumentready" handler="parseStylesheets" />
-<script type="text/javascript">
-/**
- *     Pseudos - V1.30.050121 - hover & active
- *     ---------------------------------------------
- *     Peterned - http://www.xs4all.nl/~peterned/
- *     (c) 2005 - Peter Nederlof
- *
- *     Credits  - Arnoud Berendsen 
- *              - Martin Reurings
- *           - Robert Hanson
- *
- *     howto: body { behavior:url("csshover.htc"); }
- *     ---------------------------------------------
- */
-
-var currentSheet, doc = window.document, activators = {
-       onhover:{on:'onmouseover', off:'onmouseout'},
-       onactive:{on:'onmousedown', off:'onmouseup'}
-}
-
-function parseStylesheets() {
-       var sheets = doc.styleSheets, l = sheets.length;
-       for(var i=0; i<l; i++) 
-               parseStylesheet(sheets[i]);
-}
-       function parseStylesheet(sheet) {
-               if(sheet.imports) {
-                       try {
-                               var imports = sheet.imports, l = imports.length;
-                               for(var i=0; i<l; i++) parseStylesheet(sheet.imports[i]);
-                       } catch(securityException){}
-               }
-
-               try {
-                       var rules = (currentSheet = sheet).rules, l = rules.length;
-                       for(var j=0; j<l; j++) parseCSSRule(rules[j]);
-               } catch(securityException){}
-       }
-
-       function parseCSSRule(rule) {
-               var select = rule.selectorText, style = rule.style.cssText;
-               if(!(/(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i).test(select) || !style) return;
-               
-               var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
-               var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
-               var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
-               var affected = select.replace(/:hover.*$/, '');
-               var elements = getElementsBySelect(affected);
-
-               currentSheet.addRule(newSelect, style);
-               for(var i=0; i<elements.length; i++)
-                       new HoverElement(elements[i], className, activators[pseudo]);
-       }
-
-function HoverElement(node, className, events) {
-       if(!node.hovers) node.hovers = {};
-       if(node.hovers[className]) return;
-       node.hovers[className] = true;
-       node.attachEvent(events.on,
-               function() { node.className += ' ' + className; });
-       node.attachEvent(events.off,
-               function() { node.className = 
-                       node.className.replace(new RegExp('\\s+'+className, 'g'),''); });
-}
-
-function getElementsBySelect(rule) {
-       var parts, nodes = [doc];
-       parts = rule.split(' ');
-       for(var i=0; i<parts.length; i++) {
-               nodes = getSelectedNodes(parts[i], nodes);
-       }       return nodes;
-}
-       function getSelectedNodes(select, elements) {
-               var result, node, nodes = [];
-               var classname = (/\.([a-z0-9_-]+)/i).exec(select);
-               var identify = (/\#([a-z0-9_-]+)/i).exec(select);
-               var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
-               for(var i=0; i<elements.length; i++) {
-                       result = tagName? elements[i].all.tags(tagName):elements[i].all; 
-                       for(var j=0; j<result.length; j++) {
-                               node = result[j];
-                               if((identify && node.id != identify[1]) || (classname && !(new RegExp('\\b' +
-                                       classname[1] + '\\b').exec(node.className)))) continue;
-                               nodes[nodes.length] = node;
-                       }
-               }       return nodes;
-       }
-</script>
\ No newline at end of file
index f4126a9..e6c52d5 100644 (file)
@@ -73,7 +73,7 @@ course_content_removed - object course table record + context property
 course_deleted - object course table record + context property
 
 user_enrolled - object record from user_enrolments table + courseid,enrol
-user_unenrol_modified - object record from user_enrolments table + courseid,enrol
+user_enrol_modified - object record from user_enrolments table + courseid,enrol
 user_unenrolled - object record from user_enrolments table + courseid,enrol,lastenrol
 
 ==== cohort related events ===
index 117bf9d..73eed2c 100644 (file)
@@ -29,7 +29,16 @@ $functions = array(
     // === group related functions ===
 
     'moodle_group_create_groups' => array(
-        'classname'   => 'moodle_group_external',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'create_groups',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_create_groups(). ',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_create_groups' => array(
+        'classname'   => 'core_group_external',
         'methodname'  => 'create_groups',
         'classpath'   => 'group/externallib.php',
         'description' => 'Creates new groups.',
@@ -38,7 +47,16 @@ $functions = array(
     ),
 
     'moodle_group_get_groups' => array(
-        'classname'   => 'moodle_group_external',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'get_groups',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_get_groups()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_get_groups' => array(
+        'classname'   => 'core_group_external',
         'methodname'  => 'get_groups',
         'classpath'   => 'group/externallib.php',
         'description' => 'Returns group details.',
@@ -47,7 +65,16 @@ $functions = array(
     ),
 
     'moodle_group_get_course_groups' => array(
-        'classname'   => 'moodle_group_external',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'get_course_groups',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_get_course_groups()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_get_course_groups' => array(
+        'classname'   => 'core_group_external',
         'methodname'  => 'get_course_groups',
         'classpath'   => 'group/externallib.php',
         'description' => 'Returns all groups in specified course.',
@@ -56,7 +83,16 @@ $functions = array(
     ),
 
     'moodle_group_delete_groups' => array(
-        'classname'   => 'moodle_group_external',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'delete_groups',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_delete_groups()',
+        'type'        => 'delete',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_delete_groups' => array(
+        'classname'   => 'core_group_external',
         'methodname'  => 'delete_groups',
         'classpath'   => 'group/externallib.php',
         'description' => 'Deletes all specified groups.',
@@ -65,8 +101,17 @@ $functions = array(
     ),
 
     'moodle_group_get_groupmembers' => array(
-        'classname'   => 'moodle_group_external',
-        'methodname'  => 'get_groupmembers',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'get_group_members',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_get_group_members()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_get_group_members' => array(
+        'classname'   => 'core_group_external',
+        'methodname'  => 'get_group_members',
         'classpath'   => 'group/externallib.php',
         'description' => 'Returns group members.',
         'type'        => 'read',
@@ -74,8 +119,17 @@ $functions = array(
     ),
 
     'moodle_group_add_groupmembers' => array(
-        'classname'   => 'moodle_group_external',
-        'methodname'  => 'add_groupmembers',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'add_group_members',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_add_group_members()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
+
+    'core_group_add_group_members' => array(
+        'classname'   => 'core_group_external',
+        'methodname'  => 'add_group_members',
         'classpath'   => 'group/externallib.php',
         'description' => 'Adds group members.',
         'type'        => 'write',
@@ -83,26 +137,51 @@ $functions = array(
     ),
 
     'moodle_group_delete_groupmembers' => array(
-        'classname'   => 'moodle_group_external',
-        'methodname'  => 'delete_groupmembers',
+        'classname'   => 'core_group_external',
+        'methodname'  => 'delete_group_members',
         'classpath'   => 'group/externallib.php',
-        'description' => 'Deletes group members.',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_group_delete_group_members()',
         'type'        => 'delete',
         'capabilities'=> 'moodle/course:managegroups',
     ),
 
+    'core_group_delete_group_members' => array(
+        'classname'   => 'core_group_external',
+        'methodname'  => 'delete_group_members',
+        'classpath'   => 'group/externallib.php',
+        'description' => 'Deletes group members.',
+        'type'        => 'delete',
+        'capabilities'=> 'moodle/course:managegroups',
+    ),
 
     // === file related functions ===
 
     'moodle_file_get_files' => array(
-        'classname'   => 'moodle_file_external',
+        'classname'   => 'core_files_external',
+        'methodname'  => 'get_files',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_files_get_files()',
+        'type'        => 'read',
+        'classpath'   => 'files/externallib.php',
+    ),
+
+    'core_files_get_files' => array(
+        'classname'   => 'core_files_external',
         'methodname'  => 'get_files',
         'description' => 'browse moodle files',
         'type'        => 'read',
         'classpath'   => 'files/externallib.php',
     ),
+
     'moodle_file_upload' => array(
-        'classname'   => 'moodle_file_external',
+        'classname'   => 'core_files_external',
+        'methodname'  => 'upload',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_files_upload()',
+        'type'        => 'write',
+        'classpath'   => 'files/externallib.php',
+    ),
+
+    'core_files_upload' => array(
+        'classname'   => 'core_files_external',
         'methodname'  => 'upload',
         'description' => 'upload a file to moodle',
         'type'        => 'write',
@@ -112,7 +191,16 @@ $functions = array(
     // === user related functions ===
 
     'moodle_user_create_users' => array(
-        'classname'   => 'moodle_user_external',
+        'classname'   => 'core_user_external',
+        'methodname'  => 'create_users',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_user_create_users()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/user:create',
+    ),
+
+    'core_user_create_users' => array(
+        'classname'   => 'core_user_external',
         'methodname'  => 'create_users',
         'classpath'   => 'user/externallib.php',
         'description' => 'Create users.',
@@ -121,7 +209,16 @@ $functions = array(
     ),
 
     'moodle_user_get_users_by_id' => array(
-        'classname'   => 'moodle_user_external',
+        'classname'   => 'core_user_external',
+        'methodname'  => 'get_users_by_id',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_user_get_users_by_id()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update',
+    ),
+
+    'core_user_get_users_by_id' => array(
+        'classname'   => 'core_user_external',
         'methodname'  => 'get_users_by_id',
         'classpath'   => 'user/externallib.php',
         'description' => 'Get users by id.',
@@ -130,25 +227,43 @@ $functions = array(
     ),
 
     'moodle_user_get_users_by_courseid' => array(
-        'classname'   => 'moodle_user_external',
-        'methodname'  => 'get_users_by_courseid',
-        'classpath'   => 'user/externallib.php',
-        'description' => 'Get enrolled users by course id.',
+        'classname'   => 'core_enrol_external',
+        'methodname'  => 'get_enrolled_users',
+        'classpath'   => 'enrol/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_enrol_get_enrolled_users()',
         'type'        => 'read',
         'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups',
     ),
 
     'moodle_user_get_course_participants_by_id' => array(
-        'classname'   => 'moodle_user_external',
-        'methodname'  => 'get_course_participants_by_id',
+        'classname'   => 'core_user_external',
+        'methodname'  => 'get_course_user_profiles',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_user_get_course_user_profiles()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups',
+    ),
+
+    'core_user_get_course_user_profiles' => array(
+        'classname'   => 'core_user_external',
+        'methodname'  => 'get_course_user_profiles',
         'classpath'   => 'user/externallib.php',
-        'description' => 'Get course user profiles by id.',
+        'description' => 'Get course user profiles (each of the profils matching a course id and a user id).',
         'type'        => 'read',
         'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups',
     ),
 
     'moodle_user_delete_users' => array(
-        'classname'   => 'moodle_user_external',
+        'classname'   => 'core_user_external',
+        'methodname'  => 'delete_users',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_user_delete_users()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/user:delete',
+    ),
+
+    'core_user_delete_users' => array(
+        'classname'   => 'core_user_external',
         'methodname'  => 'delete_users',
         'classpath'   => 'user/externallib.php',
         'description' => 'Delete users.',
@@ -157,7 +272,16 @@ $functions = array(
     ),
 
     'moodle_user_update_users' => array(
-        'classname'   => 'moodle_user_external',
+        'classname'   => 'core_user_external',
+        'methodname'  => 'update_users',
+        'classpath'   => 'user/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_user_update_users()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/user:update',
+    ),
+
+    'core_user_update_users' => array(
+        'classname'   => 'core_user_external',
         'methodname'  => 'update_users',
         'classpath'   => 'user/externallib.php',
         'description' => 'Update users.',
@@ -171,24 +295,53 @@ $functions = array(
         'classname'   => 'moodle_enrol_external',
         'methodname'  => 'get_enrolled_users',
         'classpath'   => 'enrol/externallib.php',
-        'description' => 'Get list of course participants',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. Please use core_enrol_get_enrolled_users() (previously known as moodle_user_get_users_by_courseid).',
         'type'        => 'read',
         'capabilities'=> 'moodle/site:viewparticipants, moodle/course:viewparticipants,
             moodle/role:review, moodle/site:accessallgroups, moodle/course:enrolreview',
     ),
 
+    'core_enrol_get_enrolled_users' => array(
+        'classname'   => 'core_enrol_external',
+        'methodname'  => 'get_enrolled_users',
+        'classpath'   => 'enrol/externallib.php',
+        'description' => 'Get enrolled users by course id.',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/user:viewdetails, moodle/user:viewhiddendetails, moodle/course:useremail, moodle/user:update, moodle/site:accessallgroups',
+    ),
+
     'moodle_enrol_get_users_courses' => array(
-        'classname'   => 'moodle_enrol_external',
+        'classname'   => 'core_enrol_external',
         'methodname'  => 'get_users_courses',
         'classpath'   => 'enrol/externallib.php',
-        'description' => 'Get list of courses user is enrolled in',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_enrol_get_users_courses()',
         'type'        => 'read',
         'capabilities'=> 'moodle/course:viewparticipants',
     ),
 
+    'core_enrol_get_users_courses' => array(
+        'classname'   => 'core_enrol_external',
+        'methodname'  => 'get_users_courses',
+        'classpath'   => 'enrol/externallib.php',
+        'description' => 'Get the list of courses where a user is enrolled in',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/course:viewparticipants',
+    ),
+
+    // === Role related functions ===
+
     'moodle_role_assign' => array(
-        'classname'   => 'moodle_enrol_external',
-        'methodname'  => 'role_assign',
+        'classname'   => 'core_role_external',
+        'methodname'  => 'assign_roles',
+        'classpath'   => 'enrol/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_role_assign_role()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/role:assign',
+    ),
+
+    'core_role_assign_roles' => array(
+        'classname'   => 'core_role_external',
+        'methodname'  => 'assign_roles',
         'classpath'   => 'enrol/externallib.php',
         'description' => 'Manual role assignments.',
         'type'        => 'write',
@@ -196,8 +349,17 @@ $functions = array(
     ),
 
     'moodle_role_unassign' => array(
-        'classname'   => 'moodle_enrol_external',
-        'methodname'  => 'role_unassign',
+        'classname'   => 'core_role_external',
+        'methodname'  => 'unassign_roles',
+        'classpath'   => 'enrol/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_role_unassign_role()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/role:assign',
+    ),
+
+    'core_role_unassign_roles' => array(
+        'classname'   => 'core_role_external',
+        'methodname'  => 'unassign_roles',
         'classpath'   => 'enrol/externallib.php',
         'description' => 'Manual role unassignments.',
         'type'        => 'write',
@@ -207,7 +369,16 @@ $functions = array(
     // === course related functions ===
 
     'moodle_course_get_courses' => array(
-        'classname'   => 'moodle_course_external',
+        'classname'   => 'core_course_external',
+        'methodname'  => 'get_courses',
+        'classpath'   => 'course/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_course_get_courses()',
+        'type'        => 'read',
+        'capabilities'=> 'moodle/course:view,moodle/course:update,moodle/course:viewhiddencourses',
+    ),
+
+    'core_course_get_courses' => array(
+        'classname'   => 'core_course_external',
         'methodname'  => 'get_courses',
         'classpath'   => 'course/externallib.php',
         'description' => 'Return course details',
@@ -216,7 +387,16 @@ $functions = array(
     ),
 
     'moodle_course_create_courses' => array(
-        'classname'   => 'moodle_course_external',
+        'classname'   => 'core_course_external',
+        'methodname'  => 'create_courses',
+        'classpath'   => 'course/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_course_create_courses()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/course:create,moodle/course:visibility',
+    ),
+
+    'core_course_create_courses' => array(
+        'classname'   => 'core_course_external',
         'methodname'  => 'create_courses',
         'classpath'   => 'course/externallib.php',
         'description' => 'Create new courses',
@@ -227,8 +407,17 @@ $functions = array(
     // === message related functions ===
 
     'moodle_message_send_instantmessages' => array(
-        'classname'   => 'moodle_message_external',
-        'methodname'  => 'send_instantmessages',
+        'classname'   => 'core_message_external',
+        'methodname'  => 'send_instant_messages',
+        'classpath'   => 'message/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_message_send_instant_messages()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/site:sendmessage',
+    ),
+
+    'core_message_send_instant_messages' => array(
+        'classname'   => 'core_message_external',
+        'methodname'  => 'send_instant_messages',
         'classpath'   => 'message/externallib.php',
         'description' => 'Send instant messages',
         'type'        => 'write',
@@ -238,7 +427,16 @@ $functions = array(
     // === notes related functions ===
 
     'moodle_notes_create_notes' => array(
-        'classname'   => 'moodle_notes_external',
+        'classname'   => 'core_notes_external',
+        'methodname'  => 'create_notes',
+        'classpath'   => 'notes/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_notes_create_notes()',
+        'type'        => 'write',
+        'capabilities'=> 'moodle/notes:manage',
+    ),
+
+    'core_notes_create_notes' => array(
+        'classname'   => 'core_notes_external',
         'methodname'  => 'create_notes',
         'classpath'   => 'notes/externallib.php',
         'description' => 'Create notes',
@@ -249,8 +447,16 @@ $functions = array(
     // === webservice related functions ===
 
     'moodle_webservice_get_siteinfo' => array(
-        'classname'   => 'moodle_webservice_external',
-        'methodname'  => 'get_siteinfo',
+        'classname'   => 'core_webservice_external',
+        'methodname'  => 'get_site_info',
+        'classpath'   => 'webservice/externallib.php',
+        'description' => 'DEPRECATED: this deprecated function will be removed in a future version. This function has be renamed as core_webservice_get_site_info()',
+        'type'        => 'read',
+    ),
+
+    'core_webservice_get_site_info' => array(
+        'classname'   => 'core_webservice_external',
+        'methodname'  => 'get_site_info',
         'classpath'   => 'webservice/externallib.php',
         'description' => 'Return some site info / user info / list web service functions',
         'type'        => 'read',
index a100802..0184da5 100644 (file)
@@ -3716,14 +3716,6 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
         upgrade_main_savepoint(true, 2010051801);
     }
 
-    if ($oldversion < 2010052100) {
-        // Switch to html purifier as default cleaning engine - KSES is really very bad
-        if (empty($CFG->enablehtmlpurifier)) {
-            unset_config('enablehtmlpurifier');
-        }
-        upgrade_main_savepoint(true, 2010052100);
-    }
-
     if ($oldversion < 2010052200) {
         // Define field legacyfiles to be added to course - just in case we are upgrading from PR1
         $table = new xmldb_table('course');
@@ -6810,6 +6802,12 @@ FROM
         upgrade_main_savepoint(true, 2011101200.01);
     }
 
+    if ($oldversion < 2011101900.02) {
+        // remove unused setting
+        unset_config('enablehtmlpurifier');
+        upgrade_main_savepoint(true, 2011101900.02);
+    }
+
     return true;
 }
 
index 8428fec..c85abd7 100644 (file)
@@ -3756,6 +3756,28 @@ class dml_test extends UnitTestCase {
         $records = $DB->get_records_sql($sql, null);
         $this->assertEqual($result, $records);
 
+        // another grouping by CASE expression just to ensure it works ok for multiple WHEN
+        $sql = "SELECT CASE name
+                            WHEN 'xyz' THEN 'last'
+                            WHEN 'def' THEN 'mid'
+                            WHEN 'abc' THEN 'first'
+                       END AS casecol,
+                       COUNT(1) AS countrecs,
+                       MAX(name) AS maxname
+                  FROM {{$tablename}}
+              GROUP BY CASE name
+                           WHEN 'xyz' THEN 'last'
+                           WHEN 'def' THEN 'mid'
+                           WHEN 'abc' THEN 'first'
+                       END
+              ORDER BY casecol DESC";
+        $result = array(
+                'mid'  => (object)array('casecol' => 'mid', 'countrecs' => 1, 'maxname' => 'def'),
+                'last' => (object)array('casecol' => 'last', 'countrecs' => 1, 'maxname' => 'xyz'),
+                'first'=> (object)array('casecol' => 'first', 'countrecs' => 2, 'maxname' => 'abc'));
+        $records = $DB->get_records_sql($sql, null);
+        $this->assertEqual($result, $records);
+
         // test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268
         $sql = "SELECT   DISTINCT   course
                   FROM {{$tablename}}
index fe3dce2..c3ce81c 100644 (file)
@@ -1103,6 +1103,7 @@ abstract class enrol_plugin {
         $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST);
 
         $inserted = false;
+        $updated  = false;
         if ($ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) {
             //only update if timestart or timeend or status are different.
             if ($ue->timestart != $timestart or $ue->timeend != $timeend or (!is_null($status) and $ue->status != $status)) {
@@ -1114,6 +1115,8 @@ abstract class enrol_plugin {
                 $ue->modifierid   = $USER->id;
                 $ue->timemodified = time();
                 $DB->update_record('user_enrolments', $ue);
+
+                $updated = true;
             }
         } else {
             $ue = new stdClass();
@@ -1143,6 +1146,10 @@ abstract class enrol_plugin {
             $ue->courseid  = $courseid;
             $ue->enrol     = $name;
             events_trigger('user_enrolled', $ue);
+        } else if ($updated) {
+            $ue->courseid  = $courseid;
+            $ue->enrol     = $name;
+            events_trigger('user_enrol_modified', $ue);
         }
 
         // reset primitive require_login() caching
@@ -1160,8 +1167,8 @@ abstract class enrol_plugin {
     /**
      * Store user_enrolments changes and trigger event.
      *
-     * @param object $ue
-     * @param int $user id
+     * @param stdClass $instance
+     * @param int $userid
      * @param int $status
      * @param int $timestart
      * @param int $timeend
@@ -1206,7 +1213,7 @@ abstract class enrol_plugin {
         // trigger event
         $ue->courseid  = $instance->courseid;
         $ue->enrol     = $instance->name;
-        events_trigger('user_unenrol_modified', $ue);
+        events_trigger('user_enrol_modified', $ue);
     }
 
     /**
index 835fc76..212179c 100644 (file)
@@ -452,7 +452,7 @@ class stored_file {
      * @return string
      */
     public function get_author() {
-        return $this->file_record->license;
+        return $this->file_record->author;
     }
 
     /**
diff --git a/lib/kses.php b/lib/kses.php
deleted file mode 100644 (file)
index 8d87c23..0000000
+++ /dev/null
@@ -1,712 +0,0 @@
-<?php
-/**
- * kses 0.2.2 - HTML/XHTML filter that only allows some elements and attributes
- * Copyright (C) 2002, 2003, 2005  Ulf Harnhammar
- *
- * This program is free software and open source software; you can redistribute
- * it and/or modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  or visit
- * http://www.gnu.org/licenses/gpl.html
- *
- * *** CONTACT INFORMATION ***
- *
- * E-mail:      metaur at users dot sourceforge dot net
- * Web page:    http://sourceforge.net/projects/kses
- * Paper mail:  Ulf Harnhammar
- *              Ymergatan 17 C
- *              753 25  Uppsala
- *              SWEDEN
- *
- * [kses strips evil scripts!]
- *
- * @package   moodlecore
- * @copyright Ulf Harnhammar  {@link http://sourceforge.net/projects/kses}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-/**
- * This function makes sure that only the allowed HTML element names, attribute
- * names and attribute values plus only sane HTML entities will occur in
- * $string. You have to remove any slashes from PHP's magic quotes before you
- * call this function.
- *
- * @param string $string
- * @param string $allowed_html
- * @param array $allowed_protocols
- * @return string
- */
-function kses($string, $allowed_html, $allowed_protocols =
-               array('http', 'https', 'ftp', 'news', 'nntp', 'telnet',
-                     'gopher', 'mailto'))
-###############################################################################
-# This function makes sure that only the allowed HTML element names, attribute
-# names and attribute values plus only sane HTML entities will occur in
-# $string. You have to remove any slashes from PHP's magic quotes before you
-# call this function.
-###############################################################################
-{
-  $string = kses_no_null($string);
-  $string = kses_js_entities($string);
-  $string = kses_normalize_entities($string);
-  $string = kses_hook($string);
-  $allowed_html_fixed = kses_array_lc($allowed_html);
-  return kses_split($string, $allowed_html_fixed, $allowed_protocols);
-} # function kses
-
-
-/**
- * You add any kses hooks here
- *
- * @param string $string
- * @return string
- */
-function kses_hook($string)
-###############################################################################
-# You add any kses hooks here.
-###############################################################################
-{
-  return $string;
-} # function kses_hook
-
-/**
- * This function returns kses' version number.
- *
- * @return string
- */
-function kses_version()
-###############################################################################
-# This function returns kses' version number.
-###############################################################################
-{
-  return '0.2.2';
-} # function kses_version
-
-
-/**
- * This function searches for HTML tags, no matter how malformed. It also
- * matches stray ">" characters.
- *
- * @param string $string
- * @param string $allowed_html
- * @param array $allowed_protocols
- * @return string
- */
-function kses_split($string, $allowed_html, $allowed_protocols)
-###############################################################################
-# This function searches for HTML tags, no matter how malformed. It also
-# matches stray ">" characters.
-###############################################################################
-{
-  return preg_replace('%(<'.   # EITHER: <
-                      '[^>]*'. # things that aren't >
-                      '(>|$)'. # > or end of string
-                      '|>)%e', # OR: just a >
-                      "kses_split2('\\1', \$allowed_html, ".
-                      '$allowed_protocols)',
-                      $string);
-} # function kses_split
-
-/**
- * This function does a lot of work. It rejects some very malformed things
- * like <:::>. It returns an empty string, if the element isn't allowed (look
- * ma, no strip_tags()!). Otherwise it splits the tag into an element and an
- * attribute list.
- *
- * @param string $string
- * @param string $allowed_html
- * @param array $allowed_protocols
- * @return string
- */
-function kses_split2($string, $allowed_html, $allowed_protocols)
-###############################################################################
-# This function does a lot of work. It rejects some very malformed things
-# like <:::>. It returns an empty string, if the element isn't allowed (look
-# ma, no strip_tags()!). Otherwise it splits the tag into an element and an
-# attribute list.
-###############################################################################
-{
-  $string = kses_stripslashes($string);
-
-  if (substr($string, 0, 1) != '<')
-    return '&gt;';
-    # It matched a ">" character
-
-  if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $string, $matches))
-    return '';
-    # It's seriously malformed
-
-  $slash = trim($matches[1]);
-  $elem = $matches[2];
-  $attrlist = $matches[3];
-
-  if (!@isset($allowed_html[strtolower($elem)]))
-    return '';
-    # They are using a not allowed HTML element
-
-  if ($slash != '')
-    return "<$slash$elem>";
-  # No attributes are allowed for closing elements
-
-  return kses_attr("$slash$elem", $attrlist, $allowed_html,
-                   $allowed_protocols);
-} # function kses_split2
-
-/**
- * This function removes all attributes, if none are allowed for this element.
- * If some are allowed it calls kses_hair() to split them further, and then it
- * builds up new HTML code from the data that kses_hair() returns. It also
- * removes "<" and ">" characters, if there are any left. One more thing it
- * does is to check if the tag has a closing XHTML slash, and if it does,
- * it puts one in the returned code as well.
- *
- * @param string $element
- * @param string $attr
- * @param string $allowed_html
- * @param array $allowed_protocols
- * @return string
- */
-function kses_attr($element, $attr, $allowed_html, $allowed_protocols)
-###############################################################################
-# This function removes all attributes, if none are allowed for this element.
-# If some are allowed it calls kses_hair() to split them further, and then it
-# builds up new HTML code from the data that kses_hair() returns. It also
-# removes "<" and ">" characters, if there are any left. One more thing it
-# does is to check if the tag has a closing XHTML slash, and if it does,
-# it puts one in the returned code as well.
-###############################################################################
-{
-# Is there a closing XHTML slash at the end of the attributes?
-
-  $xhtml_slash = '';
-  if (preg_match('%\s/\s*$%', $attr))
-    $xhtml_slash = ' /';
-
-# Are any attributes allowed at all for this element?
-
-  if (@count($allowed_html[strtolower($element)]) == 0)
-    return "<$element$xhtml_slash>";
-
-# Split it
-
-  $attrarr = kses_hair($attr, $allowed_protocols);
-
-# Go through $attrarr, and save the allowed attributes for this element
-# in $attr2
-
-  $attr2 = '';
-
-  foreach ($attrarr as $arreach)
-  {
-    if (!@isset($allowed_html[strtolower($element)]
-                            [strtolower($arreach['name'])]))
-      continue; # the attribute is not allowed
-
-    $current = $allowed_html[strtolower($element)]
-                            [strtolower($arreach['name'])];
-
-    if (!is_array($current))
-      $attr2 .= ' '.$arreach['whole'];
-    # there are no checks
-
-    else
-    {
-    # there are some checks
-      $ok = true;
-      foreach ($current as $currkey => $currval)
-        if (!kses_check_attr_val($arreach['value'], $arreach['vless'],
-                                 $currkey, $currval))
-        { $ok = false; break; }
-
-      if ($ok)
-        $attr2 .= ' '.$arreach['whole']; # it passed them
-    } # if !is_array($current)
-  } # foreach
-
-# Remove any "<" or ">" characters
-
-  $attr2 = preg_replace('/[<>]/', '', $attr2);
-
-  return "<$element$attr2$xhtml_slash>";
-} # function kses_attr
-
-/**
- * This function does a lot of work. It parses an attribute list into an array
- * with attribute data, and tries to do the right thing even if it gets weird
- * input. It will add quotes around attribute values that don't have any quotes
- * or apostrophes around them, to make it easier to produce HTML code that will
- * conform to W3C's HTML specification. It will also remove bad URL protocols
- * from attribute values.
- *
- * @param string $attr
- * @param array $allowed_protocols
- * @return array
- */
-function kses_hair($attr, $allowed_protocols)
-###############################################################################
-# This function does a lot of work. It parses an attribute list into an array
-# with attribute data, and tries to do the right thing even if it gets weird
-# input. It will add quotes around attribute values that don't have any quotes
-# or apostrophes around them, to make it easier to produce HTML code that will
-# conform to W3C's HTML specification. It will also remove bad URL protocols
-# from attribute values.
-###############################################################################
-{
-  $attrarr = array();
-  $mode = 0;
-  $attrname = '';
-
-# Loop through the whole attribute list
-
-  while (strlen($attr) != 0)
-  {
-    $working = 0; # Was the last operation successful?
-
-    switch ($mode)
-    {
-      case 0: # attribute name, href for instance
-
-        if (preg_match('/^([-a-zA-Z]+)/', $attr, $match))
-        {
-          $attrname = $match[1];
-          $working = $mode = 1;
-          $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr);
-        }
-
-        break;
-
-      case 1: # equals sign or valueless ("selected")
-
-        if (preg_match('/^\s*=\s*/', $attr)) # equals sign
-        {
-          $working = 1; $mode = 2;
-          $attr = preg_replace('/^\s*=\s*/', '', $attr);
-          break;
-        }
-
-        if (preg_match('/^\s+/', $attr)) # valueless
-        {
-          $working = 1; $mode = 0;
-          $attrarr[] = array
-                        ('name'  => $attrname,
-                         'value' => '',
-                         'whole' => $attrname,
-                         'vless' => 'y');
-          $attr = preg_replace('/^\s+/', '', $attr);
-        }
-
-        break;
-
-      case 2: # attribute value, a URL after href= for instance
-
-        if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match))
-         # "value"
-        {
-          // MDL-2684 - kses stripping CSS styles that it thinks look like protocols
-          if ($attrname == 'style') {
-              $thisval = $match[1];
-          } else {
-              $thisval = kses_bad_protocol($match[1], $allowed_protocols);
-          }
-
-          $attrarr[] = array
-                        ('name'  => $attrname,
-                         'value' => $thisval,
-                         'whole' => "$attrname=\"$thisval\"",
-                         'vless' => 'n');
-          $working = 1; $mode = 0;
-          $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr);
-          break;
-        }
-
-        if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match))
-         # 'value'
-        {
-          $thisval = kses_bad_protocol($match[1], $allowed_protocols);
-
-          $attrarr[] = array
-                        ('name'  => $attrname,
-                         'value' => $thisval,
-                         'whole' => "$attrname='$thisval'",
-                         'vless' => 'n');
-          $working = 1; $mode = 0;
-          $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr);
-          break;
-        }
-
-        if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match))
-         # value
-        {
-          $thisval = kses_bad_protocol($match[1], $allowed_protocols);
-
-          $attrarr[] = array
-                        ('name'  => $attrname,
-                         'value' => $thisval,
-                         'whole' => "$attrname=\"$thisval\"",
-                         'vless' => 'n');
-                         # We add quotes to conform to W3C's HTML spec.
-          $working = 1; $mode = 0;
-          $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr);
-        }
-
-        break;
-    } # switch
-
-    if ($working == 0) # not well formed, remove and try again
-    {
-      $attr = kses_html_error($attr);
-      $mode = 0;
-    }
-  } # while
-
-  if ($mode == 1)
-  # special case, for when the attribute list ends with a valueless
-  # attribute like "selected"
-    $attrarr[] = array
-                  ('name'  => $attrname,
-                   'value' => '',
-                   'whole' => $attrname,
-                   'vless' => 'y');
-
-  return $attrarr;
-} # function kses_hair
-
-/**
- * This function performs different checks for attribute values. The currently
- * implemented checks are "maxlen", "minlen", "maxval", "minval" and "valueless"
- * with even more checks to come soon.
- *
- * @param string $value
- * @param string $vless
- * @param string $checkname
- * @param string $checkvalue
- * @return bool
- */
-function kses_check_attr_val($value, $vless, $checkname, $checkvalue)
-###############################################################################
-# This function performs different checks for attribute values. The currently
-# implemented checks are "maxlen", "minlen", "maxval", "minval" and "valueless"
-# with even more checks to come soon.
-###############################################################################
-{
-  $ok = true;
-
-  switch (strtolower($checkname))
-  {
-    case 'maxlen':
-    # The maxlen check makes sure that the attribute value has a length not
-    # greater than the given value. This can be used to avoid Buffer Overflows
-    # in WWW clients and various Internet servers.
-
-      if (strlen($value) > $checkvalue)
-        $ok = false;
-      break;
-
-    case 'minlen':
-    # The minlen check makes sure that the attribute value has a length not
-    # smaller than the given value.
-
-      if (strlen($value) < $checkvalue)
-        $ok = false;
-      break;
-
-    case 'maxval':
-    # The maxval check does two things: it checks that the attribute value is
-    # an integer from 0 and up, without an excessive amount of zeroes or
-    # whitespace (to avoid Buffer Overflows). It also checks that the attribute
-    # value is not greater than the given value.
-    # This check can be used to avoid Denial of Service attacks.
-
-      if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
-        $ok = false;
-      if ($value > $checkvalue)
-        $ok = false;
-      break;
-
-    case 'minval':
-    # The minval check checks that the attribute value is a positive integer,
-    # and that it is not smaller than the given value.
-
-      if (!preg_match('/^\s{0,6}[0-9]{1,6}\s{0,6}$/', $value))
-        $ok = false;
-      if ($value < $checkvalue)
-        $ok = false;
-      break;
-
-    case 'valueless':
-    # The valueless check checks if the attribute has a value
-    # (like <a href="blah">) or not (<option selected>). If the given value
-    # is a "y" or a "Y", the attribute must not have a value.
-    # If the given value is an "n" or an "N", the attribute must have one.
-
-      if (strtolower($checkvalue) != $vless)
-        $ok = false;
-      break;
-  } # switch
-
-  return $ok;
-} # function kses_check_attr_val
-
-/**
- * This function removes all non-allowed protocols from the beginning of
- * $string. It ignores whitespace and the case of the letters, and it does
- * understand HTML entities. It does its work in a while loop, so it won't be
- * fooled by a string like "javascript:javascript:alert(57)".
- *
- * @param string $string
- * @param array $$allowed_protocols
- * @return string
- */
-function kses_bad_protocol($string, $allowed_protocols)
-###############################################################################
-# This function removes all non-allowed protocols from the beginning of
-# $string. It ignores whitespace and the case of the letters, and it does
-# understand HTML entities. It does its work in a while loop, so it won't be
-# fooled by a string like "javascript:javascript:alert(57)".
-###############################################################################
-{
-  $string = kses_no_null($string);
-  $string = preg_replace('/([^\xc3-\xcf])\xad+/', '\\1', $string); # deals with Opera "feature" -- moodle utf8 fix
-  $string2 = $string.'a';
-
-  while ($string != $string2)
-  {
-    $string2 = $string;
-    $string = kses_bad_protocol_once($string, $allowed_protocols);
-  } # while
-
-  return $string;
-} # function kses_bad_protocol
-
-/**
- * This function removes any NULL characters in $string.
- *
- * @param string $string
- * @return string
- */
-function kses_no_null($string)
-###############################################################################
-# This function removes any NULL characters in $string.
-###############################################################################
-{
-  $string = preg_replace('/\0+/', '', $string);
-  $string = preg_replace('/(\\\\0)+/', '', $string);
-
-  return $string;
-} # function kses_no_null
-
-
-/**
- * This function changes the character sequence  \"  to just  "
- * It leaves all other slashes alone. It's really weird, but the quoting from
- * preg_replace(//e) seems to require this.
- *
- * @param string $string
- * @return string
- */
-function kses_stripslashes($string)
-###############################################################################
-# This function changes the character sequence  \"  to just  "
-# It leaves all other slashes alone. It's really weird, but the quoting from
-# preg_replace(//e) seems to require this.
-###############################################################################
-{
-  return preg_replace('%\\\\"%', '"', $string);
-} # function kses_stripslashes
-
-
-/**
- * This function goes through an array, and changes the keys to all lower case.
- *
- * @param array $inarray
- * @return array
- */
-function kses_array_lc($inarray)
-###############################################################################
-# This function goes through an array, and changes the keys to all lower case.
-###############################################################################
-{
-  $outarray = array();
-
-  foreach ($inarray as $inkey => $inval)
-  {
-    $outkey = strtolower($inkey);
-    $outarray[$outkey] = array();
-
-    foreach ($inval as $inkey2 => $inval2)
-    {
-      $outkey2 = strtolower($inkey2);
-      $outarray[$outkey][$outkey2] = $inval2;
-    } # foreach $inval
-  } # foreach $inarray
-
-  return $outarray;
-} # function kses_array_lc
-
-/**
- * This function removes the HTML JavaScript entities found in early versions of
- * Netscape 4.
- *
- * @param string $string
- */
-function kses_js_entities($string)
-###############################################################################
-# This function removes the HTML JavaScript entities found in early versions of
-# Netscape 4.
-###############################################################################
-{
-  return preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string);
-} # function kses_js_entities
-
-/**
- * This function deals with parsing errors in kses_hair(). The general plan is
- * to remove everything to and including some whitespace, but it deals with
- * quotes and apostrophes as well.
- *
- * @param string $string
- * @return string
- */
-function kses_html_error($string)
-###############################################################################
-# This function deals with parsing errors in kses_hair(). The general plan is
-# to remove everything to and including some whitespace, but it deals with
-# quotes and apostrophes as well.
-###############################################################################
-{
-  return preg_replace('/^("[^"]*("|$)|\'[^\']*(\'|$)|\S)*\s*/', '', $string);
-} # function kses_html_error
-
-/**
- * This function searches for URL protocols at the beginning of $string, while
- * handling whitespace and HTML entities.
- *
- * @param string $string
- * @param string $allowed_protocols
- * @return string
- */
-function kses_bad_protocol_once($string, $allowed_protocols)
-###############################################################################
-# This function searches for URL protocols at the beginning of $string, while
-# handling whitespace and HTML entities.
-###############################################################################
-{
-  $string2 = preg_split('/:|&#58;|&#x3a;/i', $string, 2);
-  if(isset($string2[1]) && !preg_match('%/\?%',$string2[0]))
-  {
-    $string = kses_bad_protocol_once2($string2[0],$allowed_protocols).trim($string2[1]);
-  }
-  return $string;
-} # function kses_bad_protocol_once
-
-/**
- * This function processes URL protocols, checks to see if they're in the white-
- * list or not, and returns different data depending on the answer.
- *
- * @param string $string
- * @param string $allowed_protocols
- * @return string
- */
-function kses_bad_protocol_once2($string, $allowed_protocols)
-###############################################################################
-# This function processes URL protocols, checks to see if they're in the white-
-# list or not, and returns different data depending on the answer.
-###############################################################################
-{
-  $string2 = kses_decode_entities($string);
-  $string2 = preg_replace('/\s/', '', $string2);
-  $string2 = kses_no_null($string2);
-  $string2 = preg_replace('/\xad+/', '', $string2);
-   # deals with Opera "feature"
-  $string2 = strtolower($string2);
-
-  $allowed = false;
-  foreach ($allowed_protocols as $one_protocol)
-    if (strtolower($one_protocol) == $string2)
-    {
-      $allowed = true;
-      break;
-    }
-
-  if ($allowed)
-    return "$string2:";
-  else
-    return '';
-} # function kses_bad_protocol_once2
-
-/**
- * This function normalizes HTML entities. It will convert "AT&T" to the correct
- * "AT&amp;T", "&#00058;" to "&#58;", "&#XYZZY;" to "&amp;#XYZZY;" and so on.
- *
- * @param string $string
- * @return string
- */
-function kses_normalize_entities($string)
-###############################################################################
-# This function normalizes HTML entities. It will convert "AT&T" to the correct
-# "AT&amp;T", "&#00058;" to "&#58;", "&#XYZZY;" to "&amp;#XYZZY;" and so on.
-###############################################################################
-{
-# Disarm all entities by converting & to &amp;
-
-  $string = str_replace('&', '&amp;', $string);
-
-# Change back the allowed entities in our entity whitelist
-
-  $string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]{0,19});/',
-                         '&\\1;', $string);
-  $string = preg_replace('/&amp;#0*([0-9]{1,5});/e',
-                         'kses_normalize_entities2("\\1")', $string);
-  $string = preg_replace('/&amp;#([Xx])0*(([0-9A-Fa-f]{2}){1,2});/',
-                         '&#\\1\\2;', $string);
-
-  return $string;
-} # function kses_normalize_entities
-
-/**
- * This function helps kses_normalize_entities() to only accept 16 bit values
- * and nothing more for &#number; entities.
- *
- * @param int $i
- * @return string
- */
-function kses_normalize_entities2($i)
-###############################################################################
-# This function helps kses_normalize_entities() to only accept 16 bit values
-# and nothing more for &#number; entities.
-###############################################################################
-{
-  return (($i > 65535) ? "&amp;#$i;" : "&#$i;");
-} # function kses_normalize_entities2
-
-/**
- * This function decodes numeric HTML entities (&#65; and &#x41;). It doesn't
- * do anything with other entities like &auml;, but we don't need them in the
- * URL protocol whitelisting system anyway.
- *
- * @param string $string
- * @return string
- */
-function kses_decode_entities($string)
-###############################################################################
-# This function decodes numeric HTML entities (&#65; and &#x41;). It doesn't
-# do anything with other entities like &auml;, but we don't need them in the
-# URL protocol whitelisting system anyway.
-###############################################################################
-{
-  $string = preg_replace('/&#([0-9]+);/e', 'chr("\\1")', $string);
-  $string = preg_replace('/&#[Xx]([0-9A-Fa-f]+);/e', 'chr(hexdec("\\1"))',
-                         $string);
-
-  return $string;
-} # function kses_decode_entities
-
-?>
diff --git a/lib/md5.js b/lib/md5.js
deleted file mode 100644 (file)
index 46d2aab..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
- * Digest Algorithm, as defined in RFC 1321.
- * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for more info.
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
-var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
-var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
-function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
-function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
-function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
-function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
-function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
-
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function md5_vm_test()
-{
-  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
-}
-
-/*
- * Calculate the MD5 of an array of little-endian words, and a bit length
- */
-function core_md5(x, len)
-{
-  /* append padding */
-  x[len >> 5] |= 0x80 << ((len) % 32);
-  x[(((len + 64) >>> 9) << 4) + 14] = len;
-
-  var a =  1732584193;
-  var b = -271733879;
-  var c = -1732584194;
-  var d =  271733878;
-
-  for(var i = 0; i < x.length; i += 16)
-  {
-    var olda = a;
-    var oldb = b;
-    var oldc = c;
-    var oldd = d;
-
-    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
-    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
-    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
-    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
-    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
-    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
-    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
-    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
-    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
-    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
-    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
-    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
-    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
-    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
-    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
-    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
-
-    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
-    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
-    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
-    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
-    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
-    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
-    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
-    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
-    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
-    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
-    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
-    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
-    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
-    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
-    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
-    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
-
-    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
-    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
-    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
-    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
-    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
-    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
-    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
-    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
-    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
-    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
-    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
-    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
-    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
-    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
-    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
-    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
-
-    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
-    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
-    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
-    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
-    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
-    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
-    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
-    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
-    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
-    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
-    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
-    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
-    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
-    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
-    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
-    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
-
-    a = safe_add(a, olda);
-    b = safe_add(b, oldb);
-    c = safe_add(c, oldc);
-    d = safe_add(d, oldd);
-  }
-  return Array(a, b, c, d);
-
-}
-
-/*
- * These functions implement the four basic operations the algorithm uses.
- */
-function md5_cmn(q, a, b, x, s, t)
-{
-  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
-}
-function md5_ff(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
-}
-function md5_gg(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
-}
-function md5_hh(a, b, c, d, x, s, t)
-{
-  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
-}
-function md5_ii(a, b, c, d, x, s, t)
-{
-  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
-}
-
-/*
- * Calculate the HMAC-MD5, of a key and some data
- */
-function core_hmac_md5(key, data)
-{
-  var bkey = str2binl(key);
-  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
-
-  var ipad = Array(16), opad = Array(16);
-  for(var i = 0; i < 16; i++)
-  {
-    ipad[i] = bkey[i] ^ 0x36363636;
-    opad[i] = bkey[i] ^ 0x5C5C5C5C;
-  }
-
-  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
-  return core_md5(opad.concat(hash), 512 + 128);
-}
-
-/*
- * Add integers, wrapping at 2^32. This uses 16-bit operations internally
- * to work around bugs in some JS interpreters.
- */
-function safe_add(x, y)
-{
-  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
-  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-  return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Bitwise rotate a 32-bit number to the left.
- */
-function bit_rol(num, cnt)
-{
-  return (num << cnt) | (num >>> (32 - cnt));
-}
-
-/*
- * Convert a string to an array of little-endian words
- * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
- */
-function str2binl(str)
-{
-  var bin = Array();
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < str.length * chrsz; i += chrsz)
-    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
-  return bin;
-}
-
-/*
- * Convert an array of little-endian words to a string
- */
-function binl2str(bin)
-{
-  var str = "";
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < bin.length * 32; i += chrsz)
-    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a hex string.
- */
-function binl2hex(binarray)
-{
-  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i++)
-  {
-    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
-           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
-  }
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a base-64 string
- */
-function binl2b64(binarray)
-{
-  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i += 3)
-  {
-    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
-                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
-                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
-    for(var j = 0; j < 4; j++)
-    {
-      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
-      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
-    }
-  }
-  return str;
-}
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..2a9fed0 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
  *
@@ -9827,11 +9709,6 @@ function get_performance_info() {
     $info['html'] .= '<span class="dbqueries">DB reads/writes: '.$info['dbqueries'].'</span> ';
     $info['txt'] .= 'db reads/writes: '.$info['dbqueries'].' ';
 
-    if (!empty($PERF->profiling) && $PERF->profiling) {
-        require_once($CFG->dirroot .'/lib/profilerlib.php');
-        $info['html'] .= '<span class="profilinginfo">'.Profiler::get_profiling(array('-R')).'</span>';
-    }
-
     if (function_exists('posix_times')) {
         $ptimes = posix_times();
         if (is_array($ptimes)) {
diff --git a/lib/odbc.php b/lib/odbc.php
deleted file mode 100644 (file)
index 3c773a3..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-/**
- * odbc.php - This is the ODBC Socket Server class PHP client class 
- * with sample usage at bottom.
- *
- * Released into the public domain for version 0.90 of ODBC Socket Server
- * {@link http://odbc.linuxbox.com/}
- * 
- * @package moodlecore
- * @author Team FXML
- * @copyright Copyright (c) 1999 Team FXML
- * @license http://odbc.linuxbox.com/ public domain
- */
-/**
- * ODBC Socket Server class
- *
- * @package moodlecore
- * @copyright Copyright (c) 1999 Team FXML
- * @license http://odbc.linuxbox.com/ public domain
- */
-class ODBCSocketServer {
-
-   /**
-    * Name of the host to connect to
-    * @var string $sHostName 
-    */
-    var $sHostName;
-   /**
-    * Port to connect to
-    * @var int $nPort 
-    */
-    var $nPort;
-   /**
-    * Connection string to use
-    * @var string $sConnectionString 
-    */
-    var $sConnectionString;
-
-    // 
-    /** 
-     * Function to parse the SQL
-     *
-     * @param string $sSQL The SQL statement to parse
-     * @return string
-     */
-    function ExecSQL($sSQL) {
-
-        $fToOpen = fsockopen($this->sHostName, $this->nPort, &$errno, &$errstr, 30);
-        if (!$fToOpen)
-        {
-            //contruct error string to return
-            $sReturn = "<?xml version=\"1.0\"?>\r\n<result state=\"failure\">\r\n<error>$errstr</error>\r\n</result>\r\n";
-        }
-        else
-        {
-            //construct XML to send
-            //search and replace HTML chars in SQL first
-            $sSQL = HTMLSpecialChars($sSQL);
-            $sSend = "<?xml version=\"1.0\"?>\r\n<request>\r\n<connectionstring>$this->sConnectionString</connectionstring>\r\n<sql>$sSQL</sql>\r\n</request>\r\n";
-            //write request
-            fputs($fToOpen, $sSend);
-            //now read response
-            while (!feof($fToOpen))
-            {
-                $sReturn = $sReturn . fgets($fToOpen, 128);
-            }
-            fclose($fToOpen);
-        }
-        return $sReturn;
-    }
-}//class
-?>
diff --git a/lib/overlib/overlib.js b/lib/overlib/overlib.js
deleted file mode 100644 (file)
index f4ce770..0000000
+++ /dev/null
@@ -1,1491 +0,0 @@
-//\/////
-//\  overLIB 4.21 - You may not remove or change this notice.
-//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
-//\
-//\  Contributors are listed on the homepage.
-//\  This file might be old, always check for the latest version at:
-//\  http://www.bosrup.com/web/overlib/
-//\
-//\  Please read the license agreement (available through the link above)
-//\  before using overLIB. Direct any licensing questions to erik@bosrup.com.
-//\
-//\  Do not sell this as your own work or remove this copyright notice. 
-//\  For full details on copying or changing this script please read the
-//\  license agreement at the link above. Please give credit on sites that
-//\  use overLIB and submit changes of the script so other people can use
-//\  them as well.
-//   $Revision$                $Date$
-//\/////
-//\mini
-
-////////
-// PRE-INIT
-// Ignore these lines, configuration is below.
-////////
-var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pmt=''; var pms = new Array(); var olInfo = new Info('4.21', 1);
-var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3; var FCHAIN=4;
-var olHideForm=0;  // parameter for hiding SELECT and ActiveX elements in IE5.5+ 
-var olHautoFlag = 0;  // flags for over-riding VAUTO and HAUTO if corresponding
-var olVautoFlag = 0;  // positioning commands are used on the command line
-var hookPts = new Array(), postParse = new Array(), cmdLine = new Array(), runTime = new Array();
-// for plugins
-registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,compatmode,cssclass,fgclass,bgclass,textfontclass,captionfontclass,closefontclass');
-
-////////
-// DEFAULT CONFIGURATION
-// Settings you want everywhere are set here. All of this can also be
-// changed on your html page or through an overLIB call.
-////////
-if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF";
-if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399";
-if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";
-if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";
-if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF";
-if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica";
-if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica";
-if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica";
-if (typeof ol_textsize=='undefined') var ol_textsize="1";
-if (typeof ol_captionsize=='undefined') var ol_captionsize="1";
-if (typeof ol_closesize=='undefined') var ol_closesize="1";
-if (typeof ol_width=='undefined') var ol_width="200";
-if (typeof ol_border=='undefined') var ol_border="1";
-if (typeof ol_cellpad=='undefined') var ol_cellpad=2;
-if (typeof ol_offsetx=='undefined') var ol_offsetx=10;
-if (typeof ol_offsety=='undefined') var ol_offsety=10;
-if (typeof ol_text=='undefined') var ol_text="Default Text";
-if (typeof ol_cap=='undefined') var ol_cap="";
-if (typeof ol_sticky=='undefined') var ol_sticky=0;
-if (typeof ol_background=='undefined') var ol_background="";
-if (typeof ol_close=='undefined') var ol_close="Close";
-if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;
-if (typeof ol_status=='undefined') var ol_status="";
-if (typeof ol_autostatus=='undefined') var ol_autostatus=0;
-if (typeof ol_height=='undefined') var ol_height=-1;
-if (typeof ol_snapx=='undefined') var ol_snapx=0;
-if (typeof ol_snapy=='undefined') var ol_snapy=0;
-if (typeof ol_fixx=='undefined') var ol_fixx=-1;
-if (typeof ol_fixy=='undefined') var ol_fixy=-1;
-if (typeof ol_relx=='undefined') var ol_relx=null;
-if (typeof ol_rely=='undefined') var ol_rely=null;
-if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";
-if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";
-if (typeof ol_padxl=='undefined') var ol_padxl=1;
-if (typeof ol_padxr=='undefined') var ol_padxr=1;
-if (typeof ol_padyt=='undefined') var ol_padyt=1;
-if (typeof ol_padyb=='undefined') var ol_padyb=1;
-if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;
-if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;
-if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;
-if (typeof ol_capicon=='undefined') var ol_capicon="";
-if (typeof ol_frame=='undefined') var ol_frame=self;
-if (typeof ol_timeout=='undefined') var ol_timeout=0;
-if (typeof ol_function=='undefined') var ol_function=null;
-if (typeof ol_delay=='undefined') var ol_delay=0;
-if (typeof ol_hauto=='undefined') var ol_hauto=0;
-if (typeof ol_vauto=='undefined') var ol_vauto=0;
-if (typeof ol_closeclick=='undefined') var ol_closeclick=0;
-if (typeof ol_wrap=='undefined') var ol_wrap=0;
-if (typeof ol_followmouse=='undefined') var ol_followmouse=1;
-if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;
-if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';
-if (typeof ol_compatmode=='undefined') var ol_compatmode=0;
-if (typeof ol_css=='undefined') var ol_css=CSSOFF;
-if (typeof ol_fgclass=='undefined') var ol_fgclass="";
-if (typeof ol_bgclass=='undefined') var ol_bgclass="";
-if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";
-if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";
-if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
-
-////////
-// ARRAY CONFIGURATION
-////////
-
-// You can use these arrays to store popup text here instead of in the html.
-if (typeof ol_texts=='undefined') var ol_texts = new Array("Text 0", "Text 1");
-if (typeof ol_caps=='undefined') var ol_caps = new Array("Caption 0", "Caption 1");
-
-////////
-// END OF CONFIGURATION
-// Don't change anything below this line, all configuration is above.
-////////
-
-
-
-
-
-////////
-// INIT
-////////
-// Runtime variables init. Don't change for config!
-var o3_text="";
-var o3_cap="";
-var o3_sticky=0;
-var o3_background="";
-var o3_close="Close";
-var o3_hpos=RIGHT;
-var o3_offsetx=2;
-var o3_offsety=2;
-var o3_fgcolor="";
-var o3_bgcolor="";
-var o3_textcolor="";
-var o3_capcolor="";
-var o3_closecolor="";
-var o3_width=100;
-var o3_border=1;
-var o3_cellpad=2;
-var o3_status="";
-var o3_autostatus=0;
-var o3_height=-1;
-var o3_snapx=0;
-var o3_snapy=0;
-var o3_fixx=-1;
-var o3_fixy=-1;
-var o3_relx=null;
-var o3_rely=null;
-var o3_fgbackground="";
-var o3_bgbackground="";
-var o3_padxl=0;
-var o3_padxr=0;
-var o3_padyt=0;
-var o3_padyb=0;
-var o3_fullhtml=0;
-var o3_vpos=BELOW;
-var o3_aboveheight=0;
-var o3_capicon="";
-var o3_textfont="Verdana,Arial,Helvetica";
-var o3_captionfont="Verdana,Arial,Helvetica";
-var o3_closefont="Verdana,Arial,Helvetica";
-var o3_textsize="1";
-var o3_captionsize="1";
-var o3_closesize="1";
-var o3_frame=self;
-var o3_timeout=0;
-var o3_timerid=0;
-var o3_allowmove=0;
-var o3_function=null; 
-var o3_delay=0;
-var o3_delayid=0;
-var o3_hauto=0;
-var o3_vauto=0;
-var o3_closeclick=0;
-var o3_wrap=0;
-var o3_followmouse=1;
-var o3_mouseoff=0;
-var o3_closetitle='';
-var o3_compatmode=0;
-var o3_css=CSSOFF;
-var o3_fgclass="";
-var o3_bgclass="";
-var o3_textfontclass="";
-var o3_captionfontclass="";
-var o3_closefontclass="";
-
-// Display state variables
-var o3_x = 0;
-var o3_y = 0;
-var o3_showingsticky = 0;
-var o3_removecounter = 0;
-
-// Our layer
-var over = null;
-var fnRef, hoveringSwitch = false;
-var olHideDelay;
-
-// Decide browser version
-var isMac = (navigator.userAgent.indexOf("Mac") != -1);
-var olOp = (navigator.userAgent.toLowerCase().indexOf('opera') > -1 && document.createTextNode);  // Opera 7
-var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4);
-var olNs6 = (document.getElementById) ? true : false;
-var olKq = (olNs6 && /konqueror/i.test(navigator.userAgent));
-var olIe4 = (document.all) ? true : false;
-var olIe5 = false; 
-var olIe55 = false; // Added additional variable to identify IE5.5+
-var docRoot = 'document.body';
-
-// Resize fix for NS4.x to keep track of layer
-if (olNs4) {
-       var oW = window.innerWidth;
-       var oH = window.innerHeight;
-       window.onresize = function() { if (oW != window.innerWidth || oH != window.innerHeight) location.reload(); }
-}
-
-// Microsoft Stupidity Check(tm).
-if (olIe4) {
-       var agent = navigator.userAgent;
-       if (/MSIE/.test(agent)) {
-               var versNum = parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/i)[1]);
-               if (versNum >= 5){
-                       olIe5=true;
-                       olIe55=(versNum>=5.5&&!olOp) ? true : false;
-                       if (olNs6) olNs6=false;
-               }
-       }
-       if (olNs6) olIe4 = false;
-}
-
-// Check for compatability mode.
-if (document.compatMode && document.compatMode == 'CSS1Compat') {
-       docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot);
-}
-
-// Add window onload handlers to indicate when all modules have been loaded
-// For Netscape 6+ and Mozilla, uses addEventListener method on the window object
-// For IE it uses the attachEvent method of the window object and for Netscape 4.x
-// it sets the window.onload handler to the OLonload_handler function for Bubbling
-if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,false);
-else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);
-
-var capExtent;
-
-////////
-// PUBLIC FUNCTIONS
-////////
-
-// overlib(arg0,...,argN)
-// Loads parameters into global runtime variables.
-function overlib() {
-       if (!olLoaded || isExclusive(overlib.arguments)) return true;
-       if (olCheckMouseCapture) olMouseCapture();
-       if (over) {
-               over = (typeof over.id != 'string') ? o3_frame.document.all['overDiv'] : over;
-               cClick();
-       }
-
-       // Load defaults to runtime.
-  olHideDelay=0;
-       o3_text=ol_text;
-       o3_cap=ol_cap;
-       o3_sticky=ol_sticky;
-       o3_background=ol_background;
-       o3_close=ol_close;
-       o3_hpos=ol_hpos;
-       o3_offsetx=ol_offsetx;
-       o3_offsety=ol_offsety;
-       o3_fgcolor=ol_fgcolor;
-       o3_bgcolor=ol_bgcolor;
-       o3_textcolor=ol_textcolor;
-       o3_capcolor=ol_capcolor;
-       o3_closecolor=ol_closecolor;
-       o3_width=ol_width;
-       o3_border=ol_border;
-       o3_cellpad=ol_cellpad;
-       o3_status=ol_status;
-       o3_autostatus=ol_autostatus;
-       o3_height=ol_height;
-       o3_snapx=ol_snapx;
-       o3_snapy=ol_snapy;
-       o3_fixx=ol_fixx;
-       o3_fixy=ol_fixy;
-       o3_relx=ol_relx;
-       o3_rely=ol_rely;
-       o3_fgbackground=ol_fgbackground;
-       o3_bgbackground=ol_bgbackground;
-       o3_padxl=ol_padxl;
-       o3_padxr=ol_padxr;
-       o3_padyt=ol_padyt;
-       o3_padyb=ol_padyb;
-       o3_fullhtml=ol_fullhtml;
-       o3_vpos=ol_vpos;
-       o3_aboveheight=ol_aboveheight;
-       o3_capicon=ol_capicon;
-       o3_textfont=ol_textfont;
-       o3_captionfont=ol_captionfont;
-       o3_closefont=ol_closefont;
-       o3_textsize=ol_textsize;
-       o3_captionsize=ol_captionsize;
-       o3_closesize=ol_closesize;
-       o3_timeout=ol_timeout;
-       o3_function=ol_function;
-       o3_delay=ol_delay;
-       o3_hauto=ol_hauto;
-       o3_vauto=ol_vauto;
-       o3_closeclick=ol_closeclick;
-       o3_wrap=ol_wrap;        
-       o3_followmouse=ol_followmouse;
-       o3_mouseoff=ol_mouseoff;
-       o3_closetitle=ol_closetitle;
-       o3_css=ol_css;
-       o3_compatmode=ol_compatmode;
-       o3_fgclass=ol_fgclass;
-       o3_bgclass=ol_bgclass;
-       o3_textfontclass=ol_textfontclass;
-       o3_captionfontclass=ol_captionfontclass;
-       o3_closefontclass=ol_closefontclass;
-       
-       setRunTimeVariables();
-       
-       fnRef = '';
-       
-       // Special for frame support, over must be reset...
-       o3_frame = ol_frame;
-       
-       if(!(over=createDivContainer())) return false;
-
-       parseTokens('o3_', overlib.arguments);
-       if (!postParseChecks()) return false;
-
-       if (o3_delay == 0) {
-               return runHook("olMain", FREPLACE);
-       } else {
-               o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay);
-               return false;
-       }
-}
-
-// Clears popups if appropriate
-function nd(time) {
-       if (olLoaded && !isExclusive()) {
-               hideDelay(time);  // delay popup close if time specified
-
-               if (o3_removecounter >= 1) { o3_showingsticky = 0 };
-               
-               if (o3_showingsticky == 0) {
-                       o3_allowmove = 0;
-                       if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over);
-               } else {
-                       o3_removecounter++;
-               }
-       }
-       
-       return true;
-}
-
-// The Close onMouseOver function for stickies
-function cClick() {
-       if (olLoaded) {
-               runHook("hideObject", FREPLACE, over);
-               o3_showingsticky = 0;   
-       }       
-       return false;
-}
-
-// Method for setting page specific defaults.
-function overlib_pagedefaults() {
-       parseTokens('ol_', overlib_pagedefaults.arguments);
-}
-
-
-////////
-// OVERLIB MAIN FUNCTION
-////////
-
-// This function decides what it is we want to display and how we want it done.
-function olMain() {
-       var layerhtml, styleType;
-       runHook("olMain", FBEFORE);
-       
-       if (o3_background!="" || o3_fullhtml) {
-               // Use background instead of box.
-               layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);
-       } else {
-               // They want a popup box.
-               styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass");
-
-               // Prepare popup background
-               if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\"";
-               if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground);
-
-               // Prepare popup colors
-               if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor);
-               if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor);
-
-               // Prepare popup height
-               if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height);
-               else o3_height = "";
-
-               // Decide which kinda box.
-               if (o3_cap=="") {
-                       // Plain
-                       layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);
-               } else {
-                       // With caption
-                       if (o3_sticky) {
-                               // Show close text
-                               layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);
-                       } else {
-                               // No close text
-                               layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");
-                       }
-               }
-       }       
-
-       // We want it to stick!
-       if (o3_sticky) {
-               if (o3_timerid > 0) {
-                       clearTimeout(o3_timerid);
-                       o3_timerid = 0;
-               }
-               o3_showingsticky = 1;
-               o3_removecounter = 0;
-       }
-
-       // Created a separate routine to generate the popup to make it easier
-       // to implement a plugin capability
-       if (!runHook("createPopup", FREPLACE, layerhtml)) return false;
-
-       // Prepare status bar
-       if (o3_autostatus > 0) {
-               o3_status = o3_text;
-               if (o3_autostatus > 1) o3_status = o3_cap;
-       }
-
-       // When placing the layer the first time, even stickies may be moved.
-       o3_allowmove = 0;
-
-       // Initiate a timer for timeout
-       if (o3_timeout > 0) {          
-               if (o3_timerid > 0) clearTimeout(o3_timerid);
-               o3_timerid = setTimeout("cClick()", o3_timeout);
-       }
-
-       // Show layer
-       runHook("disp", FREPLACE, o3_status);
-       runHook("olMain", FAFTER);
-
-       return (olOp && event && event.type == 'mouseover' && !o3_status) ? '' : (o3_status != '');
-}
-
-////////
-// LAYER GENERATION FUNCTIONS
-////////
-// These functions just handle popup content with tags that should adhere to the W3C standards specification.
-
-// Makes simple table without caption
-function ol_content_simple(text) {
-       var cpIsMultiple = /,/.test(o3_cellpad);
-       var txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" '+((olNs4||!cpIsMultiple) ? 'cellpadding="'+o3_cellpad+'" ' : '')+'cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' : ((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td></tr></table></td></tr></table>';
-
-       set_background("");
-       return txt;
-}
-
-// Makes table with caption and optional close link
-function ol_content_caption(text,title,close) {
-       var nameId, txt, cpIsMultiple = /,/.test(o3_cellpad);
-       var closing, closeevent;
-
-       closing = "";
-       closeevent = "onmouseover";
-       if (o3_closeclick == 1) closeevent = (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick";
-       if (o3_capicon != "") {
-         nameId = ' hspace = \"5\"'+' align = \"middle\" alt = \"\"';
-         if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId =' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
-         o3_capicon = '<img src=\"'+o3_capicon+'\"'+nameId+' />';
-       }
-
-       if (close != "")
-               closing = '<td '+(!o3_compatmode && o3_closefontclass ? 'class="'+o3_closefontclass : 'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();"'+((o3_compatmode && o3_closefontclass) ? ' class="' + o3_closefontclass + '" ' : ' ')+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+'</a></td>';
-       txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_bgbackground+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="2" cellspacing="0"><tr><td'+(o3_captionfontclass ? ' class="'+o3_captionfontclass+'">' : '>')+(o3_captionfontclass ? '' : '<b>'+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'</b>')+'</td>'+closing+'</tr></table><table width="100%" border="0" '+((olNs4||!cpIsMultiple) ? 'cellpadding="'+o3_cellpad+'" ' : '')+'cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' :((!olNs4&&cpIsMultiple) ? ' style="'+setCellPadStr(o3_cellpad)+'">' : '>'))+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize)) + '</td></tr></table></td></tr></table>';
-
-       set_background("");
-       return txt;
-}
-
-// Sets the background picture,padding and lots more. :)
-function ol_content_background(text,picture,hasfullhtml) {
-       if (hasfullhtml) {
-               txt=text;
-       } else {
-               txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+(o3_textfontclass ? '" class="'+o3_textfontclass : '')+'">'+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';
-       }
-
-       set_background(picture);
-       return txt;
-}
-
-// Loads a picture into the div.
-function set_background(pic) {
-       if (pic == "") {
-               if (olNs4) {
-                       over.background.src = null; 
-               } else if (over.style) {
-                       over.style.backgroundImage = "none";
-               }
-       } else {
-               if (olNs4) {
-                       over.background.src = pic;
-               } else if (over.style) {
-                       over.style.width=o3_width + 'px';
-                       over.style.backgroundImage = "url("+pic+")";
-               }
-       }
-}
-
-////////
-// HANDLING FUNCTIONS
-////////
-var olShowId=-1;
-
-// Displays the popup
-function disp(statustext) {
-       runHook("disp", FBEFORE);
-       
-       if (o3_allowmove == 0) {
-               runHook("placeLayer", FREPLACE);
-               (olNs6&&olShowId<0) ? olShowId=setTimeout("runHook('showObject', FREPLACE, over)", 1) : runHook("showObject", FREPLACE, over);
-               o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1;
-       }
-       
-       runHook("disp", FAFTER);
-
-       if (statustext != "") self.status = statustext;
-}
-
-// Creates the actual popup structure
-function createPopup(lyrContent){
-       runHook("createPopup", FBEFORE);
-       
-       if (o3_wrap) {
-               var wd,ww,theObj = (olNs4 ? over : over.style);
-               theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
-               layerWrite(lyrContent);
-               wd = (olNs4 ? over.clip.width : over.offsetWidth);
-               if (wd > (ww=windowWidth())) {
-                       lyrContent=lyrContent.replace(/\&nbsp;/g, ' ');
-                       o3_width=ww;
-                       o3_wrap=0;
-               } 
-       }
-
-       layerWrite(lyrContent);
-       
-       // Have to set o3_width for placeLayer() routine if o3_wrap is turned on
-       if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth);
-       
-       runHook("createPopup", FAFTER, lyrContent);
-
-       return true;
-}
-
-// Decides where we want the popup.
-function placeLayer() {
-       var placeX, placeY, widthFix = 0;
-       
-       // HORIZONTAL PLACEMENT, re-arranged to work in Safari
-       if (o3_frame.innerWidth) widthFix=18; 
-       iwidth = windowWidth();
-
-       // Horizontal scroll offset
-       winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
-
-       placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
-
-       // VERTICAL PLACEMENT, re-arranged to work in Safari
-       if (o3_frame.innerHeight) {
-               iheight=o3_frame.innerHeight;
-       } else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) { 
-               iheight=eval('o3_frame.'+docRoot+'.clientHeight');
-       }                       
-
-       // Vertical scroll offset
-       scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
-       placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
-
-       // Actually move the object.
-       repositionTo(over, placeX, placeY);
-}
-
-// Moves the layer
-function olMouseMove(e) {
-       var e = (e) ? e : event;
-
-       if (e.pageX) {
-               o3_x = e.pageX;
-               o3_y = e.pageY;
-       } else if (e.clientX) {
-               o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');
-               o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');
-       }
-       
-       if (o3_allowmove == 1) runHook("placeLayer", FREPLACE);
-
-       // MouseOut handler
-       if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) {
-               (olHideDelay ? hideDelay(olHideDelay) : cClick());
-               hoveringSwitch = !hoveringSwitch;
-       }
-}
-
-// Fake function for 3.0 users.
-function no_overlib() { return ver3fix; }
-
-// Capture the mouse and chain other scripts.
-function olMouseCapture() {
-       capExtent = document;
-       var fN, str = '', l, k, f, wMv, sS, mseHandler = olMouseMove;
-       var re = /function[ ]*(\w*)\(/;
-       
-       wMv = (!olIe4 && window.onmousemove);
-       if (document.onmousemove || wMv) {
-               if (wMv) capExtent = window;
-               f = capExtent.onmousemove.toString();
-               fN = f.match(re);
-               if (fN == null) {
-                       str = f+'(e); ';
-               } else if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove' || (wMv && fN[1] == 'onmousemove')) {
-                       if (!olOp && wMv) {
-                               l = f.indexOf('{')+1;
-                               k = f.lastIndexOf('}');
-                               sS = f.substring(l,k);
-                               if ((l = sS.indexOf('(')) != -1) {
-                                       sS = sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,'');
-                                       if (eval("typeof " + sS + " == 'undefined'")) window.onmousemove = null;
-                                       else str = sS + '(e);';
-                               }
-                       }
-                       if (!str) {
-                               olCheckMouseCapture = false;
-                               return;
-                       }
-               } else {
-                       if (fN[1]) str = fN[1]+'(e); ';
-                       else {
-                               l = f.indexOf('{')+1;
-                               k = f.lastIndexOf('}');
-                               str = f.substring(l,k) + '\n';
-                       }
-               }
-               str += 'olMouseMove(e); ';
-               mseHandler = new Function('e', str);
-       }
-
-       capExtent.onmousemove = mseHandler;
-       if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);
-}
-
-////////
-// PARSING FUNCTIONS
-////////
-
-// Does the actual command parsing.
-function parseTokens(pf, ar) {
-       // What the next argument is expected to be.
-       var v, i, mode=-1, par = (pf != 'ol_'); 
-       var fnMark = (par && !ar.length ? 1 : 0);
-
-       for (i = 0; i < ar.length; i++) {
-               if (mode < 0) {
-                       // Arg is maintext,unless its a number between pmStart and pmUpper
-                       // then its a command.
-                       if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) {
-                               fnMark = (par ? 1 : 0);
-                               i--;   // backup one so that the next block can parse it
-                       } else {
-                               switch(pf) {
-                                       case 'ol_':
-                                               ol_text = ar[i].toString();
-                                               break;
-                                       default:
-                                               o3_text=ar[i].toString();  
-                               }
-                       }
-                       mode = 0;
-               } else {
-                       // Note: NS4 doesn't like switch cases with vars.
-                       if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; }
-                       if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; }
-                       if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; }
-                       if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; }
-                       if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; }
-                       if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); if(pf!='ol_') olHautoFlag=1; continue; }
-                       if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; }
-                       if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; }
-                       if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; }
-                       if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; }
-                       if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; }
-                       if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; }
-                       if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; }
-                       if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again.
-                       if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; }
-                       if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; }
-                       if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; }
-                       if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; }
-                       if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; }
-                       if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; }
-                       if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; }
-                       if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; }
-                       if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; }
-                       if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); if (pf!='ol_') olVautoFlag=1; continue; }
-                       if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; }
-                       if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i];  opt_FUNCTION(v); } continue; }
-                       if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; }
-                       if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; }
-                       if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; }
-                       if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; }
-                       if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; }
-                       if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; }
-                       if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff==0) ? 1 : 0'); v=ar[i+1]; if (pf != 'ol_' && eval(pf+'mouseoff') && typeof v == 'number' && (v < pmStart || v > pmUpper)) olHideDelay=ar[++i]; continue; }
-                       if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; }
-                       if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; }
-                       if (ar[i]==COMPATMODE) { eval(pf+'compatmode=('+pf+'compatmode==0) ? 1 : 0'); continue; }
-                       if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; }
-                       if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; }
-                       i = parseCmdLine(pf, i, ar);
-               }
-       }
-
-       if (fnMark && o3_function) o3_text = o3_function();
-       
-       if ((pf == 'o3_') && o3_wrap) {
-               o3_width = 0;
-               
-               var tReg=/<.*\n*>/ig;
-               if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, '&nbsp;');
-               if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, '&nbsp;');
-       }
-       if ((pf == 'o3_') && o3_sticky) {
-               if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close;
-               if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' ');
-       }
-}
-
-
-////////
-// LAYER FUNCTIONS
-////////
-
-// Writes to a layer
-function layerWrite(txt) {
-       txt += "\n";
-       if (olNs4) {
-               var lyr = o3_frame.document.layers['overDiv'].document
-               lyr.write(txt)
-               lyr.close()
-       } else if (typeof over.innerHTML != 'undefined') {
-               if (olIe5 && isMac) over.innerHTML = '';
-               over.innerHTML = txt;
-       } else {
-               range = o3_frame.document.createRange();
-               range.setStartAfter(over);
-               domfrag = range.createContextualFragment(txt);
-               
-               while (over.hasChildNodes()) {
-                       over.removeChild(over.lastChild);
-               }
-               
-               over.appendChild(domfrag);
-       }
-}
-
-// Make an object visible
-function showObject(obj) {
-       runHook("showObject", FBEFORE);
-
-       var theObj=(olNs4 ? obj : obj.style);
-       theObj.visibility = 'visible';
-
-       runHook("showObject", FAFTER);
-}
-
-// Hides an object
-function hideObject(obj) {
-       runHook("hideObject", FBEFORE);
-
-       var theObj=(olNs4 ? obj : obj.style);
-       if (olNs6 && olShowId>0) { clearTimeout(olShowId); olShowId=0; }
-       theObj.visibility = 'hidden';
-       theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
-
-       if (o3_timerid > 0) clearTimeout(o3_timerid);
-       if (o3_delayid > 0) clearTimeout(o3_delayid);
-
-       o3_timerid = 0;
-       o3_delayid = 0;
-       self.status = "";
-
-       if (obj.onmouseout||obj.onmouseover) {
-               if (olNs4) obj.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER);
-               obj.onmouseout = obj.onmouseover = null;
-       }
-
-       runHook("hideObject", FAFTER);
-}
-
-// Move a layer
-function repositionTo(obj, xL, yL) {
-       var theObj=(olNs4 ? obj : obj.style);
-       theObj.left = xL + (!olNs4 ? 'px' : 0);
-       theObj.top = yL + (!olNs4 ? 'px' : 0);
-}
-
-// Check position of cursor relative to overDiv DIVision; mouseOut function
-function cursorOff() {
-       var left = parseInt(over.style.left);
-       var top = parseInt(over.style.top);
-       var right = left + (over.offsetWidth >= parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width));
-       var bottom = top + (over.offsetHeight >= o3_aboveheight ? over.offsetHeight : o3_aboveheight);
-
-       if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
-
-       return false;
-}
-
-
-////////
-// COMMAND FUNCTIONS
-////////
-
-// Calls callme or the default function.
-function opt_FUNCTION(callme) {
-       o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function'));
-
-       return 0;
-}
-
-// Handle hovering
-function opt_NOCLOSE(unused) {
-       if (!unused) o3_close = "";
-
-       if (olNs4) {
-               over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER);
-               over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } }
-               over.onmouseout = function (e) { if (olHideDelay) hideDelay(olHideDelay); else cClick(e); }
-       } else {
-               over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } }
-       }
-
-       return 0;
-}
-
-// Function to scan command line arguments for multiples
-function opt_MULTIPLEARGS(i, args, parameter) {
-  var k=i, re, pV, str='';
-
-  for(k=i; k<args.length; k++) {
-               if(typeof args[k] == 'number' && args[k]