Merge branch 'MDL-40472-master' of git://github.com/damyon/moodle
authorMarina Glancy <marina@moodle.com>
Tue, 9 Jul 2013 11:34:49 +0000 (21:34 +1000)
committerMarina Glancy <marina@moodle.com>
Tue, 9 Jul 2013 11:34:49 +0000 (21:34 +1000)
357 files changed:
admin/cli/install.php
admin/cli/install_database.php
admin/cli/upgrade.php
admin/handlevirus.php
admin/index.php
admin/localplugins.php
admin/oacleanup.php
admin/plugins.php
admin/roles/classes/check_capability_table.php
admin/roles/classes/permissions_table.php
admin/roles/usersroles.php
admin/settings/security.php
admin/settings/users.php
admin/tool/behat/cli/init.php
admin/tool/capability/classes/settings_form.php [new file with mode: 0644]
admin/tool/capability/index.php
admin/tool/capability/lang/en/tool_capability.php
admin/tool/capability/locallib.php [new file with mode: 0644]
admin/tool/capability/module.js [deleted file]
admin/tool/capability/renderer.php [new file with mode: 0644]
admin/tool/capability/settings.php
admin/tool/capability/styles.css [new file with mode: 0644]
admin/tool/capability/version.php
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js [new file with mode: 0644]
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js [new file with mode: 0644]
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js [new file with mode: 0644]
admin/tool/capability/yui/src/search/build.json [new file with mode: 0644]
admin/tool/capability/yui/src/search/js/search.js [new file with mode: 0644]
admin/tool/capability/yui/src/search/meta/search.json [new file with mode: 0644]
admin/tool/customlang/edit.php
admin/tool/customlang/index.php
admin/tool/generator/index.php
admin/tool/installaddon/yui/permcheck/permcheck.js
admin/tool/phpunit/cli/init.php
admin/tool/unsuproles/index.php
admin/user/user_bulk_cohortadd.php
admin/user/user_bulk_display.php
auth/ldap/auth.php
auth/ldap/tests/plugin_test.php [moved from auth/ldap/tests/ldap_test.php with 94% similarity]
auth/mnet/auth.php
auth/tests/behat/behat_auth.php
auth/tests/behat/login.feature
backup/moodle2/backup_stepslib.php
backup/util/dbops/restore_dbops.class.php
backup/util/ui/restore_ui_components.php
badges/renderer.php
blocks/edit_form.php
cache/locallib.php
calendar/lib.php
calendar/tests/externallib_test.php [moved from calendar/tests/externallib_tests.php with 98% similarity]
comment/lib.php
course/editcategory.php
course/editcategory_form.php
course/lib.php
course/view.php
enrol/category/locallib.php
enrol/cohort/lib.php
enrol/cohort/locallib.php
enrol/externallib.php
enrol/locallib.php
error/index.php
files/externallib.php
files/tests/externallib_test.php
filter/manage.php
grade/grading/lib.php
grade/grading/pick.php
grade/report/grader/lib.php
grade/report/upgrade.txt
group/index.php
group/overview.php
lang/en/admin.php
lang/en/moodle.php
lib/accesslib.php
lib/adminlib.php
lib/badgeslib.php
lib/blocklib.php
lib/classes/component.php
lib/coursecatlib.php
lib/datalib.php
lib/db/install.xml
lib/db/upgrade.php
lib/deprecatedlib.php
lib/dml/mssql_native_moodle_database.php
lib/editor/tinymce/db/upgrade.php
lib/editor/tinymce/lang/en/editor_tinymce.php
lib/editor/tinymce/lib.php
lib/editor/tinymce/plugins/moodlemedia/lib.php
lib/editor/tinymce/plugins/moodlenolink/lib.php
lib/editor/tinymce/plugins/pdw/lang/en/tinymce_pdw.php [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/lib.php [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/pix/icon.gif [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/readme_moodle.txt [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin_src.js [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/tinymce/img/toolbars.gif [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/tinymce/langs/en.js [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/tinymce/langs/nl.js [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/version.php [new file with mode: 0644]
lib/editor/tinymce/plugins/wrap/lang/en/tinymce_wrap.php [new file with mode: 0644]
lib/editor/tinymce/plugins/wrap/lib.php [new file with mode: 0644]
lib/editor/tinymce/plugins/wrap/tinymce/editor_plugin.js [new file with mode: 0644]
lib/editor/tinymce/plugins/wrap/version.php [new file with mode: 0644]
lib/editor/tinymce/settings.php
lib/editor/tinymce/styles.css
lib/editor/tinymce/upgrade.txt
lib/editor/tinymce/version.php
lib/enrollib.php
lib/externallib.php
lib/filebrowser/file_info_context_course.php
lib/filebrowser/file_info_context_coursecat.php
lib/filebrowser/file_info_context_module.php
lib/formslib.php
lib/gradelib.php
lib/messagelib.php
lib/modinfolib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputcomponents.php
lib/pagelib.php
lib/phpunit/bootstrap.php
lib/phpunit/classes/autoloader.php
lib/phpunit/classes/util.php
lib/phpunit/tests/advanced_test.php
lib/pluginlib.php
lib/questionlib.php
lib/setup.php
lib/setuplib.php
lib/tablelib.php
lib/testing/generator/data_generator.php
lib/tests/accesslib_test.php
lib/tests/behat/behat_general.php
lib/tests/moodlelib_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
login/token.php
mnet/service/enrol/index.php
mnet/service/enrol/locallib.php
mod/assign/adminmanageplugins.php
mod/assign/gradingtable.php
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/book/edit.php
mod/data/db/upgrade.php
mod/data/lib.php
mod/data/tests/search_test.php
mod/data/view.php
mod/feedback/delete_template.php
mod/feedback/edit.php
mod/feedback/edit_form.php
mod/feedback/item/label/lib.php
mod/feedback/lib.php
mod/forum/lib.php
mod/forum/user.php
mod/lti/mod_form.js
mod/quiz/renderer.php
mod/quiz/report/attemptsreport_table.php
mod/quiz/report/overview/overview_form.php
mod/scorm/lib.php
mod/scorm/mod_form.php
mod/scorm/report/basic/report.php
mod/scorm/report/interactions/report.php
mod/workshop/allocation/manual/lib.php
mod/workshop/locallib.php
pix/c/course.gif [deleted file]
pix/c/course.png [deleted file]
pix/c/course.svg [deleted file]
pix/c/group.gif [deleted file]
pix/c/group.png [deleted file]
pix/c/group.svg [deleted file]
pix/c/site.gif [deleted file]
pix/c/site.png [deleted file]
pix/c/site.svg [deleted file]
pix/c/user.gif [deleted file]
pix/c/user.png [deleted file]
pix/c/user.svg [deleted file]
pix/i/agg_mean.gif [deleted file]
pix/i/agg_sum.gif [deleted file]
pix/i/approve.gif [deleted file]
pix/i/approve.png [deleted file]
pix/i/approve.svg [deleted file]
pix/i/backup.gif [deleted file]
pix/i/calc.gif [deleted file]
pix/i/calendar.gif [deleted file]
pix/i/checkpermissions.gif [deleted file]
pix/i/cohort.gif [deleted file]
pix/i/configlock.gif [deleted file]
pix/i/course.gif [deleted file]
pix/i/cross_red_big.gif [deleted file]
pix/i/cross_red_big.png [deleted file]
pix/i/cross_red_big.svg [deleted file]
pix/i/cross_red_small.gif [deleted file]
pix/i/cross_red_small.png [deleted file]
pix/i/cross_red_small.svg [deleted file]
pix/i/db.gif [deleted file]
pix/i/edit.gif [deleted file]
pix/i/enrolmentsuspended.gif [deleted file]
pix/i/filter.gif [deleted file]
pix/i/grades.gif [deleted file]
pix/i/group.gif [deleted file]
pix/i/hide.gif [deleted file]
pix/i/hierarchylock.gif [deleted file]
pix/i/info.gif [deleted file]
pix/i/item.gif [deleted file]
pix/i/marked.gif [deleted file]
pix/i/marker.gif [deleted file]
pix/i/mnethost.gif [deleted file]
pix/i/move_2d.gif [deleted file]
pix/i/outcomes.gif [deleted file]
pix/i/permissionlock.gif [deleted file]
pix/i/permissions.gif [deleted file]
pix/i/reload.gif [deleted file]
pix/i/report.gif [deleted file]
pix/i/restore.gif [deleted file]
pix/i/return.gif [deleted file]
pix/i/risk_config.gif [deleted file]
pix/i/risk_dataloss.gif [deleted file]
pix/i/risk_managetrust.gif [deleted file]
pix/i/risk_personal.gif [deleted file]
pix/i/risk_spam.gif [deleted file]
pix/i/risk_xss.gif [deleted file]
pix/i/roles.gif [deleted file]
pix/i/roles.png [deleted file]
pix/i/roles.svg [deleted file]
pix/i/rss.gif [deleted file]
pix/i/scales.gif [deleted file]
pix/i/search.gif [deleted file]
pix/i/settings.gif [deleted file]
pix/i/show.gif [deleted file]
pix/i/tick_amber_big.gif [deleted file]
pix/i/tick_amber_big.png [deleted file]
pix/i/tick_amber_big.svg [deleted file]
pix/i/tick_amber_small.gif [deleted file]
pix/i/tick_amber_small.png [deleted file]
pix/i/tick_amber_small.svg [deleted file]
pix/i/tick_green_big.gif [deleted file]
pix/i/tick_green_big.png [deleted file]
pix/i/tick_green_big.svg [deleted file]
pix/i/tick_green_small.gif [deleted file]
pix/i/tick_green_small.png [deleted file]
pix/i/tick_green_small.svg [deleted file]
pix/i/user.gif [deleted file]
pix/i/users.gif [deleted file]
pix/t/add.gif [deleted file]
pix/t/addgreen.gif [deleted file]
pix/t/addgreen.png [deleted file]
pix/t/addgreen.svg [deleted file]
pix/t/backup.gif [deleted file]
pix/t/block.gif [deleted file]
pix/t/calc.gif [deleted file]
pix/t/calc_off.gif [deleted file]
pix/t/clear.gif [deleted file]
pix/t/clear.png [deleted file]
pix/t/clear.svg [deleted file]
pix/t/copy.gif [deleted file]
pix/t/delete.gif [deleted file]
pix/t/down.gif [deleted file]
pix/t/edit.gif [deleted file]
pix/t/email.gif [deleted file]
pix/t/emailno.gif [deleted file]
pix/t/go.gif [deleted file]
pix/t/grades.gif [deleted file]
pix/t/groupn.gif [deleted file]
pix/t/groups.gif [deleted file]
pix/t/groupv.gif [deleted file]
pix/t/hide.gif [deleted file]
pix/t/left.gif [deleted file]
pix/t/lock.gif [deleted file]
pix/t/locktime.gif [deleted file]
pix/t/manual_item.gif [deleted file]
pix/t/manual_item.png [deleted file]
pix/t/manual_item.svg [deleted file]
pix/t/message.gif [deleted file]
pix/t/move.gif [deleted file]
pix/t/portfolioadd.gif [deleted file]
pix/t/preview.gif [deleted file]
pix/t/restore.gif [deleted file]
pix/t/right.gif [deleted file]
pix/t/show.gif [deleted file]
pix/t/stop.gif [deleted file]
pix/t/switch_minus.gif [deleted file]
pix/t/switch_plus.gif [deleted file]
pix/t/switch_whole.gif [deleted file]
pix/t/unlock.gif [deleted file]
pix/t/unlock_gray.gif [deleted file]
pix/t/unlock_gray.png [deleted file]
pix/t/unlock_gray.svg [deleted file]
pix/t/up.gif [deleted file]
pix/t/user.gif [deleted file]
pix/t/userblue.gif [deleted file]
pix/t/userblue.png [deleted file]
pix/t/userblue.svg [deleted file]
portfolio/add.php
question/category_class.php
question/engine/tests/helpers.php
question/type/calculatedmulti/question.php
question/type/calculatedsimple/tests/helper.php
question/type/calculatedsimple/tests/questiontype_test.php [new file with mode: 0644]
question/type/description/tests/helper.php
question/type/description/tests/questiontype_test.php
question/type/match/tests/helper.php [new file with mode: 0644]
question/type/match/tests/questiontype_test.php
question/type/multianswer/tests/helper.php
question/type/multianswer/tests/questiontype_test.php
question/type/multichoice/tests/helper.php [new file with mode: 0644]
question/type/multichoice/tests/questiontype_test.php
question/type/numerical/tests/helper.php
question/type/numerical/tests/questiontype_test.php
question/type/questionbase.php
question/type/questiontypebase.php
question/type/shortanswer/tests/helper.php
question/type/shortanswer/tests/questiontype_test.php
question/type/truefalse/tests/helper.php
question/type/truefalse/tests/questiontype_test.php
report/backups/index.php
report/log/locallib.php
report/security/locallib.php
repository/draftfiles_ajax.php
repository/filepicker.php
repository/filesystem/lib.php
repository/flickr_public/lib.php
repository/lib.php
repository/repository_ajax.php
repository/tests/repository_test.php
tag/coursetags_more.php
tag/coursetagslib.php
theme/afterburner/pix_core/i/courseevent.png [moved from theme/afterburner/pix_core/c/course.png with 100% similarity]
theme/afterburner/pix_core/i/siteevent.png [moved from theme/afterburner/pix_core/c/site.png with 100% similarity]
theme/afterburner/pix_core/i/userevent.png [moved from theme/afterburner/pix_core/c/user.png with 100% similarity]
theme/afterburner/pix_core/t/add.png [moved from theme/afterburner/pix_core/t/addgreen.png with 100% similarity]
theme/afterburner/pix_core/t/check.png [moved from theme/afterburner/pix_core/t/clear.png with 100% similarity]
theme/afterburner/pix_core/t/userblue.png [deleted file]
theme/base/style/admin.css
theme/bootstrapbase/less/moodle/grade.less
theme/bootstrapbase/style/moodle.css
theme/formfactor/config.php
theme/mymobile/pix_core/i/courseevent.png [moved from theme/mymobile/pix_core/c/course.png with 100% similarity]
theme/mymobile/pix_core/i/cross_red_big.png [deleted file]
theme/mymobile/pix_core/i/cross_red_small.png [deleted file]
theme/mymobile/pix_core/i/groupevent.png [moved from theme/mymobile/pix_core/c/group.png with 100% similarity]
theme/mymobile/pix_core/i/siteevent.png [moved from theme/mymobile/pix_core/c/site.png with 100% similarity]
theme/mymobile/pix_core/i/userevent.png [moved from theme/mymobile/pix_core/c/user.png with 100% similarity]
theme/mymobile/pix_core/t/approve.png [moved from theme/mymobile/pix_core/i/approve.png with 100% similarity]
theme/mymobile/pix_core/t/check.png [moved from theme/mymobile/pix_core/t/clear.png with 100% similarity]
user/edit.php
user/editlib.php
user/externallib.php
user/index.php
user/messageselect.php
user/selector/lib.php
user/tests/externallib_test.php
version.php
webservice/amf/server.php
webservice/amf/simpleserver.php
webservice/soap/server.php
webservice/soap/simpleserver.php
webservice/xmlrpc/server.php
webservice/xmlrpc/simpleserver.php

index d02d1e3..f0bee31 100644 (file)
@@ -36,6 +36,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     exit(1);
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 $help =
 "Command line Moodle installer, creates config.php and initializes database.
 Please note you must execute this script with the same uid as apache
index dfc7a42..7a4f288 100644 (file)
@@ -36,6 +36,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     exit(1);
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 $help =
 "Advanced command line Moodle database installer.
 Please note you must execute this script with the same uid as apache.
index ca6ef6a..98e8726 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+// Force OPcache reset if used, we do not want any stale caches
+// when detecting if upgrade necessary or when running upgrade.
+if (function_exists('opcache_reset') and !isset($_SERVER['REMOTE_ADDR'])) {
+    opcache_reset();
+}
+
 define('CLI_SCRIPT', true);
 define('CACHE_DISABLE_ALL', true);
 
index bfd76c1..b29392d 100644 (file)
@@ -42,7 +42,7 @@ while(!feof($fd)) {
     list($ctxselect, $ctxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
     $sql = "SELECT c.id, c.fullname $ctxselect FROM {course} c $ctxjoin WHERE c.id = :courseid";
     $course = $DB->get_record_sql($sql, array('courseid' => $log->course));
-    context_instance_preload($course);
+    context_helper::preload_from_record($course);
 
     $user = $DB->get_record("user", array("id"=>$log->userid));
     $subject = get_string('virusfoundsubject','moodle',format_string($site->fullname));
index c54e838..9acf551 100644 (file)
@@ -52,6 +52,12 @@ if (empty($_GET['cache']) and empty($_POST['cache'])) {
     // we redirect to self once we known no upgrades are necessary.
     // Note: $_GET and $_POST are used here intentionally because our param cleaning is not loaded yet.
     define('CACHE_DISABLE_ALL', true);
+
+    // Force OPcache reset if used, we do not want any stale caches
+    // when detecting if upgrade necessary or when running upgrade.
+    if (function_exists('opcache_reset')) {
+        opcache_reset();
+    }
 }
 
 require('../config.php');
index 782f850..12672b2 100644 (file)
@@ -60,7 +60,7 @@ collatorlib::asort($plugins);
 foreach ($plugins as $plugin => $name) {
     $uninstall = '';
     if ($uninstallurl = plugin_manager::instance()->get_uninstall_url('local_'.$plugin)) {
-        $uninstall = html_writer::link($uninstall, get_string('uninstallplugin', 'core_admin'));
+        $uninstall = html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
     }
 
     $version = get_config('local_' . $plugin);
index a27aff9..faf55f5 100644 (file)
@@ -48,7 +48,7 @@ function online_assignment_cleanup($output=false) {
 
     /// cycle through each course
     foreach ($courses as $course) {
-        context_instance_preload($course);
+        context_helper::preload_from_record($course);
         $context = context_course::instance($course->id);
 
         if (empty($course->fullname)) {
index 280c0ae..8ceba12 100644 (file)
@@ -85,10 +85,18 @@ if ($uninstall) {
         if ($pluginman->is_plugin_folder_removable($pluginfo->component)) {
             $continueurl = new moodle_url($PAGE->url, array('delete' => $pluginfo->component, 'sesskey' => sesskey(), 'confirm' => 1));
             echo $output->plugin_uninstall_results_removable_page($pluginman, $pluginfo, $progress, $continueurl);
+            // Reset op code caches.
+            if (function_exists('opcache_reset')) {
+                opcache_reset();
+            }
             exit();
 
         } else {
             echo $output->plugin_uninstall_results_page($pluginman, $pluginfo, $progress);
+            // Reset op code caches.
+            if (function_exists('opcache_reset')) {
+                opcache_reset();
+            }
             exit();
         }
     }
@@ -131,6 +139,10 @@ if ($delete and $confirmed) {
 
     // So long, and thanks for all the bugs.
     fulldelete($pluginfo->rootdir);
+    // Reset op code caches.
+    if (function_exists('opcache_reset')) {
+        opcache_reset();
+    }
     redirect($PAGE->url);
 }
 
index de9eaae..20f9370 100644 (file)
@@ -41,7 +41,7 @@ class core_role_check_capability_table extends core_role_capability_table_base {
      * Constructor
      * @param object $context the context this table relates to.
      * @param object $user the user we are generating the results for.
-     * @param string $contextname print_context_name($context) - to save recomputing.
+     * @param string $contextname $context->get_context_name() - to save recomputing.
      */
     public function __construct($context, $user, $contextname) {
         parent::__construct($context, 'explaincaps');
index 4d317f5..aa9a2f4 100644 (file)
@@ -38,7 +38,7 @@ class core_role_permissions_table extends core_role_capability_table_base {
     /**
      * Constructor.
      * @param context $context the context this table relates to.
-     * @param string $contextname print_context_name($context) - to save recomputing.
+     * @param string $contextname $context->get_context_name() - to save recomputing.
      * @param array $allowoverrides
      * @param array $allowsafeoverrides
      * @param array $overridableroles
index 0935f6f..c62c979 100644 (file)
@@ -99,9 +99,9 @@ foreach ($contexts as $conid => $con) {
 // Put the contexts into a tree structure.
 foreach ($contexts as $conid => $con) {
     $context = context::instance_by_id($conid);
-    $parentcontextid = get_parent_contextid($context);
-    if ($parentcontextid) {
-        $contexts[$parentcontextid]->children[] = $conid;
+    $parentcontext = $context->get_parent_context();
+    if ($parentcontext) {
+        $contexts[$parentcontext->id]->children[] = $conid;
     }
 }
 
index e720160..3d63ce6 100644 (file)
@@ -46,11 +46,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
                        1800 => new lang_string('numminutes', '', 30),
                        2700 => new lang_string('numminutes', '', 45),
                        3600 => new lang_string('numminutes', '', 60))));
-    $temp->add(new admin_setting_configselect('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'),
-                  'language', array('language' => new lang_string('language'),
-                                              'firstname lastname' => new lang_string('firstname').' + '.new lang_string('lastname'),
-                                              'lastname firstname' => new lang_string('lastname').' + '.new lang_string('firstname'),
-                                              'firstname' => new lang_string('firstname'))));
+
     $temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
     $temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW));
     $temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
index 0365ab5..5a50bce 100644 (file)
@@ -150,6 +150,7 @@ if ($hassiteconfig
                     'department'  => new lang_string('department'),
                     'institution' => new lang_string('institution'),
                 )));
+        $temp->add(new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'), new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50));
         $temp->add(new admin_setting_configtext('maxusersperpage', new lang_string('maxusersperpage','admin'), new lang_string('configmaxusersperpage','admin'), 100, PARAM_INT));
         $temp->add(new admin_setting_configcheckbox('enablegravatar', new lang_string('enablegravatar', 'admin'), new lang_string('enablegravatar_help', 'admin'), 0));
         $temp->add(new admin_setting_configtext('gravatardefaulturl', new lang_string('gravatardefaulturl', 'admin'), new lang_string('gravatardefaulturl_help', 'admin'), 'mm'));
index fd11b08..9ac6931 100644 (file)
@@ -26,6 +26,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     die(); // No access from web!
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 // Is not really necessary but adding it as is a CLI_SCRIPT.
 define('CLI_SCRIPT', true);
 
diff --git a/admin/tool/capability/classes/settings_form.php b/admin/tool/capability/classes/settings_form.php
new file mode 100644 (file)
index 0000000..cf5fa3e
--- /dev/null
@@ -0,0 +1,66 @@
+<?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/>.
+
+/**
+ * Capability tool settings form.
+ *
+ * Do no include this file, it is automatically loaded by the class loader!
+ *
+ * @package    tool_capability
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Class tool_capability_settings_form
+ *
+ * The settings form for the comparison of roles/capabilities.
+ *
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_capability_settings_form extends moodleform {
+
+    /**
+     * The form definition.
+     */
+    public function definition() {
+        $form = $this->_form;
+        $capabilities = $this->_customdata['capabilities'];
+        $roles = $this->_customdata['roles'];
+        // Set the form ID.
+        $form->setAttributes(array('id' => 'capability-overview-form') + $form->getAttributes());
+
+        $form->addElement('header', 'reportsettings', get_string('reportsettings', 'tool_capability'));
+        $form->addElement('html', html_writer::tag('p', get_string('intro', 'tool_capability'), array('id' => 'intro')));
+
+        $form->addElement('hidden', 'search');
+        $form->setType('search', PARAM_TEXT);
+
+        $attributes = array('multiple' => 'multiple', 'size' => 10, 'data-search' => 'capability');
+        $form->addElement('select', 'capability', get_string('capabilitylabel', 'tool_capability'), $capabilities, $attributes);
+        $form->setType('capability', PARAM_CAPABILITY);
+
+        $attributes = array('multiple' => 'multiple', 'size' => 10);
+        $form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes);
+        $form->setType('roles', PARAM_TEXT);
+
+        $form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability'));
+    }
+
+}
\ No newline at end of file
index 3f9c58e..d1707d2 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * For a given capability, show what permission it has for every role, and
- * everywhere that it is overridden.
+ * For a given capability, show what permission it has for every role, and everywhere that it is overridden.
  *
- * @package    tool
- * @subpackage capability
+ * @package    tool_capability
  * @copyright  2008 Tim Hunt
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once(dirname(__FILE__) . '/../../../config.php');
+require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/capability/locallib.php');
 require_once($CFG->libdir.'/adminlib.php');
 
-// Check permissions.
-require_login();
-$systemcontext = context_system::instance();
-require_capability('moodle/role:manage', $systemcontext);
-
 // Get URL parameters.
-$capability = optional_param('capability', '', PARAM_CAPABILITY);
-$roleids = optional_param_array('roles', array('0'), PARAM_INT);
-
-// Clean the passed in list of role ids. If 'All' selected as an option, or
-// if none were selected, do all roles.
-$allroles = role_fix_names(get_all_roles());
-$cleanedroleids = array();
-foreach ($roleids as $roleid) {
-    if ($roleid == 0) {
-        $cleanedroleids = array_keys($allroles);
-        break;
-    }
-    if (array_key_exists($roleid, $allroles)) {
-        $cleanedroleids[] = $roleid;
-    }
-}
-if (empty($cleanedroleids)) {
-    $cleanedroleids = array_keys($allroles);
-}
-
-// Include the required JavaScript.
-$PAGE->requires->js_init_call('M.tool_capability.init', array(get_string('search')));
+$systemcontext = context_system::instance();
+$contextid = optional_param('context', $systemcontext->id, PARAM_INT);
 
-// Log.
-add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php?capability=$capability", $capability);
+// Check permissions.
+list($context, $course, $cm) = get_context_info_array($contextid);
+require_login($course, false, $cm);
+require_capability('moodle/role:manage', $context);
 
 // Print the header.
 admin_externalpage_setup('toolcapability');
-echo $OUTPUT->header();
 
-// Prepare the list of capabilities to choose from
-$allcapabilities = fetch_context_capabilities($systemcontext);
+// Prepare the list of capabilities to choose from.
 $capabilitychoices = array();
-foreach ($allcapabilities as $cap) {
+foreach ($context->get_capabilities() as $cap) {
     $capabilitychoices[$cap->name] = $cap->name . ': ' . get_capability_string($cap->name);
 }
 
-// Prepare the list of roles to choose from
+$allroles = role_fix_names(get_all_roles($context));
+// Prepare the list of roles to choose from.
 $rolechoices = array('0' => get_string('all'));
 foreach ($allroles as $role) {
     $rolechoices[$role->id] = $role->localname;
 }
-if (count($cleanedroleids) == count($allroles)) {
-    // Select 'All', rather than each role individually.
-    $selectedroleids = array('0');
-} else {
-    $selectedroleids = $cleanedroleids;
-}
 
-// Print the settings form.
-echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
-echo '<form method="get" action="" id="settingsform"><div>';
-echo $OUTPUT->heading(get_string('reportsettings', 'tool_capability'));
-echo '<p id="intro">', get_string('intro', 'tool_capability') , '</p>';
-echo '<p><label for="menucapability"> ' . get_string('capabilitylabel', 'tool_capability') . '</label></p>';
-echo  html_writer::select($capabilitychoices, 'capability', $capability, array(''=>'choose'), array('size'=>10));
-echo '<p><label for="menuroles"> ' . get_string('roleslabel', 'tool_capability') . '</label></p>';
-echo  html_writer::select($rolechoices, 'roles[]', $selectedroleids, false, array('size'=>10, 'multiple'=>'multiple'));
-echo '<p><input type="submit" id="settingssubmit" value="' . get_string('getreport', 'tool_capability') . '" /></p>';
-echo '</div></form>';
-echo $OUTPUT->box_end();
+$form = new tool_capability_settings_form(null, array(
+    'capabilities' => $capabilitychoices,
+    'roles' => $rolechoices
+));
+$PAGE->requires->yui_module(
+    'moodle-tool_capability-search',
+    'M.tool_capability.init_capability_search',
+    array(array('strsearch' => get_string('search')))
+);
 
-// If we have a capability, generate the report.
-if ($capability) {
-
-    // Work out the bits needed for the SQL WHERE clauses.
-    $params = array($capability);
-    $sqlroletest = '';
-    if (count($cleanedroleids) != count($allroles)) {
-        list($sqlroletest, $roleparams) = $DB->get_in_or_equal($cleanedroleids);
-        $params = array_merge($params, $roleparams);
-        $sqlroletest = 'AND roleid ' . $sqlroletest;
-    }
+// Log.
+$capabilities = array();
+$rolestoshow = array();
+$roleids = array('0');
+$cleanedroleids = array();
+if ($data = $form->get_data()) {
 
-    // Get all the role_capabilities rows for this capability - that is, all
-    // role definitions, and all role overrides.
-    $rolecaps = $DB->get_records_sql("
-            SELECT id, roleid, contextid, permission
-            FROM {role_capabilities}
-            WHERE capability = ? $sqlroletest", $params);
-
-    // In order to display a nice tree of contexts, we need to get all the
-    // ancestors of all the contexts in the query we just did.
-    $relevantpaths = $DB->get_records_sql_menu("
-            SELECT DISTINCT con.path, 1
-            FROM {context} con JOIN {role_capabilities} rc ON rc.contextid = con.id
-            WHERE capability = ? $sqlroletest", $params);
-    $requiredcontexts = array($systemcontext->id);
-    foreach ($relevantpaths as $path => $notused) {
-        $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/')));
+    $roleids = array();
+    if (!empty($data->roles)) {
+        $roleids = $data->roles;
     }
-    $requiredcontexts = array_unique($requiredcontexts);
-
-    // Now load those contexts.
-    list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts);
-    $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams);
 
-    // Prepare some empty arrays to hold the data we are about to compute.
-    foreach ($contexts as $conid => $con) {
-        $contexts[$conid]->children = array();
-        $contexts[$conid]->rolecapabilities = array();
+    $capabilities = array();
+    if (!empty($data->capability)) {
+        $capabilities = $data->capability;
     }
 
-    // Put the contexts into a tree structure.
-    foreach ($contexts as $conid => $con) {
-        $context = context::instance_by_id($conid);
-        $parentcontextid = get_parent_contextid($context);
-        if ($parentcontextid) {
-            $contexts[$parentcontextid]->children[] = $conid;
+    if (in_array('0', $roleids)) {
+        $rolestoshow = $allroles;
+    } else {
+        $cleanedroleids = array_intersect(array_keys($allroles), $roleids);
+        if (count($cleanedroleids) === 0) {
+            $rolestoshow = $allroles;
+        } else {
+            foreach ($cleanedroleids as $id) {
+                $rolestoshow[$id] = $allroles[$id];
+            }
         }
     }
+}
 
-    // Put the role capabilities into the context tree.
-    foreach ($rolecaps as $rolecap) {
-        $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
-    }
+add_to_log(SITEID, "admin", "tool capability", "tool/capability/index.php", count($capabilities));
 
-    // Fill in any missing rolecaps for the system context.
-    foreach ($cleanedroleids as $roleid) {
-        if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) {
-            $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT;
-        }
-    }
+$renderer = $PAGE->get_renderer('tool_capability');
 
-    // Print the report heading.
-    echo $OUTPUT->heading(get_string('reportforcapability', 'tool_capability', get_capability_string($capability)), 2, 'main', 'report');
-    if (count($cleanedroleids) != count($allroles)) {
-        $rolenames = array();
-        foreach ($cleanedroleids as $roleid) {
-            $rolenames[] = $allroles[$roleid]->localname;
-        }
-        echo '<p>', get_string('forroles', 'tool_capability', implode(', ', $rolenames)), '</p>';
-    }
+echo $OUTPUT->header();
+
+$form->display();
 
-    // Now, recursively print the contexts, and the role information.
-    print_report_tree($systemcontext->id, $contexts, $allroles);
+// If we have a capability, generate the report.
+if (count($capabilities) && count($rolestoshow)) {
+    /* @var tool_capability_renderer $renderer */
+    echo $renderer->capability_comparison_table($capabilities, $context->id, $rolestoshow);
 }
 
 // Footer.
@@ -190,7 +125,7 @@ function print_report_tree($contextid, $contexts, $allroles) {
 
     // Start the list item, and print the context name as a link to the place to
     // make changes.
-    if ($contextid == get_system_context()->id) {
+    if ($contextid == context_system::instance()->id) {
         $url = "$CFG->wwwroot/$CFG->admin/roles/manage.php";
         $title = get_string('changeroles', 'tool_capability');
     } else {
index bae923f..3862006 100644 (file)
@@ -17,8 +17,7 @@
 /**
  * Strings for component 'tool_capability', language 'en', branch 'MOODLE_22_STABLE'
  *
- * @package    tool
- * @subpackage capability
+ * @package    tool_capability
  * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
diff --git a/admin/tool/capability/locallib.php b/admin/tool/capability/locallib.php
new file mode 100644 (file)
index 0000000..08cd8b3
--- /dev/null
@@ -0,0 +1,96 @@
+<?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/>.
+
+/**
+ * Functions used by the capability tool.
+ *
+ * @package    tool_capability
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Calculates capability data organised by context for the given roles.
+ *
+ * @param string $capability The capability to get data for.
+ * @param array $roles An array of roles to get data for.
+ * @return context[] An array of contexts.
+ */
+function tool_capability_calculate_role_data($capability, array $roles) {
+    global $DB;
+
+    $systemcontext = context_system::instance();
+    $roleids = array_keys($roles);
+
+    // Work out the bits needed for the SQL WHERE clauses.
+    $params = array($capability);
+    list($sqlroletest, $roleparams) = $DB->get_in_or_equal($roleids);
+    $params = array_merge($params, $roleparams);
+    $sqlroletest = 'AND roleid ' . $sqlroletest;
+
+    // Get all the role_capabilities rows for this capability - that is, all
+    // role definitions, and all role overrides.
+    $sql = 'SELECT id, roleid, contextid, permission
+              FROM {role_capabilities}
+             WHERE capability = ? '.$sqlroletest;
+    $rolecaps = $DB->get_records_sql($sql, $params);
+
+    // In order to display a nice tree of contexts, we need to get all the
+    // ancestors of all the contexts in the query we just did.
+    $sql = 'SELECT DISTINCT con.path, 1
+              FROM {context} con
+              JOIN {role_capabilities} rc ON rc.contextid = con.id
+             WHERE capability = ? '.$sqlroletest;
+    $relevantpaths = $DB->get_records_sql_menu($sql, $params);
+    $requiredcontexts = array($systemcontext->id);
+    foreach ($relevantpaths as $path => $notused) {
+        $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/')));
+    }
+    $requiredcontexts = array_unique($requiredcontexts);
+
+    // Now load those contexts.
+    list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts);
+    $contexts = get_sorted_contexts('ctx.id ' . $sqlcontexttest, $contextparams);
+
+    // Prepare some empty arrays to hold the data we are about to compute.
+    foreach ($contexts as $conid => $con) {
+        $contexts[$conid]->children = array();
+        $contexts[$conid]->rolecapabilities = array();
+    }
+
+    // Put the contexts into a tree structure.
+    foreach ($contexts as $conid => $con) {
+        $context = context::instance_by_id($conid);
+        $parentcontext = $context->get_parent_context();
+        if ($parentcontext) {
+            $contexts[$parentcontext->id]->children[] = $conid;
+        }
+    }
+
+    // Put the role capabilities into the context tree.
+    foreach ($rolecaps as $rolecap) {
+        $contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
+    }
+
+    // Fill in any missing rolecaps for the system context.
+    foreach ($roleids as $roleid) {
+        if (!isset($contexts[$systemcontext->id]->rolecapabilities[$roleid])) {
+            $contexts[$systemcontext->id]->rolecapabilities[$roleid] = CAP_INHERIT;
+        }
+    }
+
+    return $contexts;
+}
\ No newline at end of file
diff --git a/admin/tool/capability/module.js b/admin/tool/capability/module.js
deleted file mode 100644 (file)
index 254f194..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-
-M.tool_capability = {
-    select: null,
-    input: null,
-    button: null,
-
-    init: function(Y, strsearch) {
-        var context = M.tool_capability;
-
-        // Find the form controls.
-        context.select = document.getElementById('menucapability');
-        context.button = document.getElementById('settingssubmit');
-
-        // Create a div to hold the search UI.
-        var div = document.createElement('div');
-        div.id = 'capabilitysearchui';
-
-        // Find the capability search input.
-        var input = document.createElement('input');
-        input.type = 'text';
-        input.id = 'capabilitysearch';
-        context.input = input;
-
-        // Create a label for the search input.
-        var label = document.createElement('label');
-        label.htmlFor = input.id;
-        label.appendChild(document.createTextNode(strsearch + ' '));
-
-        // Tie it all together
-        div.appendChild(label);
-        div.appendChild(input);
-        context.select.parentNode.insertBefore(div, context.select);
-        Y.on('keyup', context.typed, input);
-        Y.on('change', context.validate, context.select);
-        context.select.options[0].style.display = 'none';
-        context.validate();
-    },
-
-    typed: function() {
-        var context = M.tool_capability;
-
-        var filtertext = context.input.value;
-        var options = context.select.options;
-        var onlycapability = -1;
-        for (var i = 1; i < options.length; i++) {
-            if (options[i].text.indexOf(filtertext) >= 0) {
-                options[i].disabled = false;
-                options[i].style.display = 'block';
-                if (onlycapability == -1) {
-                    onlycapability = i;
-                } else {
-                    onlycapability = -2;
-                }
-            } else {
-                options[i].disabled = true;
-                options[i].selected = false;
-                options[i].style.display = 'none';
-            }
-        }
-        if (onlycapability >= 0) {
-            options[onlycapability].selected = true;
-        }
-        if (onlycapability == -1) {
-            context.input.className = "error";
-        } else {
-            context.input.className = "";
-        }
-        context.validate();
-    },
-
-    validate: function() {
-        var context = M.tool_capability;
-        context.button.disabled = (context.select.value == '');
-    }
-}
\ No newline at end of file
diff --git a/admin/tool/capability/renderer.php b/admin/tool/capability/renderer.php
new file mode 100644 (file)
index 0000000..586725a
--- /dev/null
@@ -0,0 +1,136 @@
+<?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/>.
+
+/**
+ * Capability tool renderer.
+ *
+ * @package    tool_capability
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * The primary renderer for the capability tool.
+ *
+ * @copyright  2013 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_capability_renderer extends plugin_renderer_base {
+
+    /**
+     * Returns an array of permission strings.
+     *
+     * @return lang_string[]
+     */
+    protected function get_permission_strings() {
+        static $strpermissions;
+        if (!$strpermissions) {
+            $strpermissions = array(
+                CAP_INHERIT => new lang_string('inherit', 'role'),
+                CAP_ALLOW => new lang_string('allow', 'role'),
+                CAP_PREVENT => new lang_string('prevent', 'role'),
+                CAP_PROHIBIT => new lang_string('prohibit', 'role')
+            );
+        }
+        return $strpermissions;
+    }
+
+    /**
+     * Returns an array of permission CSS classes.
+     *
+     * @return string[]
+     */
+    protected function get_permission_classes() {
+        static $permissionclasses;
+        if (!$permissionclasses) {
+            $permissionclasses = array(
+                CAP_INHERIT => 'inherit',
+                CAP_ALLOW => 'allow',
+                CAP_PREVENT => 'prevent',
+                CAP_PROHIBIT => 'prohibit',
+            );
+        }
+        return $permissionclasses;
+    }
+
+    /**
+     * Produces a table to visually compare roles and capabilities.
+     *
+     * @param array $capabilities An array of capabilities to show comparison for.
+     * @param int $contextid The context we are displaying for.
+     * @param array $roles An array of roles to show comparison for.
+     * @return string
+     */
+    public function capability_comparison_table(array $capabilities, $contextid, array $roles) {
+
+        $strpermissions = $this->get_permission_strings();
+        $permissionclasses = $this->get_permission_classes();
+
+        if ($contextid === context_system::instance()->id) {
+            $strpermissions[CAP_INHERIT] = new lang_string('notset', 'role');
+        }
+
+        $table = new html_table();
+        $table->attributes['class'] = 'comparisontable';
+        $table->head = array('&nbsp;');
+        foreach ($roles as $role) {
+            $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid, 'roleid' => $role->id));
+            $table->head[] = html_writer::div(html_writer::link($url, $role->localname));
+        }
+        $table->data = array();
+
+        foreach ($capabilities as $capability) {
+            $contexts = tool_capability_calculate_role_data($capability, $roles);
+            $captitle = new html_table_cell(get_capability_string($capability) . html_writer::span($capability));
+            $captitle->header = true;
+
+            $row = new html_table_row(array($captitle));
+
+            foreach ($roles as $role) {
+                if (isset($contexts[$contextid]->rolecapabilities[$role->id])) {
+                    $permission = $contexts[$contextid]->rolecapabilities[$role->id];
+                } else {
+                    $permission = CAP_INHERIT;
+                }
+                $cell = new html_table_cell($strpermissions[$permission]);
+                $cell->attributes['class'] = $permissionclasses[$permission];
+                $row->cells[] = $cell;
+            }
+
+            $table->data[] = $row;
+        }
+
+        // Start the list item, and print the context name as a link to the place to make changes.
+        if ($contextid == context_system::instance()->id) {
+            $url = new moodle_url('/admin/roles/manage.php');
+            $title = get_string('changeroles', 'tool_capability');
+        } else {
+            $url = new moodle_url('/admin/roles/override.php', array('contextid' => $contextid));
+            $title = get_string('changeoverrides', 'tool_capability');
+        }
+        $context = context::instance_by_id($contextid);
+        $html = $this->output->heading(html_writer::link($url, $context->get_context_name(), array('title' => $title)), 3);
+        $html .= html_writer::table($table);
+        // If there are any child contexts, print them recursively.
+        if (!empty($contexts[$contextid]->children)) {
+            foreach ($contexts[$contextid]->children as $childcontextid) {
+                $html .= $this->capability_comparison_table($capabilities, $childcontextid, $roles, true);
+            }
+        }
+        return $html;
+    }
+
+}
\ No newline at end of file
index bf4d6ad..ba8d551 100644 (file)
 /**
  * Capability overview settings
  *
- * @package    tool
- * @subpackage capability
+ * @package    tool_capability
  * @copyright  2008 Tim Hunt
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die;
 
-$ADMIN->add('roles', new admin_externalpage('toolcapability', get_string('pluginname', 'tool_capability'), "$CFG->wwwroot/$CFG->admin/tool/capability/index.php",'moodle/role:manage'));
+$ADMIN->add('roles', new admin_externalpage(
+    'toolcapability',
+    get_string('pluginname', 'tool_capability'),
+    "$CFG->wwwroot/$CFG->admin/tool/capability/index.php",
+    'moodle/role:manage'
+));
diff --git a/admin/tool/capability/styles.css b/admin/tool/capability/styles.css
new file mode 100644 (file)
index 0000000..757066e
--- /dev/null
@@ -0,0 +1,32 @@
+.path-admin-tool-capability .comparisontable {margin-top:150px;}
+.path-admin-tool-capability .comparisontable th,
+.path-admin-tool-capability .comparisontable td {vertical-align:middle;padding:0.4em 0.5em 0.3em;}
+.path-admin-tool-capability .comparisontable thead th {vertical-align:bottom;background:none;}
+.path-admin-tool-capability .comparisontable thead th div {position:relative;}
+.path-admin-tool-capability .comparisontable thead th div > a {
+    position:absolute;
+    top:-1.75em;
+    left:1em;
+    width:150px;
+    text-align:left;
+    margin-bottom:1em;
+    text-indent:-1.45em;
+
+    -webkit-transform-origin: top left;
+    -moz-transform-origin:    top left;
+    -ms-transform-origin:     top left;
+    -o-transform-origin:      top left;
+
+    -webkit-transform: rotate(315deg);
+    -moz-transform:    rotate(315deg);
+    -ms-transform:     rotate(315deg);
+    -o-transform:      rotate(315deg);
+}
+.path-admin-tool-capability .comparisontable tbody th {background-color:#EEE;text-align:right;border:1px solid #DFDFDF;}
+.path-admin-tool-capability .comparisontable tbody th span {display:block;color:#666;font-size:80%;}
+.path-admin-tool-capability .comparisontable tbody td {border:1px solid #DFDFDF;}
+
+.path-admin-tool-capability .comparisontable .inherit {color:#666;}
+.path-admin-tool-capability .comparisontable .allow {color:#006600;font-weight:bold;}
+.path-admin-tool-capability .comparisontable .prevent {color:#ad6704;font-weight:bold;}
+.path-admin-tool-capability .comparisontable .prohibit {color:#880000;font-weight:bold;}
\ No newline at end of file
index e14328a..4ada1ea 100644 (file)
 /**
  * Version details.
  *
- * @package    tool
- * @subpackage capability
+ * @package    tool_capability
  * @copyright  2011 Petr Skoda
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013050100; // The current plugin version (Date: YYYYMMDDXX)
-$plugin->requires  = 2013050100; // Requires this Moodle version
-$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics)
+$plugin->version   = 2013050100; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->requires  = 2013050100; // Requires this Moodle version.
+$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js
new file mode 100644 (file)
index 0000000..f0661d5
Binary files /dev/null and b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js differ
diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js
new file mode 100644 (file)
index 0000000..0153975
Binary files /dev/null and b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-min.js differ
diff --git a/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js
new file mode 100644 (file)
index 0000000..f0661d5
Binary files /dev/null and b/admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search.js differ
diff --git a/admin/tool/capability/yui/src/search/build.json b/admin/tool/capability/yui/src/search/build.json
new file mode 100644 (file)
index 0000000..2157889
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "name": "moodle-tool_capability-search",
+    "builds": {
+        "moodle-tool_capability-search": {
+            "jsfiles": [
+                "search.js"
+            ]
+        }
+    }
+}
diff --git a/admin/tool/capability/yui/src/search/js/search.js b/admin/tool/capability/yui/src/search/js/search.js
new file mode 100644 (file)
index 0000000..5e9dc34
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * This file contains the capability overview search functionality.
+ *
+ * @module moodle-tool_capability-search
+ */
+
+/**
+ * Constructs a new capability search manager.
+ *
+ * @namespace M.tool_capability.search
+ * @class Search
+ * @constructor
+ * @extends Y.Base
+ */
+var SEARCH = function() {
+    SEARCH.superclass.constructor.apply(this, arguments);
+};
+SEARCH.prototype = {
+    /**
+     * The search form.
+     * @property form
+     * @type Node
+     * @protected
+     */
+    form : null,
+    /**
+     * The capability select node.
+     * @property select
+     * @type Node
+     * @protected
+     */
+    select: null,
+    /**
+     * An associative array of search option. Populated from the select node above during initialisation.
+     * @property selectoptions
+     * @type Object
+     * @protected
+     */
+    selectoptions : {},
+    /**
+     * The search input field.
+     * @property input
+     * @type Node
+     * @protected
+     */
+    input: null,
+    /**
+     * The submit button for the form.
+     * @property button
+     * @type Node
+     * @protected
+     */
+    button: null,
+    /**
+     * The last search node if there is one.
+     * If there is a last search node then the last search term will be persisted between requests.
+     * @property lastsearch
+     * @type Node
+     * @protected
+     */
+    lastsearch : null,
+    /**
+     * Constructs the search manager.
+     * @method initializer
+     */
+    initializer : function() {
+        this.form = Y.one('#capability-overview-form');
+        this.select = this.form.one('select[data-search=capability]');
+        this.select.setStyle('minWidth', this.select.get('offsetWidth'));
+        this.select.get('options').each(function(option) {
+            var capability = option.get('value');
+            this.selectoptions[capability] = option;
+        }, this);
+        this.button = this.form.all('input[type=submit]');
+        this.lastsearch = this.form.one('input[name=search]');
+
+        var div = Y.Node.create('<div id="capabilitysearchui"></div>'),
+            label = Y.Node.create('<label for="capabilitysearch">'+this.get('strsearch')+'</label>');
+        this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
+
+        div.append(label).append(this.input);
+
+        this.select.insert(div, 'before');
+        this.select.one('option').setStyle('display', 'none');
+
+        this.input.on('keyup', this.typed, this);
+        this.select.on('change', this.validate, this);
+
+        if (this.lastsearch) {
+            this.input.set('value', this.lastsearch.get('value'));
+            this.typed();
+            if (this.select.one('option[selected]')) {
+                this.select.set('scrollTop', this.select.one('option[selected]').get('getX'));
+            }
+        }
+
+        this.validate();
+    },
+    /**
+     * Disables the submit button if there are no capabilities selected.
+     * @method validate
+     */
+    validate : function() {
+        this.button.set('disabled', (this.select.get('value') === ''));
+    },
+    /**
+     * Called when ever the user types into the search field.
+     * This method hides any capabilities that don't match the search term.
+     * @method typed
+     */
+    typed : function() {
+        var search = this.input.get('value'),
+            matching = 0,
+            last = null,
+            capability;
+        if (this.lastsearch) {
+            this.lastsearch.set('value', search);
+        }
+        this.select.all('option').remove();
+        for (capability in this.selectoptions) {
+            if (capability.indexOf(search) >= 0) {
+                matching++;
+                this.select.append(this.selectoptions[capability]);
+            }
+        }
+        if (matching === 0) {
+            this.input.addClass("error");
+        } else {
+            this.input.removeClass("error");
+            if (matching === 1) {
+                last.set('selected', true);
+            }
+        }
+        this.validate();
+    }
+};
+Y.extend(SEARCH, Y.Base, SEARCH.prototype, {
+    NAME : 'tool_capability-search',
+    ATTRS : {
+        strsearch : {}
+    }
+});
+
+/**
+ * Core namespace.
+ * @static
+ * @class tool_capability
+ */
+M.tool_capability = M.tool_capability || {};
+
+/**
+ * Initialises capability search functionality.
+ * @static
+ * @method init_capability_search
+ * @param {Object} options
+ */
+M.tool_capability.init_capability_search = function(options) {
+    new SEARCH(options);
+};
\ No newline at end of file
diff --git a/admin/tool/capability/yui/src/search/meta/search.json b/admin/tool/capability/yui/src/search/meta/search.json
new file mode 100644 (file)
index 0000000..720e20b
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "moodle-tool_capability-search": {
+        "requires": [
+            "base",
+            "node"
+        ]
+    }
+}
index 57d3859..6aaec2f 100644 (file)
@@ -26,7 +26,7 @@ require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/filter_form.php');
 
 require_login(SITEID, false);
-require_capability('tool/customlang:edit', get_system_context());
+require_capability('tool/customlang:edit', context_system::instance());
 
 $lng                    = required_param('lng', PARAM_LANG);
 $currentpage            = optional_param('p', 0, PARAM_INT);
index 28dae19..aff45ef 100644 (file)
@@ -30,7 +30,7 @@ require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->libdir.'/adminlib.php');
 
 require_login(SITEID, false);
-require_capability('tool/customlang:view', get_system_context());
+require_capability('tool/customlang:view', context_system::instance());
 
 $action  = optional_param('action', '', PARAM_ALPHA);
 $confirm = optional_param('confirm', false, PARAM_BOOL);
@@ -42,7 +42,7 @@ $langs = get_string_manager()->get_list_of_translations();
 // pre-output actions
 if ($action === 'checkout') {
     require_sesskey();
-    require_capability('tool/customlang:edit', get_system_context());
+    require_capability('tool/customlang:edit', context_system::instance());
     if (empty($lng)) {
         print_error('missingparameter');
     }
@@ -66,7 +66,7 @@ if ($action === 'checkout') {
 
 if ($action === 'checkin') {
     require_sesskey();
-    require_capability('tool/customlang:edit', get_system_context());
+    require_capability('tool/customlang:edit', context_system::instance());
     if (empty($lng)) {
         print_error('missingparameter');
     }
@@ -119,7 +119,7 @@ if ($numofmodified != 0) {
 }
 
 $menu = array();
-if (has_capability('tool/customlang:edit', get_system_context())) {
+if (has_capability('tool/customlang:edit', context_system::instance())) {
     $menu['checkout'] = array(
         'title'     => get_string('checkout', 'tool_customlang'),
         'url'       => new moodle_url($PAGE->url, array('action' => 'checkout', 'lng' => $lng)),
index 577fefc..f77c8e0 100644 (file)
@@ -39,7 +39,7 @@ if (!debugging('', DEBUG_DEVELOPER)) {
 }
 
 $PAGE->set_url('/admin/tool/generator/index.php');
-$PAGE->set_context(get_system_context());
+$PAGE->set_context(context_system::instance());
 $PAGE->set_pagelayout('base');
 $generator = new generator_web();
 $generator->setup();
index ad0e4bd..97578b8 100644 (file)
@@ -48,13 +48,13 @@ YUI.add('moodle-tool_installaddon-permcheck', function(Y) {
                         var resultline = Y.one('#tool_installaddon_installfromzip_permcheck');
                         if (resultline) {
                             if (status === 'success') {
-                                resultline.setContent('<span class="success"><img src="' + M.util.image_url('i/tick_green_big') + '" /> ' +
+                                resultline.setContent('<span class="success"><img src="' + M.util.image_url('i/valid') + '" /> ' +
                                     msg + '</span>');
                             } else if (status === 'progress') {
                                 resultline.setContent('<span class="progress"><img src="' + M.cfg.loadingicon + '" /> ' +
                                     msg + '</span>');
                             } else {
-                                resultline.setContent('<span class="error"><img src="' + M.util.image_url('i/cross_red_big') + '" /> ' +
+                                resultline.setContent('<span class="error"><img src="' + M.util.image_url('i/invalid') + '" /> ' +
                                     msg + '</span>');
                             }
                         }
index bf026a4..a3d875d 100644 (file)
@@ -26,6 +26,12 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
     die; // no access from web!
 }
 
+// Force OPcache reset if used, we do not want any stale caches
+// when preparing test environment.
+if (function_exists('opcache_reset')) {
+    opcache_reset();
+}
+
 require_once(__DIR__.'/../../../../lib/clilib.php');
 require_once(__DIR__.'/../../../../lib/phpunit/bootstraplib.php');
 require_once(__DIR__.'/../../../../lib/testing/lib.php');
index c6d2f36..f010f72 100644 (file)
@@ -61,7 +61,7 @@ if ($action === 'delete') {
     //show confirmation
     echo $OUTPUT->header();
     $yesurl = new moodle_url($PAGE->url, array('roleid'=>$roleid, 'contextlevel'=>$contextlevel, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey()));
-    $levelname = get_contextlevel_name($contextlevel);
+    $levelname = context_helper::get_level_name($contextlevel);
     $rolename = format_string($role->name);
     $message = get_string('confirmdelete', 'tool_unsuproles', array('level'=>$levelname, 'role'=>$rolename));
     echo $OUTPUT->confirm($message, $yesurl, $PAGE->url);
@@ -96,7 +96,7 @@ if (!$problems) {
     $roles = get_all_roles();
     $data = array();
     foreach ($problems as $problem) {
-        $levelname = get_contextlevel_name($problem->contextlevel);
+        $levelname = context_helper::get_level_name($problem->contextlevel);
         $rolename = role_get_name($roles[$problem->roleid]);
         //TODO: show list of users if count low
         $count = $problem->racount;
index be72d51..deb6143 100644 (file)
@@ -68,8 +68,10 @@ if (count($cohorts) < 2) {
 }
 
 $countries = get_string_manager()->get_list_of_countries(true);
+$namefields = get_all_user_name_fields(true);
 foreach ($users as $key => $id) {
-    $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, firstname, lastname, username, email, country, lastaccess, city');
+    $user = $DB->get_record('user', array('id'=>$id, 'deleted'=>0), 'id, ' . $namefields . ', username,
+            email, country, lastaccess, city');
     $user->fullname = fullname($user, true);
     $user->country = @$countries[$user->country];
     unset($user->firstname);
index 1e8514a..44259df 100644 (file)
@@ -24,8 +24,9 @@ echo $OUTPUT->header();
 
 $countries = get_string_manager()->get_list_of_countries(true);
 
+$namefields = get_all_user_name_fields(true);
 foreach ($users as $key => $id) {
-    $user = $DB->get_record('user', array('id'=>$id), 'id, firstname, lastname, username, email, country, lastaccess, city');
+    $user = $DB->get_record('user', array('id'=>$id), 'id, ' . $namefields . ', username, email, country, lastaccess, city');
     $user->fullname = fullname($user, true);
     $user->country = @$countries[$user->country];
     unset($user->firstname);
index 314e5be..8686965 100644 (file)
@@ -747,39 +747,57 @@ class auth_plugin_ldap extends auth_plugin_base {
 /// User removal
         // Find users in DB that aren't in ldap -- to be removed!
         // this is still not as scalable (but how often do we mass delete?)
-        if ($this->config->removeuser != AUTH_REMOVEUSER_KEEP) {
-            $sql = 'SELECT u.*
+
+        if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
+            $sql = "SELECT u.*
                       FROM {user} u
-                      LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
-                     WHERE u.auth = ?
+                 LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
+                     WHERE u.auth = :auth
                            AND u.deleted = 0
-                           AND e.username IS NULL';
-            $remove_users = $DB->get_records_sql($sql, array($this->authtype));
+                           AND e.username IS NULL";
+            $remove_users = $DB->get_records_sql($sql, array('auth'=>$this->authtype));
 
             if (!empty($remove_users)) {
                 print_string('userentriestoremove', 'auth_ldap', count($remove_users));
-
                 foreach ($remove_users as $user) {
-                    if ($this->config->removeuser == AUTH_REMOVEUSER_FULLDELETE) {
-                        if (delete_user($user)) {
-                            echo "\t"; print_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
-                        } else {
-                            echo "\t"; print_string('auth_dbdeleteusererror', 'auth_db', $user->username); echo "\n";
-                        }
-                    } else if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
-                        $updateuser = new stdClass();
-                        $updateuser->id = $user->id;
-                        $updateuser->auth = 'nologin';
-                        $DB->update_record('user', $updateuser);
-                        echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
-                        $euser = $DB->get_record('user', array('id' => $user->id));
-                        events_trigger('user_updated', $euser);
+                    if (delete_user($user)) {
+                        echo "\t"; print_string('auth_dbdeleteuser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
+                    } else {
+                        echo "\t"; print_string('auth_dbdeleteusererror', 'auth_db', $user->username); echo "\n";
                     }
                 }
             } else {
                 print_string('nouserentriestoremove', 'auth_ldap');
             }
-            unset($remove_users); // free mem!
+            unset($remove_users); // Free mem!
+
+        } else if ($this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
+            $sql = "SELECT u.*
+                      FROM {user} u
+                 LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
+                     WHERE u.auth = :auth
+                           AND u.deleted = 0
+                           AND u.suspended = 0
+                           AND e.username IS NULL";
+            $remove_users = $DB->get_records_sql($sql, array('auth'=>$this->authtype));
+
+            if (!empty($remove_users)) {
+                print_string('userentriestoremove', 'auth_ldap', count($remove_users));
+
+                foreach ($remove_users as $user) {
+                    $updateuser = new stdClass();
+                    $updateuser->id = $user->id;
+                    $updateuser->suspended = 1;
+                    $DB->update_record('user', $updateuser);
+                    echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
+                    $euser = $DB->get_record('user', array('id' => $user->id));
+                    events_trigger('user_updated', $euser);
+                    session_kill_user($user->id);
+                }
+            } else {
+                print_string('nouserentriestoremove', 'auth_ldap');
+            }
+            unset($remove_users); // Free mem!
         }
 
 /// Revive suspended users
@@ -787,8 +805,9 @@ class auth_plugin_ldap extends auth_plugin_base {
             $sql = "SELECT u.id, u.username
                       FROM {user} u
                       JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
-                     WHERE u.auth = 'nologin' AND u.deleted = 0";
-            $revive_users = $DB->get_records_sql($sql);
+                     WHERE (u.auth = 'nologin' OR (u.auth = ? AND u.suspended = 1)) AND u.deleted = 0";
+            // Note: 'nologin' is there for backwards compatibility.
+            $revive_users = $DB->get_records_sql($sql, array($this->authtype));
 
             if (!empty($revive_users)) {
                 print_string('userentriestorevive', 'auth_ldap', count($revive_users));
@@ -797,6 +816,7 @@ class auth_plugin_ldap extends auth_plugin_base {
                     $updateuser = new stdClass();
                     $updateuser->id = $user->id;
                     $updateuser->auth = $this->authtype;
+                    $updateuser->suspended = 0;
                     $DB->update_record('user', $updateuser);
                     echo "\t"; print_string('auth_dbreviveduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
                     $euser = $DB->get_record('user', array('id' => $user->id));
@@ -914,7 +934,7 @@ class auth_plugin_ldap extends auth_plugin_base {
 
                 $id = $DB->insert_record('user', $user);
                 echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
-                $euser = $DB->get_record('user', array('id' => $user->id));
+                $euser = $DB->get_record('user', array('id' => $id));
                 events_trigger('user_created', $euser);
                 if (!empty($this->config->forcechangepassword)) {
                     set_user_preference('auth_forcepasswordchange', 1, $id);
similarity index 94%
rename from auth/ldap/tests/ldap_test.php
rename to auth/ldap/tests/plugin_test.php
index fdf3384..b468fde 100644 (file)
@@ -34,7 +34,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-class auth_ldap_testcase extends advanced_testcase {
+class auth_ldap_plugin_testcase extends advanced_testcase {
 
     public function test_auth_ldap() {
         global $CFG, $DB;
@@ -169,9 +169,9 @@ class auth_ldap_testcase extends advanced_testcase {
         $auth->sync_users(true);
         ob_end_clean();
 
-        $this->assertEquals(4, $DB->count_records('user', array('auth'=>'ldap')));
-        $this->assertEquals(1, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
-        $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
+        $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
+        $this->assertEquals(0, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
+        $this->assertEquals(1, $DB->count_records('user', array('auth'=>'ldap', 'suspended'=>'1', 'username'=>'username1')));
         $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
         $this->assertEquals(2, $DB->count_records('role_assignments'));
         $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
@@ -188,6 +188,17 @@ class auth_ldap_testcase extends advanced_testcase {
         $this->assertEquals(2, $DB->count_records('role_assignments'));
         $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
 
+        $DB->set_field('user', 'auth', 'nologin', array('username'=>'username1'));
+
+        ob_start();
+        $auth->sync_users(true);
+        ob_end_clean();
+
+        $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
+        $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
+        $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
+        $this->assertEquals(2, $DB->count_records('role_assignments'));
+        $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
 
         set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/ldap');
 
index db7328b..c1861fa 100644 (file)
@@ -146,7 +146,7 @@ class auth_plugin_mnet extends auth_plugin_base {
         }
 
         // check remote login permissions
-        if (! has_capability('moodle/site:mnetlogintoremote', get_system_context())
+        if (! has_capability('moodle/site:mnetlogintoremote', context_system::instance())
                 or is_mnet_remote_user($USER)
                 or isguestuser()
                 or !isloggedin()) {
index c6d47aa..6ce3a34 100644 (file)
@@ -49,10 +49,10 @@ class behat_auth extends behat_base {
     public function i_log_in_as($username) {
 
         return array(new Given('I am on homepage'),
-            new Given('I follow "Login"'),
+            new Given('I follow "Log in"'),
             new Given('I fill in "Username" with "'.$username.'"'),
             new Given('I fill in "Password" with "'.$username.'"'),
-            new Given('I press "Login"')
+            new Given('I press "Log in"')
         );
     }
 
@@ -62,7 +62,7 @@ class behat_auth extends behat_base {
      * @Given /^I log out$/
      */
     public function i_log_out() {
-        return new When('I follow "Logout"');
+        return new When('I follow "Log out"');
     }
 
 }
index 72e4492..f4c4e40 100644 (file)
@@ -4,32 +4,32 @@ Feature: Authentication
   As a user
   I need to log into the system
 
-  Scenario: Login with the predefined admin user
+  Scenario: Log in with the predefined admin user
     Given I log in as "admin"
 
-  Scenario: Login as an existing admin user filling the form
+  Scenario: Log in as an existing admin user filling the form
     Given the following "users" exists:
       | username | password | firstname | lastname | email |
       | testuser | testuser | Test | User | moodle@moodlemoodle.com |
     And I am on homepage
-    When I follow "Login"
+    When I follow "Log in"
     And I fill in "Username" with "testuser"
     And I fill in "Password" with "testuser"
-    And I press "Login"
+    And I press "Log in"
     Then I should see "You are logged in as"
 
-  Scenario: Login as an unexisting user filling the form
+  Scenario: Log in as an unexisting user filling the form
     Given the following "users" exists:
       | username | password | firstname | lastname | email |
       | testuser | testuser | Test | User | moodle@moodlemoodle.com |
     And I am on homepage
-    When I follow "Login"
+    When I follow "Log in"
     And I fill in "Username" with "testuser"
     And I fill in "Password" with "unexisting"
-    And I press "Login"
+    And I press "Log in"
     Then I should see "Invalid login, please try again"
 
-  Scenario: Logout
+  Scenario: Log out
     Given I log in as "admin"
     When I log out
     Then I should see "You are not logged in"
index a926756..952cc26 100644 (file)
@@ -1194,12 +1194,12 @@ class backup_users_structure_step extends backup_structure_step {
 
         // Then, the fields potentially needing anonymization
         $anonfields = array(
-            'username', 'idnumber', 'firstname', 'lastname',
-            'email', 'icq', 'skype',
+            'username', 'idnumber', 'email', 'icq', 'skype',
             'yahoo', 'aim', 'msn', 'phone1',
             'phone2', 'institution', 'department', 'address',
             'city', 'country', 'lastip', 'picture',
             'url', 'description', 'descriptionformat', 'imagealt', 'auth');
+        $anonfields = array_merge($anonfields, get_all_user_name_fields());
 
         // Add anonymized fields to $userfields with custom final element
         foreach ($anonfields as $field) {
index 5146cfe..7feafe8 100644 (file)
@@ -741,7 +741,7 @@ abstract class restore_dbops {
                  // Build the array of contexts we are going to look
                  $systemctx = context_system::instance();
                  $coursectx = context_course::instance($courseid);
-                 $parentctxs= get_parent_contexts($coursectx);
+                 $parentctxs = $coursectx->get_parent_context_ids();
                  foreach ($parentctxs as $parentctx) {
                      // Exclude system context
                      if ($parentctx == $systemctx->id) {
index e1aca51..832717f 100644 (file)
@@ -191,7 +191,7 @@ abstract class restore_search_base implements renderable {
         while ($totalcourses > $offs and $this->totalcount < $this->maxresults) {
             $resultset = $DB->get_records_sql($sql, $params, $offs, $blocksz);
             foreach ($resultset as $result) {
-                context_instance_preload($result);
+                context_helper::preload_from_record($result);
                 $classname = context_helper::get_class_for_level($contextlevel);
                 $context = $classname::instance($result->id);
                 if (count($requiredcaps) > 0) {
index 171bdb3..e6e9d2d 100644 (file)
@@ -527,7 +527,7 @@ class core_badges_renderer extends plugin_renderer_base {
             $description = $badge->description;
             $criteria = self::print_badge_criteria($badge);
             if ($badge->dateissued) {
-                $icon = new pix_icon('i/tick_green_big',
+                $icon = new pix_icon('i/valid',
                             get_string('dateearned', 'badges',
                                 userdate($badge->dateissued, get_string('strftimedatefullshort', 'core_langconfig'))));
                 $badgeurl = new moodle_url('/badges/badge.php', array('hash' => $badge->uniquehash));
index 31eadf6..44e514a 100644 (file)
@@ -91,7 +91,7 @@ class block_edit_form extends moodleform {
         $mform->addElement('hidden', 'bui_parentcontextid', $parentcontext->id);
         $mform->setType('bui_parentcontextid', PARAM_INT);
 
-        $mform->addElement('static', 'bui_homecontext', get_string('createdat', 'block'), print_context_name($parentcontext));
+        $mform->addElement('static', 'bui_homecontext', get_string('createdat', 'block'), $parentcontext->get_context_name());
         $mform->addHelpButton('bui_homecontext', 'createdat', 'block');
 
         // For pre-calculated (fixed) pagetype lists
@@ -142,7 +142,7 @@ class block_edit_form extends moodleform {
             // module context doesn't have child contexts, so display in current context only
             $mform->addElement('hidden', 'bui_contexts', BUI_CONTEXTS_CURRENT);
         } else {
-            $parentcontextname = print_context_name($parentcontext);
+            $parentcontextname = $parentcontext->get_context_name();
             $contextoptions[BUI_CONTEXTS_CURRENT]      = get_string('showoncontextonly', 'block', $parentcontextname);
             $contextoptions[BUI_CONTEXTS_CURRENT_SUBS] = get_string('showoncontextandsubs', 'block', $parentcontextname);
             $mform->addElement('select', 'bui_contexts', get_string('contexts', 'block'), $contextoptions);
index 8124fdc..2e6c018 100644 (file)
@@ -108,6 +108,8 @@ class cache_config_writer extends cache_config {
             fflush($handle);
             fclose($handle);
             $locking->unlock('configwrite', 'config');
+            // Tell PHP to recompile the script.
+            core_component::invalidate_opcode_php_cache($cachefile);
         } else {
             throw new cache_exception('ex_configcannotsave', 'cache', '', null, 'Unable to open the cache config file.');
         }
@@ -901,7 +903,7 @@ abstract class cache_administration_helper extends cache_helper {
      */
     public static function get_store_instance_actions($name, array $storedetails) {
         $actions = array();
-        if (has_capability('moodle/site:config', get_system_context())) {
+        if (has_capability('moodle/site:config', context_system::instance())) {
             $baseurl = new moodle_url('/cache/admin.php', array('store' => $name, 'sesskey' => sesskey()));
             if (empty($storedetails['default'])) {
                 $actions[] = array(
index 371b7ec..bbcd41a 100644 (file)
@@ -1469,7 +1469,7 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) {
             }
         }
         if ($group === false) {
-            if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, get_system_context())) {
+            if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, context_system::instance())) {
                 $group = true;
             } else if ($isloggedin) {
                 $groupids = array();
@@ -1790,7 +1790,7 @@ function calendar_set_event_type_display($type, $display = null, $user = null) {
 function calendar_get_allowed_types(&$allowed, $course = null) {
     global $USER, $CFG, $DB;
     $allowed = new stdClass();
-    $allowed->user = has_capability('moodle/calendar:manageownentries', get_system_context());
+    $allowed->user = has_capability('moodle/calendar:manageownentries', context_system::instance());
     $allowed->groups = false; // This may change just below
     $allowed->courses = false; // This may change just below
     $allowed->site = has_capability('moodle/calendar:manageentries', context_course::instance(SITEID));
similarity index 98%
rename from calendar/tests/externallib_tests.php
rename to calendar/tests/externallib_test.php
index 866b268..e38538e 100644 (file)
@@ -113,13 +113,16 @@ class core_calendar_external_testcase extends externallib_advanced_testcase {
 
         // Create a few events and do asserts.
         $this->create_calendar_event('test', $USER->id);
-        $count = count($DB->get_records("event", array('name' => 'test')));
+        $where = $DB->sql_compare_text('name') ." = ?";
+        $count = count($DB->get_records_select("event", $where, array('test')));
         $this->assertEquals(1, $count);
         $aftercount = count($DB->get_records("event"));
         $this->assertEquals($prevcount + 1, $aftercount);
 
         $this->create_calendar_event('user', $USER->id, 'user', 3);
-        $count = count($DB->get_records("event", array('name' => 'user')));
+        $where = $DB->sql_compare_text('name') ." = ?";
+        $count = count($DB->get_records_select("event", $where, array('user')));
+
         $this->assertEquals(3, $count);
         $aftercount = count($DB->get_records("event"));
         $this->assertEquals($prevcount + 4, $aftercount);
index c158c97..ef1e619 100644 (file)
@@ -685,7 +685,7 @@ class comment {
         global $DB;
         $contexts = array();
         $contexts[] = $context->id;
-        $children = get_child_contexts($context);
+        $children = $context->get_child_contexts();
         foreach ($children as $c) {
             $contexts[] = $c->id;
         }
index f2dfd03..a2de1f1 100644 (file)
@@ -57,7 +57,7 @@ if ($id) {
         }
         $context = context_coursecat::instance($parent);
     } else {
-        $context = get_system_context();
+        $context = context_system::instance();
     }
     $PAGE->set_context($context);
     $category = new stdClass();
index 316c48b..4e0db04 100644 (file)
@@ -16,7 +16,7 @@ class editcategory_form extends moodleform {
 
         // get list of categories to use as parents, with site as the first one
         $options = array();
-        if (has_capability('moodle/category:manage', get_system_context()) || $category->parent == 0) {
+        if (has_capability('moodle/category:manage', context_system::instance()) || $category->parent == 0) {
             $options[0] = get_string('top');
         }
         if ($category->id) {
index 9f2bb26..eab20cf 100644 (file)
@@ -2036,7 +2036,7 @@ function move_courses($courseids, $categoryid) {
             add_to_log($course->id, "course", "move", "edit.php?id=$course->id", $course->id);
 
             $context   = context_course::instance($course->id);
-            context_moved($context, $newparent);
+            $context->update_moved($newparent);
         }
     }
     fix_course_sortorder();
@@ -2353,7 +2353,7 @@ function update_course($data, $editoroptions = NULL) {
 
     if ($movecat) {
         $newparent = context_coursecat::instance($course->category);
-        context_moved($context, $newparent);
+        $context->update_moved($newparent);
     }
 
     fix_course_sortorder();
index f7f925d..cf3748a 100644 (file)
@@ -49,7 +49,7 @@
     // Prevent caching of this page to stop confusion when changing page after making AJAX changes
     $PAGE->set_cacheable(false);
 
-    preload_course_contexts($course->id);
+    context_helper::preload_course($course->id);
     $context = context_course::instance($course->id, MUST_EXIST);
 
     // Remove any switched roles before checking login
index 4ca66c8..4240276 100644 (file)
@@ -129,7 +129,7 @@ class enrol_category_handler {
 
         foreach ($rs as $instance) {
             $coursecontext = context_course::instance($instance->courseid);
-            $contextids = get_parent_contexts($coursecontext);
+            $contextids = $coursecontext->get_parent_context_ids();
             array_pop($contextids); // Remove system context, we are interested in categories only.
 
             list($contextids, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED, 'c');
@@ -178,7 +178,7 @@ function enrol_category_sync_course($course) {
 
     // First find out if any parent category context contains interesting role assignments.
     $coursecontext = context_course::instance($course->id);
-    $contextids = get_parent_contexts($coursecontext);
+    $contextids = $coursecontext->get_parent_context_ids();
     array_pop($contextids); // Remove system context, we are interested in categories only.
 
     list($roleids, $params) = $DB->get_in_or_equal(array_keys($roles), SQL_PARAMS_NAMED, 'r');
index eeed03a..6ab0402 100644 (file)
@@ -86,7 +86,7 @@ class enrol_cohort_plugin extends enrol_plugin {
         if (!has_capability('moodle/course:enrolconfig', $coursecontext) or !has_capability('enrol/cohort:config', $coursecontext)) {
             return false;
         }
-        list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($coursecontext));
+        list($sqlparents, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids());
         $sql = "SELECT id, contextid
                   FROM {cohort}
                  WHERE contextid $sqlparents
index 606b829..377584e 100644 (file)
@@ -394,7 +394,7 @@ function enrol_cohort_get_cohorts(course_enrolment_manager $manager) {
             $enrolled[] = $instance->customint1;
         }
     }
-    list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
+    list($sqlparents, $params) = $DB->get_in_or_equal($context->get_parent_context_ids());
     $sql = "SELECT id, name, idnumber, contextid
               FROM {cohort}
              WHERE contextid $sqlparents
index 8f4ef7f..f7f0804 100644 (file)
@@ -426,7 +426,7 @@ class core_enrol_external extends external_api {
         $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
         $coursecontext = context_course::instance($courseid, IGNORE_MISSING);
         if ($courseid == SITEID) {
-            $context = get_system_context();
+            $context = context_system::instance();
         } else {
             $context = $coursecontext;
         }
@@ -467,7 +467,7 @@ class core_enrol_external extends external_api {
         $enrolledusers = $DB->get_recordset_sql($sql, $enrolledparams, $limitfrom, $limitnumber);
         $users = array();
         foreach ($enrolledusers as $user) {
-            context_instance_preload($user);
+            context_helper::preload_from_record($user);
             if ($userdetails = user_get_user_details($user, $course, $userfields)) {
                 $users[] = $userdetails;
             }
index a2039da..da06cc6 100644 (file)
@@ -176,7 +176,7 @@ class course_enrolment_manager {
     public function get_total_other_users() {
         global $DB;
         if ($this->totalotherusers === null) {
-            list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
+            list($ctxcondition, $params) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
             $params['courseid'] = $this->course->id;
             $sql = "SELECT COUNT(DISTINCT u.id)
                       FROM {role_assignments} ra
@@ -293,7 +293,7 @@ class course_enrolment_manager {
         }
         $key = md5("$sort-$direction-$page-$perpage");
         if (!array_key_exists($key, $this->otherusers)) {
-            list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
+            list($ctxcondition, $params) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'ctx');
             $params['courseid'] = $this->course->id;
             $params['cid'] = $this->course->id;
             $sql = "SELECT ra.id as raid, ra.contextid, ra.component, ctx.contextlevel, ra.roleid, u.*, ue.lastseen
index 6798a48..84b2428 100644 (file)
@@ -51,7 +51,7 @@
     $PAGE->set_url('/error/');
     $PAGE->set_title($site->fullname .':Error');
     $PAGE->set_heading($site->fullname .': Error 404');
-    $PAGE->set_context(get_system_context());
+    $PAGE->set_context(context_system::instance());
     $PAGE->navbar->add('Error 404 - File not Found');
     echo $OUTPUT->header();
     echo $OUTPUT->box(get_string('pagenotexist', 'error'). '<br />'.s($requesturi), 'generalbox boxaligncenter');
index 0b1d9e6..54cb292 100644 (file)
@@ -80,7 +80,7 @@ class core_files_external extends external_api {
         $browser = get_file_browser();
 
         if (empty($fileinfo['contextid'])) {
-            $context  = get_system_context();
+            $context  = context_system::instance();
         } else {
             $context  = context::instance_by_id($fileinfo['contextid']);
         }
index 38472be..ce91c1c 100644 (file)
@@ -147,4 +147,27 @@ class test_external_files extends advanced_testcase {
                 $filename, $filecontent, $contextlevel, $instanceid);
     }
 
+    /*
+     * Make sure core_files_external::upload() works without new parameters.
+     */
+    public function test_upload_without_new_param() {
+        global $USER;
+
+        $this->resetAfterTest();
+        $this->setAdminUser();
+        $context = context_user::instance($USER->id);
+        $contextid = $context->id;
+        $component = "user";
+        $filearea = "private";
+        $itemid = 0;
+        $filepath = "/";
+        $filename = "Simple4.txt";
+        $filecontent = base64_encode("Let us create a nice simple file");
+
+        // Make sure the file is created.
+        @core_files_external::upload($contextid, $component, $filearea, $itemid, $filepath, $filename, $filecontent);
+        $browser = get_file_browser();
+        $file = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename);
+        $this->assertNotEmpty($file);
+    }
 }
\ No newline at end of file
index 0bea014..c4b2f56 100644 (file)
@@ -53,7 +53,7 @@ if (!in_array($context->contextlevel, array(CONTEXT_COURSECAT, CONTEXT_COURSE, C
 
 $isfrontpage = ($context->contextlevel == CONTEXT_COURSE && $context->instanceid == SITEID);
 
-$contextname = print_context_name($context);
+$contextname = $context->get_context_name();
 
 if ($context->contextlevel == CONTEXT_COURSECAT) {
     $heading = "$SITE->fullname: ".get_string("categories");
index 637a583..70451da 100644 (file)
@@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die();
  *
  * @category grading
  * @example $manager = get_grading_manager($areaid);
- * @example $manager = get_grading_manager(get_system_context());
+ * @example $manager = get_grading_manager(context_system::instance());
  * @example $manager = get_grading_manager($context, 'mod_assignment', 'submission');
  * @param stdClass|int|null $context_or_areaid if $areaid is passed, no other parameter is needed
  * @param string|null $component the frankenstyle name of the component
index 075ca27..8de5bca 100644 (file)
@@ -223,7 +223,7 @@ foreach ($rs as $template) {
     $actions = array();
     if ($controller->is_shared_template()) {
         $actions[] = $output->pick_action_icon(new moodle_url($PAGE->url, array('pick' => $template->id)),
-            get_string('templatepick', 'core_grading'), 'i/tick_green_big', 'pick template');
+            get_string('templatepick', 'core_grading'), 'i/valid', 'pick template');
         if ($canmanage or ($canshare and ($template->usercreated == $USER->id))) {
             //$actions[] = $output->pick_action_icon(new moodle_url($PAGE->url, array('edit' => $template->id)),
             //    get_string('templateedit', 'core_grading'), 'i/edit', 'edit');
@@ -232,7 +232,7 @@ foreach ($rs as $template) {
         }
     } else if ($controller->is_own_form()) {
         $actions[] = $output->pick_action_icon(new moodle_url($PAGE->url, array('pick' => $template->id)),
-            get_string('templatepickownform', 'core_grading'), 'i/tick_green_big', 'pick ownform');
+            get_string('templatepickownform', 'core_grading'), 'i/valid', 'pick ownform');
     }
     $out .= $output->box(join(' ', $actions), 'template-actions');
     $out .= $output->box($controller->get_formatted_description(), 'template-description');
index c99f672..3c21585 100644 (file)
@@ -532,93 +532,17 @@ class grade_report_grader extends grade_report {
     }
 
     /**
-     * Builds and returns a div with on/off toggles.
-     * @return string HTML code
-     * @deprecated since 2.4 as it appears not to be used any more.
+     * @deprecated since Moodle 2.4 as it appears not to be used any more.
      */
     public function get_toggles_html() {
-        global $CFG, $USER, $COURSE, $OUTPUT;
-        debugging('Call to deprecated function grade_report_grader::get_toggles_html().', DEBUG_DEVELOPER);
-        $html = '';
-        if ($USER->gradeediting[$this->courseid]) {
-            if (has_capability('moodle/grade:manage', $this->context) or has_capability('moodle/grade:hide', $this->context)) {
-                $html .= $this->print_toggle('eyecons');
-            }
-            if (has_capability('moodle/grade:manage', $this->context)
-             or has_capability('moodle/grade:lock', $this->context)
-             or has_capability('moodle/grade:unlock', $this->context)) {
-                $html .= $this->print_toggle('locks');
-            }
-            if (has_capability('moodle/grade:manage', $this->context)) {
-                $html .= $this->print_toggle('quickfeedback');
-            }
-
-            if (has_capability('moodle/grade:manage', $this->context)) {
-                $html .= $this->print_toggle('calculations');
-            }
-        }
-
-        if ($this->canviewhidden) {
-            $html .= $this->print_toggle('averages');
-        }
-
-        $html .= $this->print_toggle('ranges');
-        if (!empty($CFG->enableoutcomes)) {
-            $html .= $this->print_toggle('nooutcomes');
-        }
-
-        return $OUTPUT->container($html, 'grade-report-toggles');
+        throw new coding_exception('get_toggles_html() can not be used any more');
     }
 
     /**
-    * Shortcut function for printing the grader report toggles.
-    * @param string $type The type of toggle
-    * @param bool $return Whether to return the HTML string rather than printing it
-    * @return void
-    * @deprecated since 2.4 as it appears not to be used any more.
-    */
+     * @deprecated since 2.4 as it appears not to be used any more.
+     */
     public function print_toggle($type) {
-        global $CFG, $OUTPUT;
-        debugging('Call to deprecated function grade_report_grader::print_toggle().', DEBUG_DEVELOPER);
-        $icons = array('eyecons' => 't/hide',
-                       'calculations' => 't/calc',
-                       'locks' => 't/lock',
-                       'averages' => 't/mean',
-                       'quickfeedback' => 't/feedback',
-                       'nooutcomes' => 't/outcomes');
-
-        $prefname = 'grade_report_show' . $type;
-
-        if (array_key_exists($prefname, $CFG)) {
-            $showpref = get_user_preferences($prefname, $CFG->$prefname);
-        } else {
-            $showpref = get_user_preferences($prefname);
-        }
-
-        $strshow = $this->get_lang_string('show' . $type, 'grades');
-        $strhide = $this->get_lang_string('hide' . $type, 'grades');
-
-        $showhide = 'show';
-        $toggleaction = 1;
-
-        if ($showpref) {
-            $showhide = 'hide';
-            $toggleaction = 0;
-        }
-
-        if (array_key_exists($type, $icons)) {
-            $imagename = $icons[$type];
-        } else {
-            $imagename = "t/$type";
-        }
-
-        $string = ${'str' . $showhide};
-
-        $url = new moodle_url($this->baseurl, array('toggle' => $toggleaction, 'toggle_type' => $type));
-
-        $retval = $OUTPUT->container($OUTPUT->action_icon($url, new pix_icon($imagename, $string))); // TODO: this container looks wrong here
-
-        return $retval;
+        throw new coding_exception('print_toggle() can not be used any more');
     }
 
     /**
index 4a8d086..9ff8f36 100644 (file)
@@ -1,6 +1,9 @@
 This files describes API changes in /grade/report/*,
 information provided here is intended especially for developers.
 
+=== 2.6 ===
+* grade_report_grader::get_toggles_html() and grade_report_grader::print_toggle()
+  can not be used any more
 
 === 2.3.5, 2.4.2 ===
 * class_grade_report::showtotalsifcontainhidden has been switched from a single integer value to an array.
index 9a0df5f..ffd8f74 100644 (file)
@@ -78,7 +78,7 @@ switch ($action) {
 
     case 'ajax_getmembersingroup':
         $roles = array();
-        if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) {
+        if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) {
             foreach($groupmemberroles as $roleid=>$roledata) {
                 $shortroledata = new stdClass();
                 $shortroledata->name = $roledata->name;
@@ -246,7 +246,7 @@ $member_names = array();
 
 $atleastonemember = false;
 if ($singlegroup) {
-    if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, u.firstname, u.lastname')) {
+    if ($groupmemberroles = groups_get_members_by_role($groupids[0], $courseid, 'u.id, ' . get_all_user_name_fields(true, 'u'))) {
         foreach($groupmemberroles as $roleid=>$roledata) {
             echo '<optgroup label="'.s($roledata->name).'">';
             foreach($roledata->users as $member) {
index 7e6fa2c..134261e 100644 (file)
@@ -90,7 +90,8 @@ if ($groupingid) {
 
 list($sort, $sortparams) = users_order_by_sql('u');
 
-$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, u.firstname, u.lastname, u.idnumber, u.username
+$allnames = get_all_user_name_fields(true, 'u');
+$sql = "SELECT g.id AS groupid, gg.groupingid, u.id AS userid, $allnames, u.idnumber, u.username
           FROM {groups} g
                LEFT JOIN {groupings_groups} gg ON g.id = gg.groupid
                LEFT JOIN {groups_members} gm ON g.id = gm.groupid
@@ -106,6 +107,9 @@ foreach ($rs as $row) {
     $user->lastname  = $row->lastname;
     $user->username  = $row->username;
     $user->idnumber  = $row->idnumber;
+    foreach (get_all_user_name_fields() as $addname) {
+        $user->$addname = $row->$addname;
+    }
     if (!$row->groupingid) {
         $row->groupingid = -1;
     }
index b6e872a..d6a3c2a 100644 (file)
@@ -227,7 +227,7 @@ $string['configfrontpage'] = 'The items selected above will be displayed on the
 $string['configfrontpagecourselimit'] = 'Maximum number of courses';
 $string['configfrontpagecourselimithelp'] = 'Maximum number of courses to be displayed on the site\'s front page in course listings.';
 $string['configfrontpageloggedin'] = 'The items selected above will be displayed on the site\'s front page when a user is logged in.';
-$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "First name + Surname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions).';
+$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is "firstname lastname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions). Placeholders that can be used are: firstname, lastname, firstnamephonetic, lastnamephonetic, middlename, and alternatename.';
 $string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version.<br />Simply download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz" >http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a> and extract it into "{$a}" directory on your server.';
 $string['configgetremoteaddrconf'] = 'If your server is behind a reverse proxy, you can use this setting to specify which HTTP headers can be trusted to contain the remote IP address. The headers are read in order, using the first one that is available.';
 $string['configgradebookroles'] = 'This setting allows you to control who appears on the gradebook.  Users need to have at least one of these roles in a course to be shown in the gradebook for that course.';
@@ -548,6 +548,7 @@ $string['frontpagerestore'] = 'Front page restore';
 $string['frontpageroles'] = 'Front page roles';
 $string['frontpagesettings'] = 'Front page settings';
 $string['fullnamedisplay'] = 'Full name format';
+$string['fullnamedisplayprivate'] = 'Full name format - private';
 $string['gdrecommended'] = 'GD extension is used for conversion of images, some features such as user profile images will not be available if missing.';
 $string['gdrequired'] = 'The GD extension is now required by Moodle for image conversion.';
 $string['generalsettings'] = 'General settings';
index 3ec27d6..e92ab1f 100644 (file)
@@ -60,6 +60,7 @@ $string['addfilehere'] = 'Add file(s) here';
 $string['addinganew'] = 'Adding a new {$a}';
 $string['addinganewto'] = 'Adding a new {$a->what} to {$a->to}';
 $string['addingdatatoexisting'] = 'Adding data to existing';
+$string['additionalnames'] = 'Additional names';
 $string['addlinkhere'] = 'Add link here';
 $string['addnewcategory'] = 'Add new category';
 $string['addnewcourse'] = 'Add a new course';
@@ -135,6 +136,7 @@ $string['allparticipants'] = 'All participants';
 $string['allteachers'] = 'All teachers';
 $string['alphanumerical'] = 'Can only contain alphanumeric characters, hyphen (-) or period (.)';
 $string['alreadyconfirmed'] = 'Registration has already been confirmed';
+$string['alternatename'] = 'Alternate name';
 $string['always'] = 'Always';
 $string['and'] = '{$a->one} and {$a->two}';
 $string['answer'] = 'Answer';
@@ -680,6 +682,7 @@ $string['filter'] = 'Filter';
 $string['findmorecourses'] = 'Find more courses...';
 $string['firstaccess'] = 'First access';
 $string['firstname'] = 'First name';
+$string['firstnamephonetic'] = 'First name - phonetic';
 $string['firsttime'] = 'Is this your first time here?';
 $string['folder'] = 'Folder';
 $string['folderclosed'] = 'Closed folder';
@@ -910,6 +913,7 @@ $string['lastedited'] = 'Last edited';
 $string['lastlogin'] = 'Last login';
 $string['lastmodified'] = 'Last modified';
 $string['lastname'] = 'Surname';
+$string['lastnamephonetic'] = 'Surname - phonetic';
 $string['lastyear'] = 'Last year';
 $string['latestlanguagepack'] = 'Check for latest language pack on moodle.org';
 $string['layouttable'] = 'Layout table';
@@ -1019,6 +1023,7 @@ $string['messageprovider:instantmessage'] = 'Personal messages between users';
 $string['messageprovider:instantmessage_help'] = 'This section configures what happens to messages that are sent to you directly from other users on this site.';
 $string['messageselect'] = 'Select this user as a message recipient';
 $string['messageselectadd'] = 'Send a message';
+$string['middlename'] = 'Middle name';
 $string['migratinggrades'] = 'Migrating grades';
 $string['min'] = 'min';
 $string['mins'] = 'mins';
index 10d0c80..711fa5f 100644 (file)
@@ -3964,7 +3964,8 @@ function get_role_users($roleid, context $context, $parent = false, $fields = ''
     global $DB;
 
     if (empty($fields)) {
-        $fields = 'u.id, u.confirmed, u.username, u.firstname, u.lastname, '.
+        $allnames = get_all_user_name_fields(true, 'u');
+        $fields = 'u.id, u.confirmed, u.username, '. $allnames . ', ' .
                   'u.maildisplay, u.mailformat, u.maildigest, u.email, u.emailstop, u.city, '.
                   'u.country, u.picture, u.idnumber, u.department, u.institution, '.
                   'u.lang, u.timezone, u.lastaccess, u.mnethostid, r.name AS rolename, r.sortorder, '.
@@ -5357,6 +5358,10 @@ abstract class context extends stdClass implements IteratorAggregate {
         $fs = get_file_storage();
         $fs->delete_area_files($this->_id);
 
+        // Delete all repository instances attached to this context.
+        require_once($CFG->dirroot . '/repository/lib.php');
+        repository::delete_all_for_context($this->_id);
+
         // delete all advanced grading data attached to this context
         require_once($CFG->dirroot.'/grade/grading/lib.php');
         grading_manager::delete_all_for_context($this->_id);
@@ -6001,7 +6006,7 @@ class context_system extends context {
 
 
         try {
-            // we ignore the strictness completely because system context must except except during install
+            // We ignore the strictness completely because system context must exist except during install.
             $record = $DB->get_record('context', array('contextlevel'=>CONTEXT_SYSTEM), '*', MUST_EXIST);
         } catch (dml_exception $e) {
             //table or record does not exist
@@ -7225,161 +7230,9 @@ class context_block extends context {
 // 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.
-
-
-/**
- * Not available any more, use load_temp_course_role() instead.
- *
- * @deprecated since 2.2
- * @param stdClass $context
- * @param int $roleid
- * @param array $accessdata
- * @return array
- */
-function load_temp_role($context, $roleid, array $accessdata) {
-    debugging('load_temp_role() is deprecated, please use load_temp_course_role() instead, temp role not loaded.');
-    return $accessdata;
-}
-
-/**
- * Not available any more, use remove_temp_course_roles() instead.
- *
- * @deprecated since 2.2
- * @param stdClass $context
- * @param array $accessdata
- * @return array access data
- */
-function remove_temp_roles($context, array $accessdata) {
-    debugging('remove_temp_role() is deprecated, please use remove_temp_course_roles() instead.');
-    return $accessdata;
-}
-
-/**
- * Returns system context or null if can not be created yet.
- *
- * @deprecated since 2.2, use context_system::instance()
- * @param bool $cache use caching
- * @return context system context (null if context table not created yet)
- */
-function get_system_context($cache = true) {
-    return context_system::instance(0, IGNORE_MISSING, $cache);
-}
-
-/**
- * Recursive function which, given a context, find all parent context ids,
- * and return the array in reverse order, i.e. parent first, then grand
- * parent, etc.
- *
- * @deprecated since 2.2, use $context->get_parent_context_ids() instead
- * @param context $context
- * @param bool $includeself optional, defaults to false
- * @return array
- */
-function get_parent_contexts(context $context, $includeself = false) {
-    return $context->get_parent_context_ids($includeself);
-}
-
-/**
- * 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 since 2.2, use $context->get_parent_context() instead
- * @param context $context
- * @return integer the id of the parent context.
- */
-function get_parent_contextid(context $context) {
-    if ($parent = $context->get_parent_context()) {
-        return $parent->id;
-    } else {
-        return false;
-    }
-}
-
-/**
- * Recursive function which, given a context, find all its children context ids.
- *
- * For course category contexts it will return immediate children only categories and courses.
- * It will NOT recurse into courses or child categories.
- * If you want to do that, call it on the returned courses/categories.
- *
- * When called for a course context, it will return the modules and blocks
- * displayed in the course page.
- *
- * If called on a user/course/module context it _will_ populate the cache with the appropriate
- * contexts ;-)
- *
- * @deprecated since 2.2, use $context->get_child_contexts() instead
- * @param context $context
- * @return array Array of child records
- */
-function get_child_contexts(context $context) {
-    return $context->get_child_contexts();
-}
-
-/**
- * Precreates all contexts including all parents
- *
- * @deprecated since 2.2
- * @param int $contextlevel empty means all
- * @param bool $buildpaths update paths and depths
- * @return void
- */
-function create_contexts($contextlevel = null, $buildpaths = true) {
-    context_helper::create_instances($contextlevel, $buildpaths);
-}
-
-/**
- * Remove stale context records
- *
- * @deprecated since 2.2, use context_helper::cleanup_instances() instead
- * @return bool
- */
-function cleanup_contexts() {
-    context_helper::cleanup_instances();
-    return true;
-}
-
-/**
- * Populate context.path and context.depth where missing.
- *
- * @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
- */
-function build_context_path($force = false) {
-    context_helper::build_all_paths($force);
-}
-
-/**
- * Rebuild all related context depth and path caches
- *
- * @deprecated since 2.2
- * @param array $fixcontexts array of contexts, strongtyped
- * @return void
- */
-function rebuild_contexts(array $fixcontexts) {
-    foreach ($fixcontexts as $fixcontext) {
-        $fixcontext->reset_paths(false);
-    }
-    context_helper::build_all_paths(false);
-}
-
-/**
- * Preloads all contexts relating to a course: course, modules. Block contexts
- * 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 since 2.2
- * @param int $courseid Course ID
- * @return void
- */
-function preload_course_contexts($courseid) {
-    context_helper::preload_course($courseid);
-}
-
 /**
  * Preloads context information together with instances.
- * Use context_instance_preload() to strip the context info from the record and cache the context instance.
+ * Use context_helper::preload_from_record() to strip the context info from the record and cache the context instance.
  *
  * @deprecated since 2.2
  * @param string $joinon for example 'u.id'
@@ -7393,18 +7246,6 @@ function context_instance_preload_sql($joinon, $contextlevel, $tablealias) {
     return array($select, $join);
 }
 
-/**
- * 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 since 2.2
- * @param stdClass $rec
- * @return void (modifies $rec)
- */
-function context_instance_preload(stdClass $rec) {
-    context_helper::preload_from_record($rec);
-}
-
 /**
  * Mark a context as dirty (with timestamp) so as to force reloading of the context.
  *
@@ -7438,26 +7279,6 @@ function mark_context_dirty($path) {
     }
 }
 
-/**
- * Update the path field of the context and all dep. subcontexts that follow
- *
- * Update the path field of the context and
- * all the dependent subcontexts that follow
- * the move.
- *
- * The most important thing here is to be as
- * DB efficient as possible. This op can have a
- * massive impact in the DB.
- *
- * @deprecated since 2.2
- * @param context $context context obj
- * @param context $newparent new parent obj
- * @return void
- */
-function context_moved(context $context, context $newparent) {
-    $context->update_moved($newparent);
-}
-
 /**
  * Remove a context record and any dependent entries,
  * removes context from static context cache too
@@ -7481,32 +7302,6 @@ function delete_context($contextlevel, $instanceid, $deleterecord = true) {
     return true;
 }
 
-/**
- * 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.
- */
-function get_contextlevel_name($contextlevel) {
-    return context_helper::get_level_name($contextlevel);
-}
-
-/**
- * Prints human readable context identifier.
- *
- * @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.
- * @param boolean $short whether to user the short name of the thing. Only applies
- *      to course contexts
- * @return string the human readable context name.
- */
-function print_context_name(context $context, $withprefix = true, $short = false) {
-    return $context->get_context_name($withprefix, $short);
-}
-
 /**
  * Get a URL for a context, if there is a natural one. For example, for
  * CONTEXT_COURSE, this is the course page. For CONTEXT_USER it is the
index 1276b41..4a76f82 100644 (file)
@@ -6959,7 +6959,7 @@ class admin_setting_managerepository extends admin_setting {
                     // Calculate number of instances in order to display them for the Moodle administrator
                     if (!empty($instanceoptionnames)) {
                         $params = array();
-                        $params['context'] = array(get_system_context());
+                        $params['context'] = array(context_system::instance());
                         $params['onlyvisible'] = false;
                         $params['type'] = $typename;
                         $admininstancenumber = count(repository::static_function($typename, 'get_instances', $params));
@@ -7117,7 +7117,7 @@ class admin_setting_enablemobileservice extends admin_setting_configcheckbox {
             $assign = true;
         }
         if (!empty($assign)) {
-            $systemcontext = get_system_context();
+            $systemcontext = context_system::instance();
             assign_capability('webservice/xmlrpc:use', $permission, $CFG->defaultuserroleid, $systemcontext->id, true);
             assign_capability('webservice/rest:use', $permission, $CFG->defaultuserroleid, $systemcontext->id, true);
         }
index daf2d44..cf51764 100644 (file)
@@ -620,8 +620,10 @@ function badges_notify_badge_award(badge $badge, $userid, $issued, $filepathhash
     $userfrom = new stdClass();
     $userfrom->id = $admin->id;
     $userfrom->email = !empty($CFG->badges_defaultissuercontact) ? $CFG->badges_defaultissuercontact : $admin->email;
+    foreach (get_all_user_name_fields() as $addname) {
+        $userfrom->$addname = !empty($CFG->badges_defaultissuername) ? '' : $admin->$addname;
+    }
     $userfrom->firstname = !empty($CFG->badges_defaultissuername) ? $CFG->badges_defaultissuername : $admin->firstname;
-    $userfrom->lastname = !empty($CFG->badges_defaultissuername) ? '' : $admin->lastname;
     $userfrom->maildisplay = true;
 
     $issuedlink = html_writer::link(new moodle_url('/badges/badge.php', array('hash' => $issued)), $badge->name);
index 02e3c8d..ae413cf 100644 (file)
@@ -566,7 +566,7 @@ class block_manager {
         $context = $this->page->context;
         $contexttest = 'bi.parentcontextid = :contextid2';
         $parentcontextparams = array();
-        $parentcontextids = get_parent_contexts($context);
+        $parentcontextids = $context->get_parent_context_ids();
         if ($parentcontextids) {
             list($parentcontexttest, $parentcontextparams) =
                     $DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED, 'parentcontext');
@@ -630,7 +630,7 @@ class block_manager {
         $this->birecordsbyregion = $this->prepare_per_region_arrays();
         $unknown = array();
         foreach ($blockinstances as $bi) {
-            context_instance_preload($bi);
+            context_helper::preload_from_record($bi);
             if ($this->is_known_region($bi->region)) {
                 $this->birecordsbyregion[$bi->region][] = $bi;
             } else {
index fefe8e6..0c7a8fa 100644 (file)
@@ -142,6 +142,7 @@ class core_component {
                 @chmod($cachefile, $CFG->filepermissions);
             }
             @unlink($cachefile.'.tmp'); // Just in case anything fails (race condition).
+            self::invalidate_opcode_php_cache($cachefile);
         }
     }
 
@@ -735,4 +736,21 @@ $cache = '.var_export($cache, true).';
         }
         return $return;
     }
+
+    /**
+     * Invalidate opcode cache for given file, this is intended for
+     * php files that are stored in dataroot.
+     *
+     * Note: we need it here because this class must be self-contained.
+     *
+     * @param string $file
+     */
+    public static function invalidate_opcode_php_cache($file) {
+        if (function_exists('opcache_invalidate')) {
+            if (!file_exists($file)) {
+                return;
+            }
+            opcache_invalidate($file, true);
+        }
+    }
 }
index ba549e1..c5fd1e6 100644 (file)
@@ -712,9 +712,10 @@ class coursecat implements renderable, cacheable_object, IteratorAggregate {
         list($sql2, $params2) = $DB->get_in_or_equal($managerroles, SQL_PARAMS_NAMED, 'rid');
         list($sort, $sortparams) = users_order_by_sql('u');
         $notdeleted = array('notdeleted'=>0);
+        $allnames = get_all_user_name_fields(true, 'u');
         $sql = "SELECT ra.contextid, ra.id AS raid,
                        r.id AS roleid, r.name AS rolename, r.shortname AS roleshortname,
-                       rn.name AS rolecoursealias, u.id, u.username, u.firstname, u.lastname
+                       rn.name AS rolecoursealias, u.id, u.username, $allnames
                   FROM {role_assignments} ra
                   JOIN {user} u ON ra.userid = u.id
                   JOIN {role} r ON ra.roleid = r.id
@@ -2033,7 +2034,7 @@ class course_in_list implements IteratorAggregate {
      *     context preloading
      */
     public function __construct(stdClass $record) {
-        context_instance_preload($record);
+        context_helper::preload_from_record($record);
         $this->record = new stdClass();
         foreach ($record as $key => $value) {
             $this->record->$key = $value;
@@ -2109,8 +2110,9 @@ class course_in_list implements IteratorAggregate {
                 $user = new stdClass();
                 $user->id = $ruser->id;
                 $user->username = $ruser->username;
-                $user->firstname = $ruser->firstname;
-                $user->lastname = $ruser->lastname;
+                foreach (get_all_user_name_fields() as $addname) {
+                    $user->$addname = $ruser->$addname;
+                }
                 $role = new stdClass();
                 $role->id = $ruser->roleid;
                 $role->name = $ruser->rolename;
index 49d8cb5..36ad297 100644 (file)
@@ -507,10 +507,11 @@ function get_users_listing($sort='lastaccess', $dir='ASC', $page=0, $recordsperp
                 array('id', 'username', 'email', 'firstname', 'lastname', 'city', 'country',
                 'lastaccess', 'confirmed', 'mnethostid'));
     }
+    $namefields = get_all_user_name_fields(true);
+    $extrafields = "$extrafields, $namefields";
 
     // warning: will return UNCONFIRMED USERS
-    return $DB->get_records_sql("SELECT id, username, email, firstname, lastname, city, country,
-                                        lastaccess, confirmed, mnethostid, suspended $extrafields
+    return $DB->get_records_sql("SELECT id, username, email, city, country, lastaccess, confirmed, mnethostid, suspended $extrafields
                                    FROM {user}
                                   WHERE $select
                                   $sort", $params, $page, $recordsperpage);
@@ -631,7 +632,7 @@ function get_courses($categoryid="all", $sort="c.sortorder ASC", $fields="c.*")
 
         // loop throught them
         foreach ($courses as $course) {
-            context_instance_preload($course);
+            context_helper::preload_from_record($course);
             if (isset($course->visible) && $course->visible <= 0) {
                 // for hidden courses, require visibility check
                 if (has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
@@ -698,7 +699,7 @@ function get_courses_page($categoryid="all", $sort="c.sortorder ASC", $fields="c
     $rs = $DB->get_recordset_sql($sql, $params);
     // iteration will have to be done inside loop to keep track of the limitfrom and limitnum
     foreach($rs as $course) {
-        context_instance_preload($course);
+        context_helper::preload_from_record($course);
         if ($course->visible <= 0) {
             // for hidden courses, require visibility check
             if (has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
@@ -810,7 +811,7 @@ function get_courses_search($searchterms, $sort, $page, $recordsperpage, &$total
     foreach($rs as $course) {
         if (!$course->visible) {
             // preload contexts only for hidden courses or courses we need to return
-            context_instance_preload($course);
+            context_helper::preload_from_record($course);
             $coursecontext = context_course::instance($course->id);
             if (!has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                 continue;
@@ -1781,8 +1782,8 @@ function get_logs($select, array $params=null, $order='l.time DESC', $limitfrom=
            $select";
 
     $totalcount = $DB->count_records_sql($sql, $params);
-
-    $sql = "SELECT l.*, u.firstname, u.lastname, u.picture
+    $allnames = get_all_user_name_fields(true, 'u');
+    $sql = "SELECT l.*, $allnames, u.picture
               FROM {log} l
               LEFT JOIN {user} u ON l.userid = u.id
            $select
index 67660b3..dba2025 100644 (file)
         <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
         <FIELD NAME="trustbitmask" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
         <FIELD NAME="imagealt" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="alt tag for user uploaded image"/>
+        <FIELD NAME="lastnamephonetic" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Last name phonetic"/>
+        <FIELD NAME="firstnamephonetic" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="First name phonetic"/>
+        <FIELD NAME="middlename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Middle name"/>
+        <FIELD NAME="alternatename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Alternate name - Useful for three-name countries."/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
         <INDEX NAME="email" UNIQUE="false" FIELDS="email"/>
         <INDEX NAME="auth" UNIQUE="false" FIELDS="auth"/>
         <INDEX NAME="idnumber" UNIQUE="false" FIELDS="idnumber"/>
+        <INDEX NAME="firstnamephonetic" UNIQUE="false" FIELDS="firstnamephonetic"/>
+        <INDEX NAME="lastnamephonetic" UNIQUE="false" FIELDS="lastnamephonetic"/>
+        <INDEX NAME="middlename" UNIQUE="false" FIELDS="middlename"/>
+        <INDEX NAME="alternatename" UNIQUE="false" FIELDS="alternatename"/>
       </INDEXES>
     </TABLE>
     <TABLE NAME="user_preferences" COMMENT="Allows modules to store arbitrary user preferences">
index c6bafe0..b593aef 100644 (file)
@@ -2190,5 +2190,74 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013061700.00);
     }
 
+    if ($oldversion < 2013070800.00) {
+
+        // Remove orphan repository instances.
+        if ($DB->get_dbfamily() === 'mysql') {
+            $sql = "DELETE {repository_instances} FROM {repository_instances}
+                    LEFT JOIN {context} ON {context}.id = {repository_instances}.contextid
+                    WHERE {context}.id IS NULL";
+        } else {
+            $sql = "DELETE FROM {repository_instances}
+                    WHERE NOT EXISTS (
+                        SELECT 'x' FROM {context}
+                        WHERE {context}.id = {repository_instances}.contextid)";
+        }
+        $DB->execute($sql);
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013070800.00);
+    }
+
+    if ($oldversion < 2013070800.01) {
+
+        // Define field lastnamephonetic to be added to user.
+        $table = new xmldb_table('user');
+        $field = new xmldb_field('lastnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'imagealt');
+        $index = new xmldb_index('lastnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('lastnamephonetic'));
+
+        // Conditionally launch add field lastnamephonetic.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+            $dbman->add_index($table, $index);
+        }
+
+        // Define field firstnamephonetic to be added to user.
+        $table = new xmldb_table('user');
+        $field = new xmldb_field('firstnamephonetic', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastnamephonetic');
+        $index = new xmldb_index('firstnamephonetic', XMLDB_INDEX_NOTUNIQUE, array('firstnamephonetic'));
+
+        // Conditionally launch add field firstnamephonetic.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+            $dbman->add_index($table, $index);
+        }
+
+        // Define field alternatename to be added to user.
+        $table = new xmldb_table('user');
+        $field = new xmldb_field('middlename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'firstnamephonetic');
+        $index = new xmldb_index('middlename', XMLDB_INDEX_NOTUNIQUE, array('middlename'));
+
+        // Conditionally launch add field firstnamephonetic.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+            $dbman->add_index($table, $index);
+        }
+
+        // Define field alternatename to be added to user.
+        $table = new xmldb_table('user');
+        $field = new xmldb_field('alternatename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'middlename');
+        $index = new xmldb_index('alternatename', XMLDB_INDEX_NOTUNIQUE, array('alternatename'));
+
+        // Conditionally launch add field alternatename.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+            $dbman->add_index($table, $index);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013070800.01);
+    }
+
     return true;
 }
index ecb064b..1857700 100644 (file)
@@ -599,7 +599,7 @@ function get_recent_enrolments($courseid, $timestart) {
  * This allows us to SELECT from major tables JOINing with
  * context at no cost, saving a ton of context lookups...
  *
- * Use context_instance_preload() instead.
+ * Use context_helper::preload_from_record() instead.
  *
  * @deprecated since 2.0
  * @param object $rec
@@ -612,7 +612,7 @@ function make_context_subobj($rec) {
 /**
  * Do some basic, quick checks to see whether $rec->context looks like a valid context object.
  *
- * Use context_instance_preload() instead.
+ * Use context_helper::preload_from_record() instead.
  *
  * @deprecated since 2.0
  * @param object $rec a think that has a context, for example a course,
@@ -632,7 +632,7 @@ function is_context_subobj_valid($rec, $contextlevel) {
  * or may not, have come from a place that does make_context_subobj, you can use
  * this method to ensure that $rec->context is present and correct before you continue.
  *
- * Use context_instance_preload() instead.
+ * Use context_helper::preload_from_record() instead.
  *
  * @deprecated since 2.0
  * @param object $rec a thing that has an associated context.
@@ -4069,7 +4069,7 @@ function get_categories($parent='none', $sort=NULL, $shallow=true) {
 
     $rs = $DB->get_recordset_sql($sql, $params);
     foreach($rs as $cat) {
-        context_instance_preload($cat);
+        context_helper::preload_from_record($cat);
         $catcontext = context_coursecat::instance($cat->id);
         if ($cat->visible || has_capability('moodle/category:viewhiddencategories', $catcontext)) {
             $categories[$cat->id] = $cat;
@@ -4301,7 +4301,7 @@ function get_course_category_tree($id = 0, $depth = 0) {
             if ($course->id == SITEID) {
                 continue;
             }
-            context_instance_preload($course);
+            context_helper::preload_from_record($course);
             if (!empty($course->visible) || has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
                 $categoryids[$course->category]->courses[$course->id] = $course;
             }
@@ -4474,7 +4474,7 @@ function blog_get_context_url($context=null) {
             break;
         case CONTEXT_MODULE:
             $filterparam = 'modid';
-            $strlevel = print_context_name($context);
+            $strlevel = $context->get_context_name();
             break;
         case CONTEXT_USER:
             $filterparam = 'userid';
@@ -4605,7 +4605,7 @@ function get_courses_wmanagers($categoryid=0, $sort="c.sortorder ASC", $fields=a
         // the context, and prepping data to fetch the
         // managers efficiently later...
         foreach ($courses as $k => $course) {
-            context_instance_preload($course);
+            context_helper::preload_from_record($course);
             $coursecontext = context_course::instance($course->id);
             $courses[$k] = $course;
             $courses[$k]->managers = array();
@@ -4899,3 +4899,227 @@ function get_context_instance_by_id($id, $strictness = IGNORE_MISSING) {
     debugging('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER);
     return context::instance_by_id($id, $strictness);
 }
+
+/**
+ * @deprecated since Moodle 2.2
+ * @see load_temp_course_role()
+ */
+function load_temp_role($context, $roleid, array $accessdata) {
+    throw new coding_exception('load_temp_role() can not be used any more, please use load_temp_course_role()');
+}
+
+/**
+ * @deprecated since Moodle 2.2
+ * @see remove_temp_course_roles()
+ */
+function remove_temp_roles($context, array $accessdata) {
+    throw new coding_exception('remove_temp_roles() can not be used any more, please use remove_temp_course_roles()');
+}
+
+/**
+ * Returns system context or null if can not be created yet.
+ *
+ * @see context_system::instance()
+ * @deprecated since 2.2
+ * @param bool $cache use caching
+ * @return context system context (null if context table not created yet)
+ */
+function get_system_context($cache = true) {
+    debugging('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
+    return context_system::instance(0, IGNORE_MISSING, $cache);
+}
+
+/**
+ * Recursive function which, given a context, find all parent context ids,
+ * and return the array in reverse order, i.e. parent first, then grand
+ * parent, etc.
+ *
+ * @see context::get_parent_context_ids()
+ * @deprecated since 2.2, use $context->get_parent_context_ids() instead
+ * @param context $context
+ * @param bool $includeself optional, defaults to false
+ * @return array
+ */
+function get_parent_contexts(context $context, $includeself = false) {
+    debugging('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER);
+    return $context->get_parent_context_ids($includeself);
+}
+
+/**
+ * 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 since Moodle 2.2
+ * @see context::get_parent_context()
+ * @param context $context
+ * @return integer the id of the parent context.
+ */
+function get_parent_contextid(context $context) {
+    debugging('get_parent_contextid() is deprecated, please use $context->get_parent_context() instead.', DEBUG_DEVELOPER);
+
+    if ($parent = $context->get_parent_context()) {
+        return $parent->id;
+    } else {
+        return false;
+    }
+}
+
+/**
+ * Recursive function which, given a context, find all its children contexts.
+ *
+ * For course category contexts it will return immediate children only categories and courses.
+ * It will NOT recurse into courses or child categories.
+ * If you want to do that, call it on the returned courses/categories.
+ *
+ * When called for a course context, it will return the modules and blocks
+ * displayed in the course page.
+ *
+ * If called on a user/course/module context it _will_ populate the cache with the appropriate
+ * contexts ;-)
+ *
+ * @see context::get_child_contexts()
+ * @deprecated since 2.2
+ * @param context $context
+ * @return array Array of child records
+ */
+function get_child_contexts(context $context) {
+    debugging('get_child_contexts() is deprecated, please use $context->get_child_contexts() instead.', DEBUG_DEVELOPER);
+    return $context->get_child_contexts();
+}
+
+/**
+ * Precreates all contexts including all parents.
+ *
+ * @see context_helper::create_instances()
+ * @deprecated since 2.2
+ * @param int $contextlevel empty means all
+ * @param bool $buildpaths update paths and depths
+ * @return void
+ */
+function create_contexts($contextlevel = null, $buildpaths = true) {
+    debugging('create_contexts() is deprecated, please use context_helper::create_instances() instead.', DEBUG_DEVELOPER);
+    context_helper::create_instances($contextlevel, $buildpaths);
+}
+
+/**
+ * Remove stale context records.
+ *
+ * @see context_helper::cleanup_instances()
+ * @deprecated since 2.2
+ * @return bool
+ */
+function cleanup_contexts() {
+    debugging('cleanup_contexts() is deprecated, please use context_helper::cleanup_instances() instead.', DEBUG_DEVELOPER);
+    context_helper::cleanup_instances();
+    return true;
+}
+
+/**
+ * Populate context.path and context.depth where missing.
+ *
+ * @see context_helper::build_all_paths()
+ * @deprecated since 2.2
+ * @param bool $force force a complete rebuild of the path and depth fields, defaults to false
+ * @return void
+ */
+function build_context_path($force = false) {
+    debugging('build_context_path() is deprecated, please use context_helper::build_all_paths() instead.', DEBUG_DEVELOPER);
+    context_helper::build_all_paths($force);
+}
+
+/**
+ * Rebuild all related context depth and path caches.
+ *
+ * @see context::reset_paths()
+ * @deprecated since 2.2
+ * @param array $fixcontexts array of contexts, strongtyped
+ * @return void
+ */
+function rebuild_contexts(array $fixcontexts) {
+    debugging('rebuild_contexts() is deprecated, please use $context->reset_paths(true) instead.', DEBUG_DEVELOPER);
+    foreach ($fixcontexts as $fixcontext) {
+        $fixcontext->reset_paths(false);
+    }
+    context_helper::build_all_paths(false);
+}
+
+/**
+ * Preloads all contexts relating to a course: course, modules. Block contexts
+ * 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 since Moodle 2.2
+ * @see context_helper::preload_course()
+ * @param int $courseid Course ID
+ * @return void
+ */
+function preload_course_contexts($courseid) {
+    debugging('preload_course_contexts() is deprecated, please use context_helper::preload_course() instead.', DEBUG_DEVELOPER);
+    context_helper::preload_course($courseid);
+}
+
+/**
+ * Update the path field of the context and all dep. subcontexts that follow
+ *
+ * Update the path field of the context and
+ * all the dependent subcontexts that follow
+ * the move.
+ *
+ * The most important thing here is to be as
+ * DB efficient as possible. This op can have a
+ * massive impact in the DB.
+ *
+ * @deprecated since Moodle 2.2
+ * @see context::update_moved()
+ * @param context $context context obj
+ * @param context $newparent new parent obj
+ * @return void
+ */
+function context_moved(context $context, context $newparent) {
+    debugging('context_moved() is deprecated, please use context::update_moved() instead.', DEBUG_DEVELOPER);
+    $context->update_moved($newparent);
+}
+
+/**
+ * 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 since 2.2
+ * @see context_helper::preload_from_record()
+ * @param stdClass $rec
+ * @return void (modifies $rec)
+ */
+function context_instance_preload(stdClass $rec) {
+    debugging('context_instance_preload() is deprecated, please use context_helper::preload_from_record() instead.', DEBUG_DEVELOPER);
+    context_helper::preload_from_record($rec);
+}
+
+/**
+ * Returns context level name
+ *
+ * @deprecated since 2.2
+ * @see context_helper::get_level_name()
+ * @param integer $contextlevel $context->context level. One of the CONTEXT_... constants.
+ * @return string the name for this type of context.
+ */
+function get_contextlevel_name($contextlevel) {
+    debugging('get_contextlevel_name() is deprecated, please use context_helper::get_level_name() instead.', DEBUG_DEVELOPER);
+    return context_helper::get_level_name($contextlevel);
+}
+
+/**
+ * Prints human readable context identifier.
+ *
+ * @deprecated since 2.2
+ * @see context::get_context_name()
+ * @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.
+ * @param boolean $short whether to user the short name of the thing. Only applies
+ *      to course contexts
+ * @return string the human readable context name.
+ */
+function print_context_name(context $context, $withprefix = true, $short = false) {
+    debugging('print_context_name() is deprecated, please use $context->get_context_name() instead.', DEBUG_DEVELOPER);
+    return $context->get_context_name($withprefix, $short);
+}
index 63f2470..4ac7472 100644 (file)
@@ -140,7 +140,8 @@ class mssql_native_moodle_database extends moodle_database {
         $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
 
         $dbhost = $this->dbhost;
-        if (isset($dboptions['dbport'])) {
+        // Zero shouldn't be used as a port number so doing a check with empty() should be fine.
+        if (!empty($dboptions['dbport'])) {
             if (stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin')) {
                 $dbhost .= ','.$dboptions['dbport'];
             } else {
index 9616cd9..8487e9c 100644 (file)
@@ -45,5 +45,82 @@ function xmldb_editor_tinymce_upgrade($oldversion) {
     // Put any upgrade step following this.
 
 
+    // Moodle v2.6.0 release upgrade line.
+    // Put any upgrade step following this.
+
+    if ($oldversion < 2013061400) {
+        // Reset redesigned editor toolbar setting.
+        $oldorder = "fontselect,fontsizeselect,formatselect,|,undo,redo,|,search,replace,|,fullscreen
+
+bold,italic,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,cleanup,removeformat,pastetext,pasteword,|,forecolor,backcolor,|,ltr,rtl
+
+bullist,numlist,outdent,indent,|,link,unlink,|,image,nonbreaking,charmap,table,|,code";
+
+        $neworder = "formatselect,bold,italic,|,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+        $currentorder = get_config('editor_tinymce', 'customtoolbar');
+        if ($currentorder == $oldorder) {
+            unset_config('customtoolbar', 'editor_tinymce');
+            set_config('customtoolbar', $neworder, 'editor_tinymce');
+        }
+        upgrade_plugin_savepoint(true, 2013061400, 'editor', 'tinymce');
+    }
+
+    if ($oldversion < 2013070500) {
+        // Insert wrap plugin to nicely wrap the toolbars on small screens.
+        $oldorder = "formatselect,bold,italic,|,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+
+        $neworder = "formatselect,bold,italic,wrap,bullist,numlist,|,link,unlink,|,image
+
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,wrap,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+
+fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+        $currentorder = get_config('editor_tinymce', 'customtoolbar');
+        if ($currentorder == $oldorder) {
+            unset_config('customtoolbar', 'editor_tinymce');
+            set_config('customtoolbar', $neworder, 'editor_tinymce');
+        } else {
+            // Simple auto conversion algorithm.
+            $toolbars = explode("\n", $oldorder);
+            $newtoolbars = array();
+            foreach ($toolbars as $toolbar) {
+                $sepcount = substr_count($toolbar, '|');
+
+                if ($sepcount > 0) {
+                    // We assume the middle separator (rounding down).
+                    $divisionindex = round($sepcount / 2, 0, PHP_ROUND_HALF_DOWN);
+
+                    $buttons = explode(',', $toolbar);
+                    $index = 0;
+                    foreach ($buttons as $key => $button) {
+                        if ($button === "|") {
+                            if ($index == $divisionindex) {
+                                $buttons[$key] = 'wrap';
+                                break;
+                            } else {
+                                $index += 1;
+                            }
+                        }
+                    }
+                    $toolbar = implode(',', $buttons);
+                }
+                array_push($newtoolbars, $toolbar);
+            }
+            $neworder = implode("\n", $newtoolbars);
+
+            // Set the new config.
+            unset_config('customtoolbar', 'editor_tinymce');
+            set_config('customtoolbar', $neworder, 'editor_tinymce');
+        }
+        upgrade_plugin_savepoint(true, 2013070500, 'editor', 'tinymce');
+    }
+
     return true;
 }
index f94de09..9e17c83 100644 (file)
@@ -30,7 +30,7 @@ $string['availablebuttons'] = 'Available buttons';
 $string['customconfig'] = 'Custom configuration';
 $string['customconfig_desc'] = 'Custom advanced TinyMCE configuration in JSON format, for example: {"option1" : "value2", "option2" : "value2"}. Any options specified here override standard and plugin settings.';
 $string['customtoolbar'] = 'Editor toolbar';
-$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.';
+$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.<br />The first row will always be shown, where as the visibility of second and third toolbars can be toggled';
 $string['fontselectlist'] = 'Available fonts list';
 $string['pluginname'] = 'TinyMCE HTML editor';
 $string['settings'] = 'General settings';
index 3f03950..ac912e7 100644 (file)
@@ -52,6 +52,9 @@ class tinymce_texteditor extends texteditor {
         if (check_browser_version('Safari iOS', 534)) {
             return true;
         }
+        if (check_browser_version('WebKit', 534)) {
+            return true;
+        }
 
         return false;
     }
index 048b1f5..83141fe 100644 (file)
@@ -37,14 +37,14 @@ class tinymce_moodlemedia extends editor_tinymce_plugin {
             }
         }
 
-        // Add button after emoticon button in advancedbuttons3.
-        $added = $this->add_button_after($params, 3, 'moodlemedia', 'moodleemoticon', false);
+        // Add button after emoticon button in advancedbuttons1.
+        $added = $this->add_button_after($params, 1, 'moodlemedia', 'moodleemoticon', false);
 
         // Note: We know that the emoticon button has already been added, if it
         // exists, because I set the sort order higher for this. So, if no
         // emoticon, add after 'image'.
         if (!$added) {
-            $this->add_button_after($params, 3, 'moodlemedia', 'image');
+            $this->add_button_after($params, 1, 'moodlemedia', 'image');
         }
 
         // Add JS file, which uses default name.
index fedb3cc..b400f81 100644 (file)
@@ -30,8 +30,8 @@ class tinymce_moodlenolink extends editor_tinymce_plugin {
     protected function update_init_params(array &$params, context $context,
             array $options = null) {
 
-        // Add button after 'unlink' in advancedbuttons3.
-        $this->add_button_after($params, 3, 'moodlenolink', 'unlink');
+        // Add button after 'unlink' in advancedbuttons1.
+        $this->add_button_after($params, 1, 'moodlenolink', 'unlink');
 
         // Add JS file, which uses default name.
         $this->add_js_plugin($params);
diff --git a/lib/editor/tinymce/plugins/pdw/lang/en/tinymce_pdw.php b/lib/editor/tinymce/plugins/pdw/lang/en/tinymce_pdw.php
new file mode 100644 (file)
index 0000000..d057f79
--- /dev/null
@@ -0,0 +1,28 @@
+<?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/>.
+
+/**
+ * Strings for 'Toolbar Toggle' plugin.
+ *
+ * @package   tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['pluginname'] = 'Toolbar Toggle';
+
+/* All lang strings used from TinyMCE JavaScript code must be named 'pluginname:stringname', no need to create langs/en_dlg.js */
+$string['pdw:desc'] = 'Toolbar Toggle';
diff --git a/lib/editor/tinymce/plugins/pdw/lib.php b/lib/editor/tinymce/plugins/pdw/lib.php
new file mode 100644 (file)
index 0000000..dbac6cc
--- /dev/null
@@ -0,0 +1,39 @@
+<?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/>.
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Plugin for Moodle 'Toolbar Toggle' button.
+ *
+ * @package   tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tinymce_pdw extends editor_tinymce_plugin {
+    protected function update_init_params(array &$params, context $context,
+            array $options = null) {
+
+        // Add button before 'undo' in advancedbuttons1.
+        $this->add_button_before($params, 1, ' | ', '');
+        $this->add_button_before($params, 1, 'pdw_toggle', '');
+        $params['pdw_toggle_on'] = 1;
+        $params['pdw_toggle_toolbars'] = '2,3';
+
+        // Add JS file, which uses default name.
+        $this->add_js_plugin($params);
+    }
+}
diff --git a/lib/editor/tinymce/plugins/pdw/pix/icon.gif b/lib/editor/tinymce/plugins/pdw/pix/icon.gif
new file mode 100644 (file)
index 0000000..fb828f8
Binary files /dev/null and b/lib/editor/tinymce/plugins/pdw/pix/icon.gif differ
diff --git a/lib/editor/tinymce/plugins/pdw/readme_moodle.txt b/lib/editor/tinymce/plugins/pdw/readme_moodle.txt
new file mode 100644 (file)
index 0000000..0f510ff
--- /dev/null
@@ -0,0 +1,15 @@
+Description of PDW Toolbar Toggle integration in Moodle
+=========================================================================================
+
+Copyright: Guido Neele (www.neele.name)
+License: MIT
+
+Moodle maintainer: Jason Fowler (phalacee)
+
+=========================================================================================
+Upgrade procedure:
+1/ extract standard PDW package into lib/editor/tinymce/plugins/pdw/tinymce/
+2/ bump up version.php
+3/ update lib/thirdpartylibs.xml
+4/ reimplement patch in MDL-23646
+5/ reminify the js manually (I used uglifyjs)
diff --git a/lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js b/lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js
new file mode 100644 (file)
index 0000000..3646b35
--- /dev/null
@@ -0,0 +1,25 @@
+/**\r
+ * PDW Toggle Toolbars v1.2\r
+ * Url: http://www.neele.name\r
+ * Author: Guido Neele\r
+ * \r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ * \r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ * Based on TinyMCE Wordpress plugin (Kitchen Sink)\r
+ */\r
+!function(){var DOM=tinymce.DOM;tinymce.PluginManager.requireLangPack("pdw");tinymce.create("tinymce.plugins.pdw",{init:function(ed,url){var t=this,tbIds=new Array,toolbars=new Array,i;toolbars=ed.settings.pdw_toggle_toolbars.split(",");for(i=0;i<toolbars.length;i++){tbIds[i]=ed.getParam("","toolbar"+toolbars[i].replace(" ",""))}ed.addCommand("mcePDWToggleToolbars",function(){var cm=ed.controlManager,id,j,Cookie=tinymce.util.Cookie,Toggle_PDW,Toggle=Cookie.getHash("TinyMCE_toggle")||new Object;for(j=0;j<tbIds.length;j++){obj=ed.controlManager.get(tbIds[j]);if(typeof obj=="undefined"){continue}id=obj.id;if(DOM.isHidden(id)){Toggle_PDW=0;var e=document.getElementById(id);if(e){e.style.display="table";t._resizeIframe(ed,tbIds[j],-26)}}else{Toggle_PDW=1;var e=document.getElementById(id);if(e){e.style.display="none"}t._resizeIframe(ed,tbIds[j],26)}}cm.setActive("pdw_toggle",Toggle_PDW);ed.settings.pdw_toggle_on=Toggle_PDW;Toggle[ed.id]=Toggle_PDW;Cookie.setHash("TinyMCE_toggle",Toggle)});ed.addButton("pdw_toggle",{title:ed.getLang("pdw.desc",0),cmd:"mcePDWToggleToolbars",image:url+"/img/toolbars.gif"});ed.onPostRender.add(function(){var toggle=tinymce.util.Cookie.getHash("TinyMCE_toggle")||new Object;var run=false;if(toggle[ed.id]==null){run=ed.settings.pdw_toggle_on==1?true:false}else if(toggle[ed.id]==1){run=true}if(run){var cm=ed.controlManager,tdId,id;for(i=0;i<toolbars.length;i++){tbId=ed.getParam("","toolbar"+toolbars[i].replace(" ",""));id=ed.controlManager.get(tbId).id;cm.setActive("pdw_toggle",1);DOM.hide(id);t._resizeIframe(ed,tbId,26)}}})},_resizeIframe:function(ed,tb_id,dy){var ifr=ed.getContentAreaContainer().firstChild;DOM.setStyle(ifr,"height",DOM.getSize(ifr).h+dy);ed.theme.deltaHeight+=dy},getInfo:function(){return{longname:"PDW Toggle Toolbars",author:"Guido Neele",authorurl:"http://www.neele.name/",infourl:"http://www.neele.name/pdw_toggle_toolbars",version:"1.2"}}});tinymce.PluginManager.add("pdw",tinymce.plugins.pdw)}();
\ No newline at end of file
diff --git a/lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin_src.js b/lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin_src.js
new file mode 100644 (file)
index 0000000..6a1c707
--- /dev/null
@@ -0,0 +1,182 @@
+/**\r
+ * PDW Toggle Toolbars v1.2\r
+ * Url: http://www.neele.name\r
+ * Author: Guido Neele\r
+ * \r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ * \r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ * Based on TinyMCE Wordpress plugin (Kitchen Sink)\r
+ * \r
+ * Changes V1.1.1 --> V1.2\r
+ * \r
+ * heeae made some modifications and posted his work on Sourceforge. I thought the cookie support \r
+ * was really handy so I updated the script.\r
+ * http://sourceforge.net/tracker/?func=detail&atid=738747&aid=2904683&group_id=103281\r
+ *\r
+ * 1. Added cookie support.\r
+ * 2. Some optimization\r
+ * 3. Bug fix of fire ifr.clientHeight in FF 3 ( to DOM.getStyles)\r
+ *\r
+ * Thanks heeae!\r
+ * \r
+ * Changes V1.1 --> V1.1.1\r
+ *\r
+ * Bugfix for Firefox 3.6. Caused error while loading script.\r
+ *\r
+ * Added lines 72 - 76:\r
+ *\r
+ * obj = ed.controlManager.get(tbIds[j]);\r
+ * if(typeof obj =="undefined") {\r
+ *             continue;\r
+ * }\r
+ * id = obj.id;\r
+ *\r
+ * instead of:\r
+ *\r
+ * try {\r
+ *             id = ed.controlManager.get(tbIds[j]).id;\r
+ * }\r
+ * catch(e) {\r
+ * //if(typeof id == "undefined") continue;\r
+ *             continue;\r
+ * }\r
+ *\r
+ * Thanks Anton for fixing this bug\r
+ * \r
+ */\r
+\r
+(function() {\r
+       var DOM = tinymce.DOM;\r
+       tinymce.PluginManager.requireLangPack('pdw');\r
+       \r
+       tinymce.create('tinymce.plugins.pdw', {\r
+               /**\r
+                * Initializes the plugin, this will be executed after the plugin has been created.\r
+                * This call is done before the editor instance has finished it's initialization so use the onInit event\r
+                * of the editor instance to intercept that event.\r
+                *\r
+                * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.\r
+                * @param {string} url Absolute URL to where the plugin is located.\r
+                */\r
+               init : function(ed, url) {\r
+                       var t = this, tbIds = new Array(), toolbars = new Array(), i;\r
+                       \r
+                       // Split toolbars\r
+                       toolbars = (ed.settings.pdw_toggle_toolbars).split(',');\r
+                       \r
+                       for(i = 0; i < toolbars.length; i++){\r
+                               tbIds[i] = ed.getParam('', 'toolbar' + (toolbars[i]).replace(' ',''));\r
+                       }\r
+                       \r
+                       // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');\r
+                       ed.addCommand('mcePDWToggleToolbars', function() {\r
+                       \r
+                               var cm = ed.controlManager, id, j, Cookie = tinymce.util.Cookie, Toggle_PDW, Toggle = Cookie.getHash("TinyMCE_toggle") || new Object();\r
+                               for(j = 0; j < tbIds.length; j++){\r
+                                       \r
+                                       obj = ed.controlManager.get(tbIds[j]);\r
+                    if(typeof obj =="undefined") {\r
+                        continue;\r
+                    }\r
+                    id = obj.id;\r
+                                       \r
+                                       if (DOM.isHidden(id)) {\r
+                                               Toggle_PDW = 0;\r
+                        var e = document.getElementById(id);\r
+                        if (e) {\r
+                            e.style.display = 'table';\r
+                            t._resizeIframe(ed, tbIds[j], -26);\r
+                        }\r
+                                               \r
+                                       } else {\r
+                                               Toggle_PDW = 1;\r
+                        var e = document.getElementById(id);\r
+                        if (e) {\r
+                            e.style.display = 'none';\r
+                        }\r
+                                               t._resizeIframe(ed, tbIds[j], 26);\r
+                                       }\r
+                               }\r
+                               cm.setActive('pdw_toggle', Toggle_PDW);\r
+                               ed.settings.pdw_toggle_on = Toggle_PDW;\r
+                               Toggle[ed.id] = Toggle_PDW;\r
+                               Cookie.setHash("TinyMCE_toggle", Toggle);\r
+                       });\r
+                       \r
+                       // Register pdw_toggle button\r
+                       ed.addButton('pdw_toggle', {\r
+                               title : ed.getLang('pdw.desc', 0),\r
+                               cmd : 'mcePDWToggleToolbars',\r
+                               image : url + '/img/toolbars.gif'\r
+                       });\r
+                       \r
+                       ed.onPostRender.add(function(){\r
+                               var toggle = tinymce.util.Cookie.getHash("TinyMCE_toggle") || new Object();\r
+                               var run = false;\r
+                               \r
+                               // Check if value is stored in cookie\r
+                               if(toggle[ed.id] == null){\r
+                                       // No cookie so check if the setting pdw_toggle_on is set to 1 then hide toolbars and set button active\r
+                                       run = ed.settings.pdw_toggle_on == 1 ? true : false;\r
+                               } else if(toggle[ed.id] == 1){\r
+                                       run = true;\r
+                               }\r
+                       \r
+                               if (run) {\r
+\r
+                                       var cm = ed.controlManager, tdId, id;\r
+                                       \r
+                                       for(i = 0; i < toolbars.length; i++){\r
+                                               tbId = ed.getParam('', 'toolbar' + (toolbars[i]).replace(' ',''));\r
+                                               id = ed.controlManager.get(tbId).id;\r
+                                               cm.setActive('pdw_toggle', 1);\r
+                                               DOM.hide(id);\r
+                                               t._resizeIframe(ed, tbId, 26);\r
+                                       }\r
+                               }\r
+                       });\r
+               },\r
+               \r
+               // Resizes the iframe by a relative height value\r
+               _resizeIframe : function(ed, tb_id, dy) {\r
+                       var ifr = ed.getContentAreaContainer().firstChild;\r
+                       \r
+                       DOM.setStyle(ifr, 'height',DOM.getSize(ifr).h + dy); // Resize iframe\r
+                       ed.theme.deltaHeight += dy; // For resize cookie\r
+               },\r
+\r
+               /**\r
+                * Returns information about the plugin as a name/value array.\r
+                * The current keys are longname, author, authorurl, infourl and version.\r
+                *\r
+                * @return {Object} Name/value array containing information about the plugin.\r
+                */\r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'PDW Toggle Toolbars',\r
+                               author : 'Guido Neele',\r
+                               authorurl : 'http://www.neele.name/',\r
+                               infourl : 'http://www.neele.name/pdw_toggle_toolbars',\r
+                               version : "1.2"\r
+                       };\r
+               }\r
+       });\r
+\r
+       // Register plugin\r
+       tinymce.PluginManager.add('pdw', tinymce.plugins.pdw);\r
+})();\r
diff --git a/lib/editor/tinymce/plugins/pdw/tinymce/img/toolbars.gif b/lib/editor/tinymce/plugins/pdw/tinymce/img/toolbars.gif
new file mode 100644 (file)
index 0000000..dcb7066
Binary files /dev/null and b/lib/editor/tinymce/plugins/pdw/tinymce/img/toolbars.gif differ
diff --git a/lib/editor/tinymce/plugins/pdw/tinymce/langs/en.js b/lib/editor/tinymce/plugins/pdw/tinymce/langs/en.js
new file mode 100644 (file)
index 0000000..14271e5
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.pdw',{\r
+       desc : 'Show/hide toolbars'\r
+});\r
diff --git a/lib/editor/tinymce/plugins/pdw/tinymce/langs/nl.js b/lib/editor/tinymce/plugins/pdw/tinymce/langs/nl.js
new file mode 100644 (file)
index 0000000..2debf66
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('nl.pdw',{\r
+       desc : 'Toon/verberg werkbalken'\r
+});\r
diff --git a/lib/editor/tinymce/plugins/pdw/version.php b/lib/editor/tinymce/plugins/pdw/version.php
new file mode 100644 (file)
index 0000000..9f0021a
--- /dev/null
@@ -0,0 +1,32 @@
+<?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/>.
+
+/**
+ * TinyMCE image insert/edit plugin version details.
+ *
+ * @package   tinymce_pdw
+ * @copyright 2013 Jason Fowler
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// The current plugin version (Date: YYYYMMDDXX).
+$plugin->version   = 2013070500;
+// Required Moodle version.
+$plugin->requires  = 2013050100;
+// Full name of the plugin (used for diagnostics).
+$plugin->component = 'tinymce_pdw';
diff --git a/lib/editor/tinymce/plugins/wrap/lang/en/tinymce_wrap.php b/lib/editor/tinymce/plugins/wrap/lang/en/tinymce_wrap.php
new file mode 100644 (file)
index 0000000..eedf6d0
--- /dev/null
@@ -0,0 +1,28 @@
+<?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/>.
+
+/**
+ * Strings for 'wrap' plugin.
+ *
+ * @package   tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['pluginname'] = 'Wrap';
+
+/* All lang strings used from TinyMCE JavaScript code must be named 'pluginname:stringname', no need to create langs/en_dlg.js */
+$string['moodlewrap:desc'] = 'Wrap';
diff --git a/lib/editor/tinymce/plugins/wrap/lib.php b/lib/editor/tinymce/plugins/wrap/lib.php
new file mode 100644 (file)
index 0000000..91586fc
--- /dev/null
@@ -0,0 +1,36 @@
+<?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/>.
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Plugin for Moodle 'wrap' button.
+ *
+ * @package   tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tinymce_wrap extends editor_tinymce_plugin {
+    /** @var array list of buttons defined by this plugin */
+    protected $buttons = array('wrap');
+
+    protected function update_init_params(array &$params, context $context,
+            array $options = null) {
+
+        // Add JS file, which uses default name.
+        $this->add_js_plugin($params);
+    }
+}
diff --git a/lib/editor/tinymce/plugins/wrap/tinymce/editor_plugin.js b/lib/editor/tinymce/plugins/wrap/tinymce/editor_plugin.js
new file mode 100644 (file)
index 0000000..af3d992
--- /dev/null
@@ -0,0 +1,88 @@
+// 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/>.
+
+/**
+ * Plugin for Moodle 'wrap' button.
+ *
+ * @package   tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+(function() {
+    tinymce.create('tinymce.ui.Wrap:tinymce.ui.Control', {
+        /**
+         * Constructor for the tinymce.Wrap class.
+         */
+        Wrap : function(id, s) {
+            this.parent(id, s);
+            this.groupEndClass = 'mceToolbarEnd';
+            this.groupStartClass = 'mceToolbarStart';
+            this.wrapClass = 'mceWrap';
+            this.setDisabled(true);
+        },
+
+        /**
+         * Returns the HTML for this control. This control actually ends the current td
+         * container and opens a new one so that the containers can be styled with CSS
+         * to wrap at certain screen widths.
+         * @return string HTML
+         */
+        renderHTML : function() {
+            var separator = tinymce.DOM.createHTML('span', {role : 'separator',
+                                                            'aria-orientation' : 'vertical',
+                                                            tabindex : '-1'});
+            return '</td>' +
+                   '<td style="position: relative" class="' + this.groupEndClass + '">' + separator + '</td>' +
+                   '<td style="position: relative" class="' + this.groupStartClass + ' ' + this.wrapClass + '">' + separator + '</td>';
+        }
+
+
+    });
+
+    tinymce.create('tinymce.plugins.wrapPlugin', {
+        /**
+         * Returns a new instance of this control, in this case a custom Wrap class.
+         *
+         * @param string name - The name of the control to create. Return false if we can't create this control type.
+         * @param tinymce.ControlManager cc - Tinymce control manager class.
+         * @return mixed - false or the new control
+         */
+        createControl : function(name, cc) {
+            if (name === "wrap") {
+                return new tinymce.ui.Wrap();
+            }
+            return false;
+        },
+
+        /**
+         * Returns information about the plugin as a name/value array.
+         * The current keys are longname, author, authorurl, infourl and version.
+         *
+         * @return {Object} Name/value array containing information about the plugin.
+         */
+        getInfo : function() {
+            return {
+                longname : 'wrap plugin',
+                author : 'Damyon Wiese',
+                authorurl : 'http://moodle.com/hq',
+                infourl : 'http://docs.moodle.org/en/TinyMCE',
+                version : "1.0"
+            };
+        }
+    });
+
+    // Register plugin.
+    tinymce.PluginManager.add('wrap', tinymce.plugins.wrapPlugin);
+})();
diff --git a/lib/editor/tinymce/plugins/wrap/version.php b/lib/editor/tinymce/plugins/wrap/version.php
new file mode 100644 (file)
index 0000000..e1eb2a1
--- /dev/null
@@ -0,0 +1,32 @@
+<?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/>.
+
+/**
+ * TinyMCE toolbar wrapping break
+ *
+ * @package   tinymce_wrap
+ * @copyright 2013 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// The current plugin version (Date: YYYYMMDDXX).
+$plugin->version   = 2013061900;
+// Required Moodle version.
+$plugin->requires  = 2013050100;
+// Full name of the plugin (used for diagnostics).
+$plugin->component = 'tinymce_wrap';
index 6fbe267..9865fdf 100644 (file)
@@ -31,11 +31,11 @@ if ($ADMIN->fulltree) {
     require_once(__DIR__.'/adminlib.php');
     $settings->add(new tiynce_subplugins_settings());
     $settings->add(new admin_setting_heading('tinymcegeneralheader', new lang_string('settings'), ''));
-    $default = "fontselect,fontsizeselect,formatselect,|,undo,redo,|,search,replace,|,fullscreen
+    $default = "formatselect,bold,italic,wrap,bullist,numlist,|,link,unlink,|,image
 
-bold,italic,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,|,cleanup,removeformat,pastetext,pasteword,|,forecolor,backcolor,|,ltr,rtl
+undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,wrap,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
 
-bullist,numlist,outdent,indent,|,link,unlink,|,image,nonbreaking,charmap,table,|,code";
+fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
     $settings->add(new admin_setting_configtextarea('editor_tinymce/customtoolbar',
         get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce', 'http://www.tinymce.com/wiki.php/Buttons/controls'), $default, PARAM_RAW, 100, 8));
     $settings->add(new admin_setting_configtextarea('editor_tinymce/fontselectlist',
index 51d8a92..b0708bb 100644 (file)
     color: red;
     cursor: pointer;
 }
-.mform .felement.feditor .mceStatusbar,
-.mform .felement.feditor iframe {
-    min-width: 35em;
+
+@media (max-width: 480px) {
+    .mceToolbar td {
+        float: left;
+        display: inline-block;
+    }
+    .mceToolbar .mceWrap {
+        clear: left;
+    }
+
+    .o2k7Skin tr.mceLast .mceToolbar tr td.mceWrap,
+    .o2k7Skin tr.mceFirst .mceToolbar tr td.mceWrap {
+        margin-left: -3px;
+    }
+    .dir-rtl .o2k7Skin tr.mceLast .mceToolbar tr td.mceWrap,
+    .dir-rtl .o2k7Skin tr.mceFirst .mceToolbar tr td.mceWrap {
+        margin-left: 0px;
+    }
 }
index 5696839..a8b2c15 100644 (file)
@@ -2,6 +2,12 @@ This files describes API changes in /lib/editor/tinymce/* - TinyMCE editor,
 information provided here is intended especially for developers.
 
 
+=== 2.6 ===
+
+* added a new plugin to toggle the 2nd and 3rd toolbars
+* added a new plugin to wrap the toolbars on small screens.
+This plugin will be automatically added to existing toolbars by replacing the middle occurrence of | with "wrap".
+
 === 2.5 ===
 
 * update filter related code to use short filter names instead
index 239ea28..d5e0240 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2013050100;        // The current plugin version (Date: YYYYMMDDXX)
+$plugin->version   = 2013070500;        // The current plugin version (Date: YYYYMMDDXX)
 $plugin->requires  = 2013050100;        // Requires this Moodle version
 $plugin->component = 'editor_tinymce';  // Full name of the plugin (used for diagnostics)
 $plugin->release   = '3.5.8';           // This is NOT a directory name, see lib.php if you need to know where is the editor code!
index 6247ecd..7e70bff 100644 (file)
@@ -596,7 +596,7 @@ function enrol_get_my_courses($fields = NULL, $sort = 'visible DESC,sortorder AS
 
     // preload contexts and check visibility
     foreach ($courses as $id=>$course) {
-        context_instance_preload($course);
+        context_helper::preload_from_record($course);
         if (!$course->visible) {
             if (!$context = context_course::instance($id, IGNORE_MISSING)) {
                 unset($courses[$id]);
@@ -692,7 +692,7 @@ function enrol_get_users_courses($userid, $onlyactive = false, $fields = NULL, $
     // preload contexts and check visibility
     if ($onlyactive) {
         foreach ($courses as $id=>$course) {
-            context_instance_preload($course);
+            context_helper::preload_from_record($course);
             if (!$course->visible) {
                 if (!$context = context_course::instance($id)) {
                     unset($courses[$id]);
index 9b92c5e..e6d868f 100644 (file)
@@ -345,7 +345,7 @@ class external_api {
         } else if ($rcontext->contextlevel > $context->contextlevel) {
             throw new restricted_context_exception();
         } else {
-            $parents = get_parent_contexts($context);
+            $parents = $context->get_parent_context_ids();
             if (!in_array($rcontext->id, $parents)) {
                 throw new restricted_context_exception();
             }
index 64fcc4b..84fd4e6 100644 (file)
@@ -472,13 +472,10 @@ class file_info_context_course extends file_info {
     /**
      * Returns parent file_info instance
      *
-     * @todo error checking if get_parent_contextid() returns false
      * @return file_info or null for root
      */
     public function get_parent() {
-        //TODO: error checking if get_parent_contextid() returns false
-        $pcid = get_parent_contextid($this->context);
-        $parent = context::instance_by_id($pcid, IGNORE_MISSING);
+        $parent = $this->context->get_parent_context();
         return $this->browser->get_file_info($parent);
     }
 }
index 02b1774..5b49526 100644 (file)
@@ -254,8 +254,7 @@ class file_info_context_coursecat extends file_info {
      * @return file_info|null fileinfo instance or null for root directory
      */
     public function get_parent() {
-        $cid = get_parent_contextid($this->context);
-        $parent = context::instance_by_id($cid, IGNORE_MISSING);
+        $parent = $this->context->get_parent_context();
         return $this->browser->get_file_info($parent);
     }
 }
index 9affb2b..5bd064d 100644 (file)
@@ -352,8 +352,7 @@ class file_info_context_module extends file_info {
      * @return file_info|null file_info or null for root
      */
     public function get_parent() {
-        $pcid = get_parent_contextid($this->context);
-        $parent = context::instance_by_id($pcid, IGNORE_MISSING);
+        $parent = $this->context->get_parent_context();
         return $this->browser->get_file_info($parent);
     }
 }
index c0bc249..4a91911 100644 (file)
@@ -1307,6 +1307,37 @@ abstract class moodleform {
             }
         }
     }
+
+    /**
+     * Used by tests to simulate submitted form data submission from the user.
+     *
+     * For form fields where no data is submitted the default for that field as set by set_data or setDefault will be passed to
+     * get_data.
+     *
+     * This method sets $_POST or $_GET and $_FILES with the data supplied. Our unit test code empties all these
+     * global arrays after each test.
+     *
+     * @param array  $simulatedsubmitteddata       An associative array of form values (same format as $_POST).
+     * @param array  $simulatedsubmittedfiles      An associative array of files uploaded (same format as $_FILES). Can be omitted.
+     * @param string $method                       'post' or 'get', defaults to 'post'.
+     * @param null   $formidentifier               the default is to use the class name for this class but you may need to provide
+     *                                              a different value here for some forms that are used more than once on the
+     *                                              same page.
+     */
+    public static function mock_submit($simulatedsubmitteddata, $simulatedsubmittedfiles = array(), $method = 'post',
+                                       $formidentifier = null) {
+        $_FILES = $simulatedsubmittedfiles;
+        if ($formidentifier === null) {
+            $formidentifier = get_called_class();
+        }
+        $simulatedsubmitteddata['_qf__'.$formidentifier] = 1;
+        $simulatedsubmitteddata['sesskey'] = sesskey();
+        if (strtolower($method) === 'get') {
+            $_GET = $simulatedsubmitteddata;
+        } else {
+            $_POST = $simulatedsubmitteddata;
+        }
+    }
 }
 
 /**
index 3ae134f..e95a2af 100644 (file)
@@ -839,7 +839,7 @@ function grade_get_letters($context=null) {
 
     $letters = array();
 
-    $contexts = get_parent_contexts($context);
+    $contexts = $context->get_parent_context_ids();
     array_unshift($contexts, $context->id);
 
     foreach ($contexts as $ctxid) {
index 194e08e..defa97d 100644 (file)
@@ -391,22 +391,6 @@ function message_set_default_message_preference($component, $messagename, $filep
     }
 }
 
-/**
- * This function has been deprecated please use {@link message_get_providers_for_user()} instead.
- *
- * Returns the active providers for the current user, based on capability
- *
- * @see message_get_providers_for_user()
- * @deprecated since 2.1
- * @todo Remove in 2.5 (MDL-34454)
- * @return array An array of message providers
- */
-function message_get_my_providers() {
-    global $USER;
-    debugging('message_get_my_providers is deprecated please update your code', DEBUG_DEVELOPER);
-    return message_get_providers_for_user($USER->id);
-}
-
 /**
  * Returns the active providers for the user specified, based on capability
  *
index f099328..1355b08 100644 (file)
@@ -275,7 +275,7 @@ class course_modinfo extends stdClass {
 
         // Load sectioncache field into memory as PHP object and check it's valid
         $sectioncache = unserialize($course->sectioncache);
-        if (!is_array($sectioncache) || empty($sectioncache)) {
+        if (!is_array($sectioncache)) {
             // hmm, something is wrong - let's fix it
             rebuild_course_cache($course->id);
             $course->sectioncache = $DB->get_field('course', 'sectioncache', array('id'=>$course->id));
@@ -288,7 +288,7 @@ class course_modinfo extends stdClass {
         }
 
         // If we haven't already preloaded contexts for the course, do it now
-        preload_course_contexts($course->id);
+        context_helper::preload_course($course->id);
 
         // Loop through each piece of module data, constructing it
         $modexists = array();
index 9acd467..593c964 100644 (file)
@@ -3558,7 +3558,7 @@ function ismoving($courseid) {
 /**
  * Returns a persons full name
  *
- * Given an object containing firstname and lastname
+ * Given an object containing all of the users name
  * values, this function returns a string with the
  * full name of the person.
  * The result may depend on system settings
@@ -3567,7 +3567,7 @@ function ismoving($courseid) {
  *
  * @global object
  * @global object
- * @param object $user A {@link $USER} object to get full name of
+ * @param object $user A {@link $USER} object to get full name of.
  * @param bool $override If true then the name will be first name followed by last name rather than adhering to fullnamedisplay setting.
  * @return string
  */
@@ -3591,21 +3591,114 @@ function fullname($user, $override=false) {
         $CFG->fullnamedisplay = $SESSION->fullnamedisplay;
     }
 
-    if (!isset($CFG->fullnamedisplay) or $CFG->fullnamedisplay === 'firstname lastname') {
-        return $user->firstname .' '. $user->lastname;
+    $template = null;
+    // If the fullnamedisplay setting is available, set the template to that.
+    if (isset($CFG->fullnamedisplay)) {
+        $template = $CFG->fullnamedisplay;
+    }
+    // If the template is empty, or set to language, or $override is set, return the language string.
+    if (empty($template) || $template == 'language' || $override) {
+        return get_string('fullnamedisplay', null, $user);
+    }
 
-    } else if ($CFG->fullnamedisplay == 'lastname firstname') {
-        return $user->lastname .' '. $user->firstname;
+    // Get all of the name fields.
+    $allnames = get_all_user_name_fields();
+    $requirednames = array();
+    // With each name, see if it is in the display name template, and add it to the required names array if it is.
+    foreach ($allnames as $allname) {
+        if (strpos($template, $allname) !== false) {
+            $requirednames[] = $allname;
+            // If the field is in the template, but not set in the user object, then notify the programmer that it needs to be fixed.
+            if (!array_key_exists($allname, $user)) {
+                debugging('You need to update your sql query to include additional name fields in the user object.', DEBUG_DEVELOPER);
+            }
+        }
+    }
 
-    } else if ($CFG->fullnamedisplay == 'firstname') {
-        if ($override) {
-            return get_string('fullnamedisplay', '', $user);
+    $displayname = $template;
+    // Switch in the actual data into the template.
+    foreach ($requirednames as $altname) {
+        if (isset($user->$altname)) {
+            // Using empty() on the below if statement causes breakages.
+            if ((string)$user->$altname == '') {
+                $displayname = str_replace($altname, 'EMPTY', $displayname);
+            } else {
+                $displayname = str_replace($altname, $user->$altname, $displayname);
+            }
         } else {
-            return $user->firstname;
+            $displayname = str_replace($altname, 'EMPTY', $displayname);
+        }
+    }
+    // Tidy up any misc. characters (Not perfect, but gets most characters).
+    // Don't remove the "u" at the end of the first expression unless you want garbled characters when combining hiragana or katakana and parenthesis.
+    $patterns = array();
+    // This regular expression replacement is to fix problems such as 'James () Kirk' Where 'Tiberius' (middlename) has not been filled in by a user.
+    // The special characters are Japanese brackets that are common enough to make special allowance for them (not covered by :punct:).
+    $patterns[] = '/[[:punct:]「」]*EMPTY[[:punct:]「」]*/u';
+    // This regular expression is to remove any double spaces in the display name.
+    $patterns[] = '/\s{2,}/';
+    foreach ($patterns as $pattern) {
+        $displayname = preg_replace($pattern, ' ', $displayname);
+    }
+
+    // Trimming $displayname will help the next check to ensure that we don't have a display name with spaces.
+    $displayname = trim($displayname);
+    if (empty($displayname)) {
+        // Going with just the first name if no alternate fields are filled out. May be changed later depending on what
+        // people in general feel is a good setting to fall back on.
+        $displayname = $user->firstname;
+    }
+    return $displayname;
+}
+
+/**
+ * A centralised location for the all name fields. Returns an array / sql string snippet.
+ *
+ * @param bool $returnsql True for an sql select field snippet.
+ * @param string $alias table alias to use in front of each field.
+ * @return array|string All name fields.
+ */
+function get_all_user_name_fields($returnsql = false, $alias = null) {
+    $alternatenames = array('firstnamephonetic',
+                            'lastnamephonetic',
+                            'middlename',
+                            'alternatename',
+                            'firstname',
+                            'lastname',);
+    if ($returnsql) {
+        if ($alias) {
+            foreach ($alternatenames as $key => $altname) {
+                $alternatenames[$key] = "$alias.$altname";
+            }
         }
+        $alternatenames = implode(',', $alternatenames);
     }
+    return $alternatenames;
+}
 
-    return get_string('fullnamedisplay', '', $user);
+/**
+ * Returns an array of values in order of occurance in a provided string.
+ * The key in the result is the character postion in the string.
+ *
+ * @param array $values Values to be found in the string format
+ * @param string $stringformat The string which may contain values being searched for.
+ * @return array An array of values in order according to placement in the string format.
+ */
+function order_in_string($values, $stringformat) {
+    $valuearray = array();
+    foreach ($values as $value) {
+        $pattern = "/$value\b/";
+        // Using preg_match as strpos() may match values that are similar e.g. firstname and firstnamephonetic.
+        if (preg_match($pattern, $stringformat)) {
+            $replacement = "thing";
+            // replace the value with something more unique to ensure we get the right position when using strpos().
+            $newformat = preg_replace($pattern, $replacement, $stringformat);
+            $position = strpos($newformat, $replacement);
+            $valuearray[$position] = $value;
+        }
+    }
+    ksort($valuearray);
+    return $valuearray;
 }
 
 /**
@@ -5137,7 +5230,7 @@ function reset_course_userdata($data) {
     $componentstr = get_string('roles');
 
     if (!empty($data->reset_roles_overrides)) {
-        $children = get_child_contexts($context);
+        $children = $context->get_child_contexts();
         foreach ($children as $child) {
             $DB->delete_records('role_capabilities', array('contextid'=>$child->id));
         }
@@ -5148,7 +5241,7 @@ function reset_course_userdata($data) {
     }
 
     if (!empty($data->reset_roles_local)) {
-        $children = get_child_contexts($context);
+        $children = $context->get_child_contexts();
         foreach ($children as $child) {
             role_unassign_all(array('contextid'=>$child->id));
         }
@@ -7216,6 +7309,11 @@ class core_string_manager implements string_manager {
         // and re-populate it again
         fulldelete($this->menucache);
         $this->get_list_of_translations(true);
+
+        // Lang packs use PHP files in dataroot, it is better to invalidate opcode caches.
+        if (function_exists('opcache_reset')) {
+            opcache_reset();
+        }
     }
 
     /**
index c691a83..258d273 100644 (file)
@@ -1445,7 +1445,7 @@ class global_navigation extends navigation_node {
                     if (!$this->can_add_more_courses_to_category($course->category)) {
                         continue;
                     }
-                    context_instance_preload($course);
+                    context_helper::preload_from_record($course);
                     if (!$course->visible && !is_role_switched($course->id) && !has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
                         continue;
                     }
@@ -1481,7 +1481,7 @@ class global_navigation extends navigation_node {
                         if (!$this->can_add_more_courses_to_category($course->category)) {
                             break;
                         }
-                        context_instance_preload($course);
+                        context_helper::preload_from_record($course);
                         if (!$course->visible && !is_role_switched($course->id) && !has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
                             continue;
                         }
@@ -1509,7 +1509,7 @@ class global_navigation extends navigation_node {
                     // Don't include the currentcourse in this nodelist - it's displayed in the Current course node
                     continue;
                 }
-                context_instance_preload($course);
+                context_helper::preload_from_record($course);
                 if (!$course->visible && !is_role_switched($course->id) && !has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
                     continue;
                 }
@@ -1725,7 +1725,7 @@ class global_navigation extends navigation_node {
         $categoryname = format_string($category->name, true, array('context' => $context));
         $categorynode = $parent->add($categoryname, $url, $nodetype, $categoryname, $category->id);
         if (empty($category->visible)) {
-            if (has_capability('moodle/category:viewhiddencategories', get_system_context())) {
+            if (has_capability('moodle/category:viewhiddencategories', context_system::instance())) {
                 $categorynode->hidden = true;
             } else {
                 $categorynode->display = false;
@@ -2484,7 +2484,7 @@ class global_navigation extends navigation_node {
         $coursenode->add('frontpageloaded', null, self::TYPE_CUSTOM, null, 'frontpageloaded')->display = false;
 
         //Participants
-        if (has_capability('moodle/course:viewparticipants',  get_system_context())) {
+        if (has_capability('moodle/course:viewparticipants',  context_system::instance())) {
             $coursenode->add(get_string('participants'), new moodle_url('/user/index.php?id='.$course->id), self::TYPE_CUSTOM, get_string('participants'), 'participants');
         }
 
@@ -3913,7 +3913,7 @@ class settings_navigation extends navigation_node {
         }
 
         $coursecontext = context_course::instance($course->id);   // Course context
-        $systemcontext   = get_system_context();
+        $systemcontext   = context_system::instance();
         $currentuser = ($USER->id == $userid);
 
         if ($currentuser) {
@@ -4059,7 +4059,7 @@ class settings_navigation extends navigation_node {
             $enablemanagetokens = true;
         } else if (!is_siteadmin($USER->id)
              && !empty($CFG->enablewebservices)
-             && has_capability('moodle/webservice:createtoken', get_system_context()) ) {
+             && has_capability('moodle/webservice:createtoken', context_system::instance()) ) {
             $enablemanagetokens = true;
         }
         // Security keys
@@ -4143,7 +4143,7 @@ class settings_navigation extends navigation_node {
     protected function load_block_settings() {
         global $CFG;
 
-        $blocknode = $this->add(print_context_name($this->context));
+        $blocknode = $this->add($this->context->get_context_name());
         $blocknode->force_open();
 
         // Assign local roles
@@ -4172,7 +4172,7 @@ class settings_navigation extends navigation_node {
     protected function load_category_settings() {
         global $CFG;
 
-        $categorynode = $this->add(print_context_name($this->context), null, null, null, 'categorysettings');
+        $categorynode = $this->add($this->context->get_context_name(), null, null, null, 'categorysettings');
         $categorynode->force_open();
         $onmanagepage = $this->page->url->compare(new moodle_url('/course/manage.php'), URL_MATCH_BASE);
 
index d309175..344d4df 100644 (file)
@@ -131,7 +131,8 @@ class user_picture implements renderable {
      * @var array List of mandatory fields in user record here. (do not include
      * TEXT columns because it would break SELECT DISTINCT in MSSQL and ORACLE)
      */
-    protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'imagealt', 'email');
+    protected static $fields = array('id', 'picture', 'firstname', 'lastname', 'firstnamephonetic', 'lastnamephonetic',
+            'middlename', 'alternatename', 'imagealt', 'email');
 
     /**
      * @var stdClass A user object with at least fields all columns specified
@@ -224,7 +225,6 @@ class user_picture implements renderable {
         if ($tableprefix) {
             $tableprefix .= '.';
         }
-        $fields = array();
         foreach (self::$fields as $field) {
             if ($field === 'id' and $idalias and $idalias !== 'id') {
                 $fields[$field] = "$tableprefix$field AS $idalias";
index 556a9df..fd29d8f 100644 (file)
@@ -819,7 +819,7 @@ class moodle_page {
         $summary = '';
         $summary .= 'General type: ' . $this->pagelayout . '. ';
         if (!during_initial_install()) {
-            $summary .= 'Context ' . print_context_name($this->_context) . ' (context id ' . $this->_context->id . '). ';
+            $summary .= 'Context ' . $this->context->get_context_name() . ' (context id ' . $this->_context->id . '). ';
         }
         $summary .= 'Page type ' . $this->pagetype .  '. ';
         if ($this->subpage) {
@@ -917,7 +917,8 @@ class moodle_page {
                 // fine - no change needed
             } else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) {
                 // hmm - not ideal, but it might produce too many warnings due to the design of require_login
-            } else if ($this->_context->contextlevel == CONTEXT_MODULE and $this->_context->id == get_parent_contextid($context)) {
+            } else if ($this->_context->contextlevel == CONTEXT_MODULE and ($parentcontext = $context->get_parent_context()) and
+                    $this->_context->id == $parentcontext->id) {
                 // hmm - most probably somebody did require_login() and after that set the block context
             } else {
                 // we do not want devs to do weird switching of context levels on the fly,
index ed38405..0593812 100644 (file)
@@ -31,6 +31,15 @@ error_reporting(E_ALL | E_STRICT);
 ini_set('display_errors', '1');
 ini_set('log_errors', '1');
 
+// Make sure OPcache does not strip comments, we need them in phpunit!
+if (ini_get('opcache.enable') and strtolower(ini_get('opcache.enable')) !== 'off') {
+    if (!ini_get('opcache.save_comments') or strtolower(ini_get('opcache.save_comments')) === 'off') {
+        ini_set('opcache.enable', 0);
+    } else {
+        ini_set('opcache.load_comments', 1);
+    }
+}
+
 require_once(__DIR__.'/bootstraplib.php');
 require_once(__DIR__.'/../testing/lib.php');
 require_once(__DIR__.'/classes/autoloader.php');
index 55654ae..7e37fde 100644 (file)
@@ -146,7 +146,8 @@ class phpunit_autoloader implements PHPUnit_Runner_TestSuiteLoader {
             );
         }
 
-        return $class;
+        $classname = reset($candidates);
+        return new ReflectionClass($classname);
     }
 
     public function reload(ReflectionClass $aClass) {
index 97c7681..85cdaed 100644 (file)
@@ -160,6 +160,10 @@ class phpunit_util extends testing_util {
         $_SERVER = self::get_global_backup('_SERVER');
         $CFG = self::get_global_backup('CFG');
         $SITE = self::get_global_backup('SITE');
+        $_GET = array();
+        $_POST = array();
+        $_FILES = array();
+        $_REQUEST = array();
         $COURSE = $SITE;
 
         // reinitialise following globals
index 60e058c..61f5a30 100644 (file)
@@ -219,6 +219,28 @@ class core_phpunit_advanced_testcase extends advanced_testcase {
         $this->assertTrue(isset($CFG->admin));
         $this->assertEquals(1, $CFG->rolesactive);
 
+        // _GET change.
+        $_GET['__somethingthatwillnotnormallybepresent__'] = 'yy';
+        phpunit_util::reset_all_data(true);
+
+        $this->assertEquals(array(), $_GET);
+
+
+        // _POST change.
+        $_POST['__somethingthatwillnotnormallybepresent2__'] = 'yy';
+        phpunit_util::reset_all_data(true);
+        $this->assertEquals(array(), $_POST);
+
+        // _FILES change.
+        $_FILES['__somethingthatwillnotnormallybepresent3__'] = 'yy';
+        phpunit_util::reset_all_data(true);
+        $this->assertEquals(array(), $_FILES);
+
+        // _REQUEST change.
+        $_REQUEST['__somethingthatwillnotnormallybepresent4__'] = 'yy';
+        phpunit_util::reset_all_data(true);
+        $this->assertEquals(array(), $_REQUEST);
+
         //silent changes
         $_SERVER['xx'] = 'yy';
         phpunit_util::reset_all_data(true);
index 7a1192f..1706683 100644 (file)
@@ -3436,10 +3436,13 @@ class plugininfo_mod extends plugininfo_base {
             return '';
         }
 
-        $sql = "SELECT COUNT(course)
-                  FROM {course_modules}
-                 WHERE module = :mid
-              GROUP BY course";
+        $sql = "SELECT COUNT('x')
+                  FROM (
+                    SELECT course
+                      FROM {course_modules}
+                     WHERE module = :mid
+                  GROUP BY course
+                  ) c";
         $courses = $DB->count_records_sql($sql, array('mid'=>$module->id));
 
         return '<p>'.get_string('uninstallextraconfirmmod', 'core_plugin', array('instances'=>$count, 'courses'=>$courses)).'</p>';
index f1c77be..71734e5 100644 (file)
@@ -441,9 +441,14 @@ function question_delete_course_category($category, $newcategory, $feedback=true
                     $questionids = $DB->get_records_menu('question',
                             array('category'=>$category->id), '', 'id, 1');
                     if (!empty($questionids)) {
+                        $parentcontextid = false;
+                        $parentcontext = $context->get_parent_context();
+                        if ($parentcontext) {
+                            $parentcontextid = $parentcontext->id;
+                        }
                         if (!$rescueqcategory = question_save_from_deletion(
-                                array_keys($questionids), get_parent_contextid($context),
-                                print_context_name($context), $rescueqcategory)) {