Merge branch 'MDL-29527' of git://git.luns.net.uk/moodle
authorAparup Banerjee <aparup@moodle.com>
Mon, 24 Oct 2011 07:37:14 +0000 (15:37 +0800)
committerAparup Banerjee <aparup@moodle.com>
Mon, 24 Oct 2011 07:37:14 +0000 (15:37 +0800)
471 files changed:
admin/environment.xml
admin/report/questioninstances/index.php
admin/roles/usersroles.php
admin/settings/appearance.php
admin/settings/development.php
admin/tool/capability/index.php
admin/tool/unittest/simpletestlib.php
auth/shibboleth/index.php
auth/upgrade.txt [new file with mode: 0644]
blog/edit.php
blog/edit_form.php
blog/locallib.php
cohort/index.php
cohort/lib.php
course/category.php
course/lib.php
course/modedit.php
course/moodleform_mod.php
course/report/completion/index.php
course/report/progress/index.php
course/simpletest/testcourselib.php
enrol/cohort/ajax.php
enrol/cohort/lang/en/enrol_cohort.php
enrol/cohort/lib.php
enrol/cohort/locallib.php
enrol/cohort/yui/quickenrolment/assets/skins/sam/quickenrolment.css
enrol/cohort/yui/quickenrolment/quickenrolment.js
enrol/guest/lib.php
enrol/paypal/return.php
enrol/upgrade.txt [new file with mode: 0644]
grade/lib.php
install/lang/ru/install.php
lang/en/admin.php
lang/en/cohort.php
lang/en/condition.php
lang/en/debug.php
lang/en/webservice.php
lib/accesslib.php
lib/adminlib.php
lib/componentlib.class.php
lib/conditionlib.php
lib/datalib.php
lib/db/install.php
lib/db/upgrade.php
lib/deprecatedlib.php
lib/dml/simpletest/testdml.php
lib/editor/tinymce/lib.php
lib/editor/tinymce/readme_moodle.txt
lib/editor/tinymce/tiny_mce/3.4.5/plugins/layer/editor_plugin.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/editor_plugin.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/editor_plugin.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_jquery.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_prototype.js [deleted file]
lib/editor/tinymce/tiny_mce/3.4.6/jquery.tinymce.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/jquery.tinymce.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/langs/en.js with 98% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/license.txt [moved from lib/editor/tinymce/tiny_mce/3.4.5/license.txt with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/css/advhr.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/css/advhr.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/js/rule.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/js/rule.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advhr/rule.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advhr/rule.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/css/advimage.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/css/advimage.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/image.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/image.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/img/sample.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/img/sample.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/js/image.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/js/image.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advimage/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advimage/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/css/advlink.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/css/advlink.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/js/advlink.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/js/advlink.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlink/link.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlink/link.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlist/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlist/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/advlist/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/advlist/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autolink/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autolink/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autolink/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autolink/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autoresize/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autoresize/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autoresize/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autoresize/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autosave/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autosave/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autosave/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autosave/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/autosave/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/autosave/langs/en.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/bbcode/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/bbcode/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/bbcode/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/bbcode/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/contextmenu/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/contextmenu/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/contextmenu/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/contextmenu/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/directionality/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/directionality/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/directionality/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/directionality/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/dragmath.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/dragmath.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/img/dragmath.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/img/dragmath.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/js/dragmath.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/js/dragmath.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/dragmath/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/dragmath/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/emotions.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/emotions.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-cool.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-cool.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-cry.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-cry.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-embarassed.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-embarassed.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-foot-in-mouth.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-foot-in-mouth.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-frown.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-frown.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-innocent.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-innocent.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-kiss.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-kiss.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-laughing.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-laughing.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-money-mouth.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-money-mouth.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-sealed.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-sealed.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-smile.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-smile.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-surprised.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-surprised.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-tongue-out.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-tongue-out.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-undecided.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-undecided.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-wink.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-wink.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/img/smiley-yell.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/img/smiley-yell.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/js/emotions.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/js/emotions.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/emotions/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/emotions/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/dialog.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/dialog.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/img/example.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/img/example.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/js/dialog.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/js/dialog.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/langs/en.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example_dependency/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example_dependency/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/example_dependency/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/example_dependency/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/css/fullpage.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/css/fullpage.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/fullpage.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/fullpage.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/js/fullpage.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/js/fullpage.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullpage/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullpage/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullscreen/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullscreen/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullscreen/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullscreen/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/fullscreen/fullscreen.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/fullscreen/fullscreen.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/iespell/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/iespell/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/iespell/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/iespell/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/alert.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/alert.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/button.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/button.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/corners.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/corners.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/skins/clearlooks2/window.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/skins/clearlooks2/window.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/inlinepopups/template.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/inlinepopups/template.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/insertdatetime/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/insertdatetime/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/insertdatetime/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/insertdatetime/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/layer/editor_plugin.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/layer/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/layer/editor_plugin_src.js with 75% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/legacyoutput/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/legacyoutput/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/legacyoutput/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/legacyoutput/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/lists/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/lists/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/lists/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/lists/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/css/media.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/css/media.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/editor_plugin.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/editor_plugin_src.js with 91% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/js/embed.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/js/embed.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/js/media.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/js/media.js with 85% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/langs/en_dlg.js with 95% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/media.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/media.htm with 96% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/media/moxieplayer.swf [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/media/moxieplayer.swf with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodleemoticon/dialog.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodleemoticon/dialog.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodleemoticon/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodleemoticon/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodleemoticon/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodleemoticon/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodleemoticon/img/moodleemoticon.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodleemoticon/img/moodleemoticon.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodleemoticon/js/dialog.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodleemoticon/js/dialog.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/css/media.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/css/media.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/img/icon.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/img/icon.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/js/media.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/js/media.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/moodlemedia.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlemedia/moodlemedia.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlenolink/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlenolink/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlenolink/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlenolink/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlenolink/img/ed_nolink.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlenolink/img/ed_nolink.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlenolink/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/moodlenolink/langs/en.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/nonbreaking/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/nonbreaking/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/nonbreaking/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/nonbreaking/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/noneditable/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/noneditable/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/noneditable/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/noneditable/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/pagebreak/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/pagebreak/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/pagebreak/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/pagebreak/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/editor_plugin.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/editor_plugin_src.js with 98% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/js/pastetext.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/js/pastetext.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/js/pasteword.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/js/pasteword.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/pastetext.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/pastetext.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/paste/pasteword.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/paste/pasteword.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/preview/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/preview/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/preview/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/preview/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/preview/example.html [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/preview/example.html with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/preview/jscripts/embed.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/preview/jscripts/embed.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/preview/preview.html [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/preview/preview.html with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/print/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/print/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/print/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/print/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/save/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/save/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/save/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/save/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/css/searchreplace.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/css/searchreplace.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/js/searchreplace.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/js/searchreplace.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/searchreplace/searchreplace.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/searchreplace/searchreplace.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/changelog.txt [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/changelog.txt with 95% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/EnchantSpell.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/EnchantSpell.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/GoogleSpell.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/GoogleSpell.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/PSpell.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/PSpell.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/PSpellShell.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/PSpellShell.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/SpellChecker.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/SpellChecker.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/utils/JSON.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/utils/JSON.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/classes/utils/Logger.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/classes/utils/Logger.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/config.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/config.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/css/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/css/content.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/editor_plugin.js with 51% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/editor_plugin_src.js with 89% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/img/wline.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/img/wline.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/includes/general.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/includes/general.php with 96% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/spellchecker/rpc.php [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/spellchecker/rpc.php with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/css/props.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/css/props.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/js/props.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/js/props.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/style/props.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/style/props.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/tabfocus/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/tabfocus/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/tabfocus/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/tabfocus/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/cell.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/cell.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/css/cell.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/css/cell.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/css/row.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/css/row.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/css/table.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/css/table.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/js/cell.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/js/cell.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/js/merge_cells.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/js/merge_cells.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/js/row.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/js/row.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/js/table.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/js/table.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/merge_cells.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/merge_cells.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/row.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/row.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/table/table.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/table/table.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/blank.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/blank.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/css/template.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/css/template.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/js/template.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/js/template.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/template/template.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/template/template.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/visualchars/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/visualchars/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/visualchars/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/visualchars/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/wordcount/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/wordcount/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/wordcount/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/wordcount/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/abbr.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/abbr.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/acronym.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/acronym.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/attributes.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/attributes.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/cite.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/cite.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/css/attributes.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/css/attributes.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/css/popup.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/css/popup.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/del.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/del.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/editor_plugin.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/editor_plugin.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/editor_plugin_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/editor_plugin_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/ins.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/ins.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/abbr.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/abbr.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/acronym.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/acronym.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/attributes.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/attributes.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/cite.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/cite.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/del.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/del.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/element_common.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/element_common.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/js/ins.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/js/ins.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/plugins/xhtmlxtras/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/plugins/xhtmlxtras/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/about.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/about.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/anchor.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/anchor.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/charmap.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/charmap.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/color_picker.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/color_picker.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/editor_template.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/editor_template.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/editor_template_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/editor_template_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/image.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/image.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/colorpicker.jpg [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/colorpicker.jpg with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/flash.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/flash.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/icons.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/icons.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/iframe.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/iframe.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/pagebreak.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/pagebreak.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/quicktime.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/quicktime.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/realmedia.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/realmedia.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/shockwave.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/shockwave.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/trans.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/trans.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/video.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/video.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/img/windowsmedia.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/img/windowsmedia.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/about.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/about.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/anchor.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/anchor.js with 94% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/charmap.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/charmap.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/color_picker.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/color_picker.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/image.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/image.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/link.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/link.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/js/source_editor.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/js/source_editor.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/langs/en.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/langs/en_dlg.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/langs/en_dlg.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/link.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/link.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/shortcuts.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/shortcuts.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/content.css with 95% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/dialog.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/dialog.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/buttons.png [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/buttons.png with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/items.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/items.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/menu_arrow.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/menu_arrow.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/menu_check.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/menu_check.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/progress.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/progress.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/img/tabs.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/img/tabs.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/default/ui.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/default/ui.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/highcontrast/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/highcontrast/content.css with 95% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/highcontrast/dialog.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/highcontrast/dialog.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/highcontrast/ui.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/highcontrast/ui.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/content.css with 97% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/dialog.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/dialog.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/img/button_bg.png [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/img/button_bg.png with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/img/button_bg_black.png [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/img/button_bg_black.png with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/img/button_bg_silver.png [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/img/button_bg_silver.png with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/ui.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/ui.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/ui_black.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/ui_black.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/skins/o2k7/ui_silver.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/skins/o2k7/ui_silver.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/advanced/source_editor.htm [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/advanced/source_editor.htm with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/editor_template.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/editor_template.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/editor_template_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/editor_template_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/img/icons.gif [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/img/icons.gif with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/langs/en.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/langs/en.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/skins/default/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/skins/default/content.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/skins/default/ui.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/skins/default/ui.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/skins/o2k7/content.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/skins/o2k7/content.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/skins/o2k7/img/button_bg.png [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/skins/o2k7/img/button_bg.png with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/themes/simple/skins/o2k7/ui.css [moved from lib/editor/tinymce/tiny_mce/3.4.5/themes/simple/skins/o2k7/ui.css with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_dev.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_dev.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_jquery.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_jquery_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_jquery_src.js with 99% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_popup.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_popup.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_popup_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_popup_src.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_prototype.js [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_prototype_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_src.js with 99% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/tiny_mce_src.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/tiny_mce_prototype_src.js with 99% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/utils/editable_selects.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/utils/editable_selects.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/utils/form_utils.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/utils/form_utils.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/utils/mctabs.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/utils/mctabs.js with 100% similarity]
lib/editor/tinymce/tiny_mce/3.4.6/utils/validate.js [moved from lib/editor/tinymce/tiny_mce/3.4.5/utils/validate.js with 100% similarity]
lib/editor/tinymce/version.php
lib/enrollib.php
lib/externallib.php
lib/filestorage/file_storage.php
lib/form/datetimeselector.php
lib/moodlelib.php
lib/navigationlib.php
lib/pluginlib.php
lib/questionlib.php
lib/sessionlib.php
lib/setuplib.php
lib/simpletest/fulltestaccesslib.php [new file with mode: 0644]
lib/simpletest/testaccesslib.php [deleted file]
lib/simpletest/testblocklib_blockmanager.php
lib/simpletest/testfilterconfig.php
lib/thirdpartylibs.xml
lib/upgradelib.php
lib/zend/readme_moodle.txt
login/token.php
mod/assignment/type/upload/assignment.class.php
mod/feedback/backup/moodle2/restore_feedback_activity_task.class.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/feedback/version.php
mod/quiz/accessmanager.php [new file with mode: 0644]
mod/quiz/accessmanager_form.php [new file with mode: 0644]
mod/quiz/accessrule/accessrulebase.php [new file with mode: 0644]
mod/quiz/accessrule/delaybetweenattempts/lang/en/quizaccess_delaybetweenattempts.php [new file with mode: 0644]
mod/quiz/accessrule/delaybetweenattempts/rule.php [new file with mode: 0644]
mod/quiz/accessrule/delaybetweenattempts/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/delaybetweenattempts/version.php [new file with mode: 0644]
mod/quiz/accessrule/ipaddress/lang/en/quizaccess_ipaddress.php [new file with mode: 0644]
mod/quiz/accessrule/ipaddress/rule.php [new file with mode: 0644]
mod/quiz/accessrule/ipaddress/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/ipaddress/version.php [new file with mode: 0644]
mod/quiz/accessrule/numattempts/lang/en/quizaccess_numattempts.php [new file with mode: 0644]
mod/quiz/accessrule/numattempts/rule.php [new file with mode: 0644]
mod/quiz/accessrule/numattempts/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/numattempts/version.php [new file with mode: 0644]
mod/quiz/accessrule/openclosedate/lang/en/quizaccess_openclosedate.php [new file with mode: 0644]
mod/quiz/accessrule/openclosedate/rule.php [new file with mode: 0644]
mod/quiz/accessrule/openclosedate/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/openclosedate/version.php [new file with mode: 0644]
mod/quiz/accessrule/password/lang/en/quizaccess_password.php [new file with mode: 0644]
mod/quiz/accessrule/password/rule.php [new file with mode: 0644]
mod/quiz/accessrule/password/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/password/version.php [new file with mode: 0644]
mod/quiz/accessrule/safebrowser/lang/en/quizaccess_safebrowser.php [new file with mode: 0644]
mod/quiz/accessrule/safebrowser/rule.php [new file with mode: 0644]
mod/quiz/accessrule/safebrowser/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/safebrowser/version.php [new file with mode: 0644]
mod/quiz/accessrule/securewindow/lang/en/quizaccess_securewindow.php [new file with mode: 0644]
mod/quiz/accessrule/securewindow/rule.php [new file with mode: 0644]
mod/quiz/accessrule/securewindow/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/securewindow/version.php [new file with mode: 0644]
mod/quiz/accessrule/timelimit/lang/en/quizaccess_timelimit.php [new file with mode: 0644]
mod/quiz/accessrule/timelimit/rule.php [new file with mode: 0644]
mod/quiz/accessrule/timelimit/simpletest/testrule.php [new file with mode: 0644]
mod/quiz/accessrule/timelimit/version.php [new file with mode: 0644]
mod/quiz/accessrules.php [deleted file]
mod/quiz/attempt.php
mod/quiz/attemptlib.php
mod/quiz/backup/moodle1/lib.php
mod/quiz/backup/moodle2/backup_mod_quiz_access_subplugin.class.php [new file with mode: 0644]
mod/quiz/backup/moodle2/backup_quiz_stepslib.php
mod/quiz/backup/moodle2/restore_mod_quiz_access_subplugin.class.php [new file with mode: 0644]
mod/quiz/backup/moodle2/restore_quiz_stepslib.php
mod/quiz/db/install.xml
mod/quiz/db/subplugins.php
mod/quiz/db/upgrade.php
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/locallib.php
mod/quiz/mod_form.php
mod/quiz/module.js
mod/quiz/renderer.php
mod/quiz/report/overview/db/install.xml
mod/quiz/report/overview/report.php
mod/quiz/report/reportlib.php
mod/quiz/report/responses/report.php
mod/quiz/report/statistics/db/upgrade.php
mod/quiz/report/statistics/report.php
mod/quiz/review.php
mod/quiz/reviewquestion.php
mod/quiz/settings.php
mod/quiz/settingslib.php
mod/quiz/simpletest/testaccessrules.php [deleted file]
mod/quiz/simpletest/testquizobj.php [new file with mode: 0644]
mod/quiz/startattempt.php
mod/quiz/summary.php
mod/quiz/version.php
mod/quiz/view.php
mod/scorm/userreport.php
mod/url/db/install.xml
mod/url/db/upgrade.php
mod/url/lang/en/url.php
mod/url/mod_form.php
mod/url/version.php
mod/url/view.php
mod/wiki/pagelib.php
question/behaviour/adaptive/behaviour.php
question/behaviour/adaptive/renderer.php
question/behaviour/adaptive/simpletest/testwalkthrough.php
question/behaviour/adaptivenopenalty/simpletest/testwalkthrough.php
question/engine/questionattempt.php
question/type/multianswer/lang/en/qtype_multianswer.php
question/type/multichoice/edit_multichoice_form.php
question/type/multichoice/lang/en/qtype_multichoice.php
question/type/numerical/question.php
question/type/questiontypebase.php
rating/simpletest/testrating.php
rss/file.php
theme/base/style/question.css
theme/nonzero/layout/general.php
theme/nonzero/style/pagelayout.css
theme/overlay/style/pagelayout.css
theme/sky_high/style/pagelayout.css
version.php
webservice/lib.php
webservice/soap/locallib.php
webservice/upload.php
webservice/xmlrpc/locallib.php

index 25d3c13..a064ba8 100644 (file)
       </PHP_SETTING>
     </PHP_SETTINGS>
   </MOODLE>
+  <MOODLE version="2.2" requires="1.9">
+    <UNICODE level="required">
+      <FEEDBACK>
+        <ON_ERROR message="unicoderequired" />
+      </FEEDBACK>
+    </UNICODE>
+    <DATABASE level="required">
+      <VENDOR name="mysql" version="5.0.25">
+        <FEEDBACK>
+          <ON_ERROR message="mysql416required" />
+        </FEEDBACK>
+      </VENDOR>
+      <VENDOR name="postgres" version="8.3" />
+      <VENDOR name="mssql" version="9.0" />
+      <VENDOR name="odbc_mssql" version="9.0" />
+      <VENDOR name="mssql_n" version="9.0" />
+      <VENDOR name="oracle" version="10.2" />
+      <VENDOR name="sqlite" version="2.0" />
+    </DATABASE>
+    <PHP version="5.3.2" level="required">
+    </PHP>
+    <PHP_EXTENSIONS>
+      <PHP_EXTENSION name="iconv" level="required">
+        <FEEDBACK>
+          <ON_CHECK message="iconvrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="mbstring" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="mbstringrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="curl" level="required">
+        <FEEDBACK>
+          <ON_CHECK message="curlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="openssl" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="opensslrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="tokenizer" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="tokenizerrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlrpc" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="xmlrpcrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="soap" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="soaprecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="ctype" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ctyperequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zip" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ziprequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="gd" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="gdrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="simplexml" level="required">
+        <FEEDBACK>
+          <ON_CHECK message="simplexmlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="spl" level="required">
+        <FEEDBACK>
+          <ON_CHECK message="splrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="pcre" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="dom" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xml" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="intl" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="intlrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="json" level="required">
+      </PHP_EXTENSION>
+    </PHP_EXTENSIONS>
+    <PHP_SETTINGS>
+      <PHP_SETTING name="memory_limit" value="40M" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="settingmemorylimit" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="safe_mode" value="0" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingsafemode" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="file_uploads" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingfileuploads" />
+        </FEEDBACK>
+      </PHP_SETTING>
+    </PHP_SETTINGS>
+  </MOODLE>
 </COMPATIBILITY_MATRIX>
index 2add057..3719baf 100644 (file)
@@ -65,13 +65,15 @@ if ($requestedqtype) {
 
     // Get the question counts, and all the context information, for each
     // context. That is, rows of these results can be used as $context objects.
+    $ctxpreload = context_helper::get_preload_record_columns_sql('con');
+    $ctxgroupby = implode(',', array_keys(context_helper::get_preload_record_columns('con')));
     $counts = $DB->get_records_sql("
-            SELECT qc.contextid, count(1) as numquestions, sum(hidden) as numhidden, con.id, con.contextlevel, con.instanceid, con.path, con.depth
+            SELECT qc.contextid, count(1) as numquestions, sum(hidden) as numhidden, $ctxpreload
             FROM {question} q
             JOIN {question_categories} qc ON q.category = qc.id
             JOIN {context} con ON con.id = qc.contextid
             $sqlqtypetest
-            GROUP BY contextid, con.id, con.contextlevel, con.instanceid, con.path, con.depth
+            GROUP BY qc.contextid, $ctxgroupby
             ORDER BY numquestions DESC, numhidden ASC, con.contextlevel ASC, con.id ASC", $params);
 
     // Print the report heading.
@@ -94,8 +96,10 @@ if ($requestedqtype) {
     $totalhidden = 0;
     foreach ($counts as $count) {
         // Work out a link for editing questions in this context.
-        $contextname = print_context_name($count);
-        $url = question_edit_url($count);
+        context_helper::preload_from_record($count);
+        $context = context::instance_by_id($count->contextid);
+        $contextname = $context->get_context_name();
+        $url = question_edit_url($context);
         if ($url) {
             $contextname = '<a href="' . $url . '" title="' .
                     get_string('editquestionshere', 'report_questioninstances') .
index 67c9ef2..0c4b157 100644 (file)
@@ -96,7 +96,8 @@ foreach ($contexts as $conid => $con) {
 
 /// Put the contexts into a tree structure.
 foreach ($contexts as $conid => $con) {
-    $parentcontextid = get_parent_contextid($con);
+    $context = context::instance_by_id($conid);
+    $parentcontextid = get_parent_contextid($context);
     if ($parentcontextid) {
         $contexts[$parentcontextid]->children[] = $conid;
     }
@@ -156,13 +157,13 @@ function print_report_tree($contextid, $contexts, $systemcontext, $fullname) {
     }
 
     // Pull the current context into an array for convinience.
-    $context = $contexts[$contextid];
+    $context = context::instance_by_id($contextid);
 
     // Print the context name.
-    echo $OUTPUT->heading(print_context_name($contexts[$contextid]), 4, 'contextname');
+    echo $OUTPUT->heading($context->get_context_name(), 4, 'contextname');
 
     // If there are any role assignments here, print them.
-    foreach ($context->roleassignments as $ra) {
+    foreach ($contexts[$contextid]->roleassignments as $ra) {
         $value = $ra->contextid . ',' . $ra->roleid;
         $inputid = 'unassign' . $value;
 
index 1646cab..7da5786 100644 (file)
@@ -118,8 +118,11 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $ADMIN->add('appearance', $temp);
 
     // coursecontact is the person responsible for course - usually manages enrolments, receives notification, etc.
-    $temp = new admin_settingpage('coursecontact', get_string('coursecontact', 'admin'));
+    $temp = new admin_settingpage('coursecontact', get_string('courses'));
     $temp->add(new admin_setting_special_coursecontact());
+    $temp->add(new admin_setting_configcheckbox('courselistshortnames',
+            get_string('courselistshortnames', 'admin'),
+            get_string('courselistshortnames_desc', 'admin'), 0));
     $ADMIN->add('appearance', $temp);
 
     $temp = new admin_settingpage('ajax', get_string('ajaxuse'));
index 609fadb..192df5b 100644 (file)
@@ -26,7 +26,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $temp->add(new admin_setting_configcheckbox('xmlstrictheaders', get_string('xmlstrictheaders', 'admin'), get_string('configxmlstrictheaders', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('debugsmtp', get_string('debugsmtp', 'admin'), get_string('configdebugsmtp', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('perfdebug', get_string('perfdebug', 'admin'), get_string('configperfdebug', 'admin'), '7', '15', '7'));
-    $temp->add(new admin_setting_configcheckbox('debugstringids', get_string('debugstringids', 'admin'), get_string('configdebugstringids', 'admin'), 0));
+    $temp->add(new admin_setting_configcheckbox('debugstringids', get_string('debugstringids', 'admin'), get_string('debugstringids_desc', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('debugvalidators', get_string('debugvalidators', 'admin'), get_string('configdebugvalidators', 'admin'), 0));
     $temp->add(new admin_setting_configcheckbox('debugpageinfo', get_string('debugpageinfo', 'admin'), get_string('configdebugpageinfo', 'admin'), 0));
     $ADMIN->add('development', $temp);
index 43fd89e..454caa0 100644 (file)
@@ -138,7 +138,8 @@ if ($capability) {
 
     // Put the contexts into a tree structure.
     foreach ($contexts as $conid => $con) {
-        $parentcontextid = get_parent_contextid($con);
+        $context = context::instance_by_id($conid);
+        $parentcontextid = get_parent_contextid($context);
         if ($parentcontextid) {
             $contexts[$parentcontextid]->children[] = $conid;
         }
@@ -196,7 +197,8 @@ function print_report_tree($contextid, $contexts, $allroles) {
         $url = "$CFG->wwwroot/$CFG->admin/roles/override.php?contextid=$contextid";
         $title = get_string('changeoverrides', 'tool_capability');
     }
-    echo '<h3><a href="' . $url . '" title="' . $title . '">', print_context_name($contexts[$contextid]), '</a></h3>';
+    $context = context::instance_by_id($contextid);
+    echo '<h3><a href="' . $url . '" title="' . $title . '">', $context->get_context_name(), '</a></h3>';
 
     // If there are any role overrides here, print them.
     if (!empty($contexts[$contextid]->rolecapabilities)) {
index d920503..e2c573f 100644 (file)
@@ -745,6 +745,52 @@ class UnitTestCaseUsingDatabase extends UnitTestCase {
         }
     }
 
+    /**
+     * Recreates the system context record in the 'context' table
+     *
+     * Once we have switched to test db, if we have recreated the
+     * context table and it's empty, it may be necessary to manually
+     * create the system context record if unittests are going to
+     * play with contexts.
+     *
+     * This is needed because the context_system::instance() method
+     * is exceptional and always requires the record to exist, never
+     * creating it :-( No problem for other contexts.
+     *
+     * Altenatively one complete install can be done, like
+     * {@see accesslib_test::test_everything_in_accesslib} does, but that's
+     * to much for some tests not requiring all the roles/caps/friends
+     * to be present.
+     *
+     * Ideally some day we'll move a lot of these UnitTests to a complete
+     * cloned installation with real data to play with. That day this
+     * won't be necessary anymore.
+     */
+    protected function create_system_context_record() {
+        global $DB;
+
+        // If, for any reason, the record exists, do nothing
+        if ($DB->record_exists('context', array('contextlevel'=>CONTEXT_SYSTEM))) {
+            return;
+        }
+
+        $record = new stdClass();
+        $record->contextlevel = CONTEXT_SYSTEM;
+        $record->instanceid   = 0;
+        $record->depth        = 1;
+        $record->path         = null;
+        if (defined('SYSCONTEXTID')) {
+            $record->id = SYSCONTEXTID;
+            $DB->import_record('context', $record);
+            $DB->get_manager()->reset_sequence('context');
+        } else {
+            $record->id = $DB->insert_record('context', $record);
+        }
+        // fix path
+        $record->path  = '/'.$record->id;
+        $DB->set_field('context', 'path', $record->path, array('id' => $record->id));
+    }
+
     /**
      * Check that the user has not forgotten to clean anything up, and if they
      * have, display a rude message and clean it up for them.
index ea33b6c..7bc8f90 100644 (file)
@@ -39,7 +39,9 @@
 
         if ($shibbolethauth->user_login($frm->username, $frm->password)) {
 
-            $USER = authenticate_user_login($frm->username, $frm->password);
+            $user = authenticate_user_login($frm->username, $frm->password);
+            enrol_check_plugins($user);
+            session_set_user($user);
 
             $USER->loggedin = true;
             $USER->site     = $CFG->wwwroot; // for added security, store the site in the
@@ -75,9 +77,6 @@
                 }
             }
 
-            enrol_check_plugins($USER);
-            load_all_capabilities();     /// This is what lets the user do anything on the site  :-)
-
             redirect($urltogo);
 
             exit;
diff --git a/auth/upgrade.txt b/auth/upgrade.txt
new file mode 100644 (file)
index 0000000..d3e1761
--- /dev/null
@@ -0,0 +1,10 @@
+This files describes API changes in /auth/* - plugins,
+information provided here is intended especially for developers.
+
+=== 2.2 ===
+
+required changes in code:
+* the correct sequence to set up global $USER is:
+    $user = get_complete_user_data('username', $username); // or $user = authenticate_user_login()
+    enrol_check_plugins($user);
+    session_set_user($user);
index ba5bdfc..1ba7ac4 100644 (file)
@@ -143,9 +143,9 @@ if (!empty($entry->id)) {
     if ($CFG->useblogassociations && ($blogassociations = $DB->get_records('blog_association', array('blogid' => $entry->id)))) {
 
         foreach ($blogassociations as $assocrec) {
-            $contextrec = $DB->get_record('context', array('id' => $assocrec->contextid));
+            $context = get_context_instance_by_id($assocrec->contextid);
 
-            switch ($contextrec->contextlevel) {
+            switch ($context->contextlevel) {
                 case CONTEXT_COURSE:
                     $entry->courseassoc = $assocrec->contextid;
                     break;
index cbfd4ae..04c67e5 100644 (file)
@@ -95,7 +95,7 @@ class blog_edit_form extends moodleform {
                     $a->modname = $mod->name;
                     $context = get_context_instance(CONTEXT_MODULE, $modid);
                 } else {
-                    $context = $DB->get_record('context', array('id' => $entry->modassoc));
+                    $context = get_context_instance_by_id($entry->modassoc);
                     $cm = $DB->get_record('course_modules', array('id' => $context->instanceid));
                     $a = new stdClass();
                     $a->modtype = $DB->get_field('modules', 'name', array('id' => $cm->module));
@@ -134,7 +134,7 @@ class blog_edit_form extends moodleform {
 
         // validate course association
         if (!empty($data['courseassoc']) && has_capability('moodle/blog:associatecourse', $sitecontext)) {
-            $coursecontext = $DB->get_record('context', array('id' => $data['courseassoc'], 'contextlevel' => CONTEXT_COURSE));
+            $coursecontext = get_context_instance(CONTEXT_COURSE, $data['courseassoc']);
 
             if ($coursecontext)  {
                 if (!is_enrolled($coursecontext) and !is_viewing($coursecontext)) {
@@ -149,12 +149,12 @@ class blog_edit_form extends moodleform {
         if (!empty($data['modassoc'])) {
             $modcontextid = $data['modassoc'];
 
-            $modcontext = $DB->get_record('context', array('id' => $modcontextid, 'contextlevel' => CONTEXT_MODULE));
+            $modcontext = get_context_instance(CONTEXT_MODULE, $modcontextid);
 
             if ($modcontext) {
                 // get context of the mod's course
                 $path = explode('/', $modcontext->path);
-                $coursecontext = $DB->get_record('context', array('id' => $path[(count($path) - 2)]));
+                $coursecontext = get_context_instance_by_id($path[(count($path) - 2)]);
 
                 // ensure only one course is associated
                 if (!empty($data['courseassoc'])) {
index 51afba8..19b01ca 100644 (file)
@@ -247,10 +247,10 @@ class blog_entry {
 
             // First find and show the associated course
             foreach ($blogassociations as $assocrec) {
-                $contextrec = $DB->get_record('context', array('id' => $assocrec->contextid));
-                if ($contextrec->contextlevel ==  CONTEXT_COURSE) {
-                    $assocurl = new moodle_url('/course/view.php', array('id' => $contextrec->instanceid));
-                    $text = $DB->get_field('course', 'shortname', array('id' => $contextrec->instanceid)); //TODO: performance!!!!
+                $context = get_context_instance_by_id($assocrec->contextid);
+                if ($context->contextlevel ==  CONTEXT_COURSE) {
+                    $assocurl = new moodle_url('/course/view.php', array('id' => $context->instanceid));
+                    $text = $DB->get_field('course', 'shortname', array('id' => $context->instanceid)); //TODO: performance!!!!
                     $assocstr .= $OUTPUT->action_icon($assocurl, new pix_icon('i/course', $text), null, array(), true);
                     $hascourseassocs = true;
                     $assoctype = get_string('course');
@@ -259,15 +259,15 @@ class blog_entry {
 
             // Now show mod association
             foreach ($blogassociations as $assocrec) {
-                $contextrec = $DB->get_record('context', array('id' => $assocrec->contextid));
+                $context = get_context_instance_by_id($assocrec->contextid);
 
-                if ($contextrec->contextlevel ==  CONTEXT_MODULE) {
+                if ($context->contextlevel ==  CONTEXT_MODULE) {
                     if ($hascourseassocs) {
                         $assocstr .= ', ';
                         $hascourseassocs = false;
                     }
 
-                    $modinfo = $DB->get_record('course_modules', array('id' => $contextrec->instanceid));
+                    $modinfo = $DB->get_record('course_modules', array('id' => $context->instanceid));
                     $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module));
 
                     $assocurl = new moodle_url('/mod/'.$modname.'/view.php', array('id' => $modinfo->id));
index 62c4729..0ff81bf 100644 (file)
  */
 
 require('../config.php');
+require($CFG->dirroot.'/cohort/lib.php');
 require_once($CFG->libdir.'/adminlib.php');
 
 $contextid = optional_param('contextid', 0, PARAM_INT);
+$page = optional_param('page', 0, PARAM_INT);
+$searchquery  = optional_param('search', '', PARAM_RAW);
 
 require_login();
 
@@ -68,10 +71,31 @@ echo $OUTPUT->header();
 
 echo $OUTPUT->heading(get_string('cohortsin', 'cohort', print_context_name($context)));
 
-$cohorts = $DB->get_records('cohort', array('contextid'=>$context->id));
+// add search form
+$search  = html_writer::start_tag('form', array('id'=>'searchcohortquery', 'method'=>'get'));
+$search .= html_writer::start_tag('div');
+$search .= html_writer::label(get_string('searchcohort', 'cohort').':', 'cohort_search_q');
+$search .= html_writer::empty_tag('input', array('id'=>'cohort_search_q', 'type'=>'text', 'name'=>'search', 'value'=>$searchquery));
+$search .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('search', 'cohort')));
+$search .= html_writer::end_tag('div');
+$search .= html_writer::end_tag('form');
+echo $search;
+
+$cohorts = cohort_get_cohorts($context->id, $page, 25, $searchquery);
+
+// output pagination bar
+$params = array('page' => $page);
+if ($contextid) {
+    $params['contextid'] = $contextid;
+}
+if ($search) {
+    $params['search'] = $searchquery;
+}
+$baseurl = new moodle_url('/cohort/index.php', $params);
+echo $OUTPUT->paging_bar($cohorts['totalcohorts'], $page, 25, $baseurl);
 
 $data = array();
-foreach($cohorts as $cohort) {
+foreach($cohorts['cohorts'] as $cohort) {
     $line = array();
     $line[] = format_string($cohort->name);
     $line[] = $cohort->idnumber;
@@ -107,6 +131,7 @@ $table->align = array('left', 'left', 'left', 'left','center', 'center');
 $table->width = '80%';
 $table->data  = $data;
 echo html_writer::table($table);
+echo $OUTPUT->paging_bar($cohorts['totalcohorts'], $page, 25, $baseurl);
 
 if ($manager) {
     echo $OUTPUT->single_button(new moodle_url('/cohort/edit.php', array('contextid'=>$context->id)), get_string('add'));
index 9a084eb..e33f77a 100644 (file)
@@ -190,6 +190,51 @@ function cohort_get_visible_list($course) {
     return $cohorts;
 }
 
+/**
+ * Get all the cohorts.
+ *
+ * @global moodle_database $DB
+ * @param int $contextid
+ * @param int $page number of the current page
+ * @param int $perpage items per page
+ * @param string $search search string
+ * @return array    Array(totalcohorts => int, cohorts => array)
+ */
+function cohort_get_cohorts($contextid, $page = 0, $perpage = 25, $search = '') {
+    global $DB;
+
+    $cohorts = array();
+
+    // Add some additional sensible conditions
+    $tests = array('contextid = ?');
+    $params = array($contextid);
+
+    if (!empty($search)) {
+        $conditions = array(
+            'name',
+            'idnumber',
+            'description',
+        );
+        $searchparam = '%' . $search . '%';
+        foreach ($conditions as $key=>$condition) {
+            $conditions[$key] = $DB->sql_like($condition,"?", false);
+            $params[] = $searchparam;
+        }
+        $tests[] = '(' . implode(' OR ', $conditions) . ')';
+    }
+    $wherecondition = implode(' AND ', $tests);
+
+    $fields = 'SELECT *';
+    $countfields = 'SELECT COUNT(1)';
+    $sql = " FROM {cohort}
+             WHERE $wherecondition";
+    $order = ' ORDER BY name ASC';
+    $totalcohorts = $DB->count_records_sql($countfields . $sql, $params);
+    $cohorts = $DB->get_records_sql($fields . $sql . $order, $params, $page*$perpage, $perpage);
+
+    return array('totalcohorts' => $totalcohorts, 'cohorts' => $cohorts);
+}
+
 /**
  * Cohort assignment candidates
  */
index 9ed7ebc..27f4653 100644 (file)
 
             $linkcss = $acourse->visible ? '' : ' class="dimmed" ';
             echo '<tr>';
-            echo '<td><a '.$linkcss.' href="view.php?id='.$acourse->id.'">'. format_string($acourse->fullname) .'</a></td>';
+            $coursename = get_course_display_name_for_list($acourse);
+            echo '<td><a '.$linkcss.' href="view.php?id='.$acourse->id.'">'. format_string($coursename) .'</a></td>';
             if ($editingon) {
                 echo '<td>';
                 if (has_capability('moodle/course:update', $coursecontext)) {
index a00348f..5fb1ae6 100644 (file)
@@ -2173,6 +2173,22 @@ function make_categories_options() {
     return $cats;
 }
 
+/**
+ * Gets the name of a course to be displayed when showing a list of courses.
+ * By default this is just $course->fullname but user can configure it. The
+ * result of this function should be passed through print_string.
+ * @param object $course Moodle course object
+ * @return string Display name of course (either fullname or short + fullname)
+ */
+function get_course_display_name_for_list($course) {
+    global $CFG;
+    if (!empty($CFG->courselistshortnames)) {
+        return $course->shortname . ' ' .$course->fullname;
+    } else {
+        return $course->fullname;
+    }
+}
+
 /**
  * Prints the category info in indented fashion
  * This function is only used by print_whole_category_list() above
@@ -2231,7 +2247,8 @@ function print_category_info($category, $depth=0, $showcourses = false) {
                     $linkcss = array('class'=>'dimmed');
                 }
 
-                $courselink = html_writer::link(new moodle_url('/course/view.php', array('id'=>$course->id)), format_string($course->fullname), $linkcss);
+                $coursename = get_course_display_name_for_list($course);
+                $courselink = html_writer::link(new moodle_url('/course/view.php', array('id'=>$course->id)), format_string($coursename), $linkcss);
 
                 // print enrol info
                 $courseicon = '';
@@ -2423,7 +2440,9 @@ function print_course($course, $highlightterms = '') {
     echo html_writer::start_tag('h3', array('class'=>'name'));
 
     $linkhref = new moodle_url('/course/view.php', array('id'=>$course->id));
-    $linktext = highlight($highlightterms, format_string($course->fullname));
+
+    $coursename = get_course_display_name_for_list($course);
+    $linktext = highlight($highlightterms, format_string($coursename));
     $linkparams = array('title'=>get_string('entercourse'));
     if (empty($course->visible)) {
         $linkparams['class'] = 'dimmed';
index a68ddcc..111e655 100644 (file)
@@ -302,12 +302,6 @@ if ($mform->is_cancelled()) {
         if (!empty($CFG->enableavailability)) {
             $cm->availablefrom             = $fromform->availablefrom;
             $cm->availableuntil            = $fromform->availableuntil;
-            // The form time is midnight, but because we want it to be
-            // inclusive, set it to 23:59:59 on that day.
-            if ($cm->availableuntil) {
-                $cm->availableuntil = strtotime('23:59:59',
-                    $cm->availableuntil);
-            }
             $cm->showavailability          = $fromform->showavailability;
             condition_info::update_cm_from_form($cm,$fromform,true);
         }
@@ -393,12 +387,6 @@ if ($mform->is_cancelled()) {
         if(!empty($CFG->enableavailability)) {
             $newcm->availablefrom             = $fromform->availablefrom;
             $newcm->availableuntil            = $fromform->availableuntil;
-            // The form time is midnight, but because we want it to be
-            // inclusive, set it to 23:59:59 on that day.
-            if ($newcm->availableuntil) {
-                $newcm->availableuntil = strtotime('23:59:59',
-                    $newcm->availableuntil);
-            }
             $newcm->showavailability          = $fromform->showavailability;
         }
         if (isset($fromform->showdescription)) {
index ce5666b..b4fbb2f 100644 (file)
@@ -308,7 +308,7 @@ abstract class moodleform_mod extends moodleform {
         // Conditions: Don't let them set dates which make no sense
         if (array_key_exists('availablefrom', $data) &&
             $data['availablefrom'] && $data['availableuntil'] &&
-            $data['availablefrom'] > $data['availableuntil']) {
+            $data['availablefrom'] >= $data['availableuntil']) {
             $errors['availablefrom'] = get_string('badavailabledates', 'condition');
         }
 
@@ -429,10 +429,23 @@ abstract class moodleform_mod extends moodleform {
 
         if (!empty($CFG->enableavailability)) {
             // Conditional availability
-            $mform->addElement('header', 'availabilityconditionsheader', get_string('availabilityconditions', 'condition'));
-            $mform->addElement('date_selector', 'availablefrom', get_string('availablefrom', 'condition'), array('optional'=>true));
+
+            // Available from/to defaults to midnight because then the display
+            // will be nicer where it tells users when they can access it (it
+            // shows only the date and not time).
+            $date = usergetdate(time());
+            $midnight = make_timestamp($date['year'], $date['mon'], $date['mday']);
+
+            // From/until controls
+            $mform->addElement('header', 'availabilityconditionsheader',
+                    get_string('availabilityconditions', 'condition'));
+            $mform->addElement('date_time_selector', 'availablefrom',
+                    get_string('availablefrom', 'condition'),
+                    array('optional' => true, 'defaulttime' => $midnight));
             $mform->addHelpButton('availablefrom', 'availablefrom', 'condition');
-            $mform->addElement('date_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true));
+            $mform->addElement('date_time_selector', 'availableuntil',
+                    get_string('availableuntil', 'condition'),
+                    array('optional' => true, 'defaulttime' => $midnight));
 
             // Conditions based on grades
             $gradeoptions = array();
index 5936ed3..af07f65 100644 (file)
@@ -241,6 +241,9 @@ $pagingbar = '';
 foreach ($initials as $initial) {
     $var = 'si'.$initial;
 
+    $othervar = $initial == 'first' ? 'silast' : 'sifirst';
+    $othervar = $$othervar != 'all' ? "&amp;{$othervar}={$$othervar}" : '';
+
     $pagingbar .= ' <div class="initialbar '.$initial.'initial">';
     $pagingbar .= get_string($initial.'name').':&nbsp;';
 
@@ -248,7 +251,7 @@ foreach ($initials as $initial) {
         $pagingbar .= '<strong>'.get_string('all').'</strong> ';
     }
     else {
-        $pagingbar .= '<a href="'.$link.'">'.get_string('all').'</a> ';
+        $pagingbar .= "<a href=\"{$link}{$othervar}\">".get_string('all').'</a> ';
     }
 
     foreach ($alphabet as $letter) {
@@ -256,7 +259,7 @@ foreach ($initials as $initial) {
             $pagingbar .= '<strong>'.$letter.'</strong> ';
         }
         else {
-            $pagingbar .= '<a href="'.$link.'&amp;'.$var.'='.$letter.'">'.$letter.'</a> ';
+            $pagingbar .= "<a href=\"$link&amp;$var={$letter}{$othervar}\">$letter</a> ";
         }
     }
 
@@ -270,10 +273,19 @@ if($total > COMPLETION_REPORT_PAGE) {
     $pagingbar .= '<div class="paging">';
     $pagingbar .= get_string('page').': ';
 
+    $sistrings = array();
+    if ($sifirst != 'all') {
+        $sistrings[] =  "sifirst={$sifirst}";
+    }
+    if ($silast != 'all') {
+        $sistrings[] =  "silast={$silast}";
+    }
+    $sistring = !empty($sistrings) ? '&amp;'.implode('&amp;', $sistrings) : '';
+
     // Display previous link
     if ($start > 0) {
         $pstart = max($start - COMPLETION_REPORT_PAGE, 0);
-        $pagingbar .= '(<a class="previous" href="'.$link.$pstart.'">'.get_string('previous').'</a>)&nbsp;';
+        $pagingbar .= "(<a class=\"previous\" href=\"{$link}{$pstart}{$sistring}\">".get_string('previous').'</a>)&nbsp;';
     }
 
     // Create page links
@@ -286,7 +298,7 @@ if($total > COMPLETION_REPORT_PAGE) {
             $pagingbar .= '&nbsp;'.$curpage.'&nbsp;';
         }
         else {
-            $pagingbar .= '&nbsp;<a href="'.$link.$curstart.'">'.$curpage.'</a>&nbsp;';
+            $pagingbar .= "&nbsp;<a href=\"{$link}{$curstart}{$sistring}\">$curpage</a>&nbsp;";
         }
 
         $curstart += COMPLETION_REPORT_PAGE;
@@ -295,7 +307,7 @@ if($total > COMPLETION_REPORT_PAGE) {
     // Display next link
     $nstart = $start + COMPLETION_REPORT_PAGE;
     if ($nstart < $total) {
-        $pagingbar .= '&nbsp;(<a class="next" href="'.$link.$nstart.'">'.get_string('next').'</a>)';
+        $pagingbar .= "&nbsp;(<a class=\"next\" href=\"{$link}{$nstart}{$sistring}\">".get_string('next').'</a>)';
     }
 
     $pagingbar .= '</div>';
@@ -441,12 +453,15 @@ if(!$csv) {
 
     // User heading / sort option
     print '<th scope="col" class="completion-sortchoice" style="clear: both;">';
+
+    $sistring = "&amp;silast={$silast}&amp;sifirst={$sifirst}";
+
     if($firstnamesort) {
         print
-            get_string('firstname').' / <a href="./?course='.$course->id.'">'.
+            get_string('firstname')." / <a href=\"./?course={$course->id}{$sistring}\">".
             get_string('lastname').'</a>';
     } else {
-        print '<a href="./?course='.$course->id.'&amp;sort=firstname">'.
+        print "<a href=\"./?course={$course->id}&amp;sort=firstname{$sistring}\">".
             get_string('firstname').'</a> / '.
             get_string('lastname');
     }
index b205c0b..323d2b8 100644 (file)
@@ -173,6 +173,9 @@ $pagingbar = '';
 foreach ($initials as $initial) {
     $var = 'si'.$initial;
 
+    $othervar = $initial == 'first' ? 'silast' : 'sifirst';
+    $othervar = $$othervar != 'all' ? "&amp;{$othervar}={$$othervar}" : '';
+
     $pagingbar .= ' <div class="initialbar '.$initial.'initial">';
     $pagingbar .= get_string($initial.'name').':&nbsp;';
 
@@ -180,7 +183,7 @@ foreach ($initials as $initial) {
         $pagingbar .= '<strong>'.get_string('all').'</strong> ';
     }
     else {
-        $pagingbar .= '<a href="'.$link.'">'.get_string('all').'</a> ';
+        $pagingbar .= "<a href=\"{$link}{$othervar}\">".get_string('all').'</a> ';
     }
 
     foreach ($alphabet as $letter) {
@@ -188,7 +191,7 @@ foreach ($initials as $initial) {
             $pagingbar .= '<strong>'.$letter.'</strong> ';
         }
         else {
-            $pagingbar .= '<a href="'.$link.'&amp;'.$var.'='.$letter.'">'.$letter.'</a> ';
+            $pagingbar .= "<a href=\"$link&amp;$var={$letter}{$othervar}\">$letter</a> ";
         }
     }
 
@@ -202,10 +205,19 @@ if($total > COMPLETION_REPORT_PAGE) {
     $pagingbar .= '<div class="paging">';
     $pagingbar .= get_string('page').': ';
 
+    $sistrings = array();
+    if ($sifirst != 'all') {
+        $sistrings[] =  "sifirst={$sifirst}";
+    }
+    if ($silast != 'all') {
+        $sistrings[] =  "silast={$silast}";
+    }
+    $sistring = !empty($sistrings) ? '&amp;'.implode('&amp;', $sistrings) : '';
+
     // Display previous link
     if ($start > 0) {
         $pstart = max($start - COMPLETION_REPORT_PAGE, 0);
-        $pagingbar .= '(<a class="previous" href="'.$link.$pstart.'">'.get_string('previous').'</a>)&nbsp;';
+        $pagingbar .= "(<a class=\"previous\" href=\"{$link}{$pstart}{$sistring}\">".get_string('previous').'</a>)&nbsp;';
     }
 
     // Create page links
@@ -218,7 +230,7 @@ if($total > COMPLETION_REPORT_PAGE) {
             $pagingbar .= '&nbsp;'.$curpage.'&nbsp;';
         }
         else {
-            $pagingbar .= '&nbsp;<a href="'.$link.$curstart.'">'.$curpage.'</a>&nbsp;';
+            $pagingbar .= "&nbsp;<a href=\"{$link}{$curstart}{$sistring}\">$curpage</a>&nbsp;";
         }
 
         $curstart += COMPLETION_REPORT_PAGE;
@@ -227,7 +239,7 @@ if($total > COMPLETION_REPORT_PAGE) {
     // Display next link
     $nstart = $start + COMPLETION_REPORT_PAGE;
     if ($nstart < $total) {
-        $pagingbar .= '&nbsp;(<a class="next" href="'.$link.$nstart.'">'.get_string('next').'</a>)';
+        $pagingbar .= "&nbsp;(<a class=\"next\" href=\"{$link}{$nstart}{$sistring}\">".get_string('next').'</a>)';
     }
 
     $pagingbar .= '</div>';
@@ -251,12 +263,15 @@ if(!$csv) {
 
     // User heading / sort option
     print '<th scope="col" class="completion-sortchoice">';
+
+    $sistring = "&amp;silast={$silast}&amp;sifirst={$sifirst}";
+
     if($firstnamesort) {
         print
-            get_string('firstname').' / <a href="./?course='.$course->id.'">'.
+            get_string('firstname')." / <a href=\"./?course={$course->id}{$sistring}\">".
             get_string('lastname').'</a>';
     } else {
-        print '<a href="./?course='.$course->id.'&amp;sort=firstname">'.
+        print "<a href=\"./?course={$course->id}&amp;sort=firstname{$sistring}\">".
             get_string('firstname').'</a> / '.
             get_string('lastname');
     }
index 2104d84..857d13e 100644 (file)
@@ -113,4 +113,24 @@ class courselib_test extends UnitTestCase {
         $this->assertEqual(25, next($newsections_flipped));
         $this->assertEqual(21, next($newsections_flipped));
     }
+
+    function test_get_course_display_name_for_list() {
+        global $CFG;
+
+        $course = (object)array('shortname' => 'FROG101',
+                'fullname' => 'Introduction to pond life');
+
+        // Store config value in case other tests rely on it
+        $oldcfg = $CFG->courselistshortnames;
+
+        $CFG->courselistshortnames = 0;
+        $this->assertEqual('Introduction to pond life',
+                get_course_display_name_for_list($course));
+
+        $CFG->courselistshortnames = 1;
+        $this->assertEqual('FROG101 Introduction to pond life',
+                get_course_display_name_for_list($course));
+
+        $CFG->courselistshortnames = $oldcfg;
+    }
 }
index ccb8412..87d319b 100644 (file)
@@ -70,7 +70,9 @@ switch ($action) {
         break;
     case 'getcohorts':
         require_capability('moodle/course:enrolconfig', $context);
-        $outcome->response = enrol_cohort_get_cohorts($manager);
+        $offset = optional_param('offset', 0, PARAM_INT);
+        $search  = optional_param('search', '', PARAM_RAW);
+        $outcome->response = enrol_cohort_search_cohorts($manager, $offset, 25, $search);
         break;
     case 'enrolcohort':
         require_capability('moodle/course:enrolconfig', $context);
@@ -79,8 +81,7 @@ switch ($action) {
         $cohortid = required_param('cohortid', PARAM_INT);
         
         $roles = $manager->get_assignable_roles();
-        $cohorts = enrol_cohort_get_cohorts($manager);
-        if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
+        if (!enrol_cohort_can_view_cohort($cohortid) || !array_key_exists($roleid, $roles)) {
             throw new enrol_ajax_exception('errorenrolcohort');
         }
         $enrol = enrol_get_plugin('cohort');
@@ -94,8 +95,7 @@ switch ($action) {
         $result = enrol_cohort_enrol_all_users($manager, $cohortid, $roleid);
 
         $roles = $manager->get_assignable_roles();
-        $cohorts = enrol_cohort_get_cohorts($manager);
-        if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
+        if (!enrol_cohort_can_view_cohort($cohortid) || !array_key_exists($roleid, $roles)) {
             throw new enrol_ajax_exception('errorenrolcohort');
         }
         if ($result === false) {
index 740834c..a2dcbf4 100644 (file)
@@ -24,6 +24,8 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['ajaxmore'] = 'More...';
+$string['cohortsearch'] = 'Search';
 $string['cohort:config'] = 'Configure cohort instances';
 $string['pluginname'] = 'Cohort sync';
 $string['pluginname_desc'] = 'Cohort enrolment plugin synchronises cohort members with course participants.';
index d8cd4e1..11c22f7 100644 (file)
@@ -157,7 +157,16 @@ class enrol_cohort_plugin extends enrol_plugin {
         $button = new enrol_user_button($cohorturl, get_string('enrolcohort', 'enrol'), 'get');
         $button->class .= ' enrol_cohort_plugin';
 
-        $button->strings_for_js(array('enrol','synced','enrolcohort','enrolcohortusers'), 'enrol');
+        $button->strings_for_js(array(
+            'enrol',
+            'synced',
+            'enrolcohort',
+            'enrolcohortusers',
+            ), 'enrol');
+        $button->strings_for_js(array(
+            'ajaxmore',
+            'cohortsearch',
+            ), 'enrol_cohort');
         $button->strings_for_js('assignroles', 'role');
         $button->strings_for_js('cohort', 'cohort');
         $button->strings_for_js('users', 'moodle');
index 5a37f44..3462638 100644 (file)
@@ -244,6 +244,7 @@ function enrol_cohort_enrol_all_users(course_enrolment_manager $manager, $cohort
  * Gets all the cohorts the user is able to view.
  *
  * @global moodle_database $DB
+ * @param course_enrolment_manager $manager
  * @return array
  */
 function enrol_cohort_get_cohorts(course_enrolment_manager $manager) {
@@ -277,4 +278,100 @@ function enrol_cohort_get_cohorts(course_enrolment_manager $manager) {
     }
     $rs->close();
     return $cohorts;
+}
+
+/**
+ * Check if cohort exists and user is allowed to enrol it
+ *
+ * @global moodle_database $DB
+ * @param int $cohortid Cohort ID
+ * @return boolean
+ */
+function enrol_cohort_can_view_cohort($cohortid) {
+    global $DB;
+    $cohort = $DB->get_record('cohort', array('id' => $cohortid), 'id, contextid');
+    if ($cohort) {
+        $context = get_context_instance_by_id($cohort->contextid);
+        if (has_capability('moodle/cohort:view', $context)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * Gets cohorts the user is able to view.
+ *
+ * @global moodle_database $DB
+ * @param course_enrolment_manager $manager
+ * @param int $offset limit output from
+ * @param int $limit items to output per load
+ * @param string $search search string
+ * @return array    Array(more => bool, offset => int, cohorts => array)
+ */
+function enrol_cohort_search_cohorts(course_enrolment_manager $manager, $offset = 0, $limit = 25, $search = '') {
+    global $DB;
+    $context = $manager->get_context();
+    $cohorts = array();
+    $instances = $manager->get_enrolment_instances();
+    $enrolled = array();
+    foreach ($instances as $instance) {
+        if ($instance->enrol == 'cohort') {
+            $enrolled[] = $instance->customint1;
+        }
+    }
+
+    list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
+
+    // Add some additional sensible conditions
+    $tests = array('contextid ' . $sqlparents);
+
+    // Modify the quesry to perform the search if requred
+    if (!empty($search)) {
+        $conditions = array(
+            'name',
+            'idnumber',
+            'description'
+        );
+        $searchparam = '%' . $search . '%';
+        foreach ($conditions as $key=>$condition) {
+            $conditions[$key] = $DB->sql_like($condition,"?", false);
+            $params[] = $searchparam;
+        }
+        $tests[] = '(' . implode(' OR ', $conditions) . ')';
+    }
+    $wherecondition = implode(' AND ', $tests);
+
+    $fields = 'SELECT id, name, contextid, description';
+    $countfields = 'SELECT COUNT(1)';
+    $sql = " FROM {cohort}
+             WHERE $wherecondition";
+    $order = ' ORDER BY name ASC';
+    $rs = $DB->get_recordset_sql($fields . $sql . $order, $params, $offset);
+
+    // Produce the output respecting parameters
+    foreach ($rs as $c) {
+        // Track offset
+        $offset++;
+        // Check capabilities
+        $context = get_context_instance_by_id($c->contextid);
+        if (!has_capability('moodle/cohort:view', $context)) {
+            continue;
+        }
+        if ($limit === 0) {
+            // we have reached the required number of items and know that there are more, exit now
+            $offset--;
+            break;
+        }
+        $cohorts[$c->id] = array(
+            'cohortid'=>$c->id,
+            'name'=>  shorten_text(format_string($c->name), 35),
+            'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
+            'enrolled'=>in_array($c->id, $enrolled)
+        );
+        // Count items
+        $limit--;
+    }
+    $rs->close();
+    return array('more' => !(bool)$limit, 'offset' => $offset, 'cohorts' => $cohorts);
 }
\ No newline at end of file
index 916adcb..540ed78 100644 (file)
@@ -1,25 +1,36 @@
-.qce-panel {background-color:#666;border:2px solid #666;border-width:0 2px 2px 0;width:420px;}
+.qce-panel {background-color:#666;border:2px solid #666;border-width:0 2px 2px 0;min-width:420px;}
 .qce-panel .yui3-widget-hd {background:url("sprite.png");background-repeat:repeat-x;background-color:#DDD;background-position: 0 -15px;border-bottom:1px solid #555;border-top:1px solid #fff;}
 .qce-panel .yui3-widget-hd h2 {margin:3px 5px 2px;padding:0;font-size:110%;}
 .qce-panel .yui3-widget-hd .close {width:25px;height:15px;position:absolute;top:3px;right:1em;cursor:pointer;background:url("sprite.png") no-repeat scroll 0 0 transparent;}
 .qce-panel .yui3-overlay-content {background-color:#F6F6F6;border:1px solid #555;margin-top:-2px;margin-left:-2px;}
-.qce-panel .yui3-widget-bd .loading {height:300px;text-align:center;}
-.qce-panel .yui3-widget-bd .loading img {margin-top:130px;}
-.qce-panel .qce-enrollable-cohorts {overflow:auto;margin:5px;}
-.qce-panel .qce-cohorts {border:1px solid #666;width:408px;background-color:#FFF;height:250px;}
-.qce-panel .qce-cohort {width:100%;position:relative;clear:both;height:24px;}
+.qce-panel .qce-enrollable-cohorts {margin:5px;}
+.qce-panel .qce-cohorts {border:1px solid #666;min-width:408px;background-color:#FFF;height:375px;overflow:auto;}
+.qce-panel .qce-cohorts .qce-more-results {background-color:#eee;padding:5px;border-top:1px solid #BBB;text-align:center;}
+
+.qce-panel .qce-panel-content {min-height:405px;}
+.qce-panel .qce-panel-content .qce-loading-lightbox {position:absolute;width:100%;height:100%;top:0;left:0;background-color:#FFF;min-height:264px;text-align:center;}
+.qce-panel .qce-panel-content .qce-loading-lightbox.hidden {display:none;}
+.qce-panel .qce-panel-content .qce-loading-lightbox .loading-icon {margin:auto;vertical-align:middle;margin-top:198px;}
+
+.qce-panel .qce-cohort {width:100%;position:relative;clear:both;height:24px;white-space:nowrap;}
+.qce-panel .qce-cohort div {display:inline-block;overflow:hidden;}
 .qce-panel .qce-cohort.odd {background-color:#f4f4f4;}
-.qce-panel .qce-cohort .qce-cohort-button {float:left;text-align:center;display:inline-block;font-size:80%;height:22px;line-height:22px;overflow:hidden;padding:0 4px;}
+.qce-panel .qce-cohort .qce-cohort-button {text-align:center;display:inline-block;font-size:80%;height:22px;line-height:22px;overflow:hidden;padding:0 4px;}
 .qce-panel .qce-cohort .qce-cohort-button.notenrolled {background-color:#ddd;border:1px outset #CCC;background:url("sprite.png");background-repeat:repeat-x;background-color:#DDD;background-position: 0 -25px;color:inherit;}
 .qce-panel .qce-cohort .qce-cohort-button.notenrolled:hover {background-position:0 -15px;cursor:pointer;}
 .qce-panel .qce-cohort .qce-cohort-button.notenrolled.enrolusers {margin-right: 4px;}
-.qce-panel .qce-cohort .qce-cohort-button.alreadyenrolled {font-weight:bold;margin:2px;}
-.qce-panel .qce-cohort .qce-cohort-name {margin-left:80px;margin-right:40px;line-height:24px;}
-.qce-panel .canenrolusers .qce-cohort .qce-cohort-button.alreadyenrolled {width:140px;}
-.qce-panel .canenrolusers .qce-cohort .qce-cohort-name {margin-left:150px;margin-right:40px;line-height:24px;}
-.qce-panel .qce-cohort .qce-cohort-users {position:absolute;right:5px;top:0;width:30px;text-align:right;height:24px;line-height:24px;}
-.qce-panel .qce-assignable-roles {margin:3px 5px 2px;}
+.qce-panel .qce-cohort .qce-cohort-button.alreadyenrolled {font-weight:bold;}
+.qce-panel .qce-cohort .qce-cohort-name {line-height:24px;width:220px;}
+.qce-panel .canenrolusers .qce-cohort .qce-cohort-button.alreadyenrolled {width:125px;}
+.qce-panel .canenrolusers .qce-cohort .qce-cohort-name {line-height:24px;}
+.qce-panel .qce-cohort .qce-cohort-users {width:30px;text-align:right;height:24px;line-height:24px;margin-right:4px}
+
+.qce-panel .qce-assignable-roles {margin:5px 6px 0 6px;}
+.qce-panel .qce-assignable-roles label {padding-right:8px;}
+
+.qce-panel .qce-footer {margin:0 6px 5px 6px;}
+.qce-panel .qce-search label {padding-right:8px;}
+.qce-panel .qce-search input {width:70%;}
+
 .qce-panel .qce-cohort.headings {font-weight:bold;border-width:0;}
-.qce-panel .qce-cohort.headings .qce-cohort-button {display:none;}
-.qce-panel .performing-action {position:absolute;top:0;left:0;width:100%;height:100%;background-color:#fff;text-align:center;}
-.qce-panel .performing-action img {margin-top:150px;}
\ No newline at end of file
+.qce-panel .qce-cohort.headings .qce-cohort-button {display:none;}
\ No newline at end of file
index 6607566..7f5437e 100644 (file)
@@ -10,7 +10,12 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
         ASSIGNABLEROLES = 'assignableRoles',
         DEFAULTCOHORTROLE = 'defaultCohortRole',
         COHORTS = 'cohorts',
+        MORERESULTS = 'moreresults',
+        FIRSTPAGE = 'firstpage',
+        OFFSET = 'offset',
         PANELID = 'qce-panel-',
+        REQUIREREFRESH = 'requiresRefresh',
+        SEARCH = 'search',
         URL = 'url',
         AJAXURL = 'ajaxurl',
         MANUALENROLMENT = 'manualEnrolment',
@@ -21,12 +26,18 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             COHORTENROLLED : 'qce-cohort-enrolled',
             COHORTNAME : 'qce-cohort-name',
             COHORTUSERS : 'qce-cohort-users',
+            ENROLUSERS : 'canenrolusers',
+            FOOTER : 'qce-footer',
+            HIDDEN : 'hidden',
+            LIGHTBOX : 'qce-loading-lightbox',
+            LOADINGICON : 'loading-icon',
+            MORERESULTS : 'qce-more-results',
             PANEL : 'qce-panel',
             PANELCONTENT : 'qce-panel-content',
             PANELCOHORTS : 'qce-enrollable-cohorts',
             PANELROLES : 'qce-assignable-roles',
             PANELCONTROLS : 'qce-panel-controls',
-            ENROLUSERS : 'canenrolusers'
+            SEARCH : 'qce-search'
         },
         COUNT = 0;
 
@@ -35,24 +46,47 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
         CONTROLLER.superclass.constructor.apply(this, arguments);
     };
     CONTROLLER.prototype = {
-        _preformingAction : false,
         initializer : function(config) {
             COUNT ++;
             this.publish('assignablerolesloaded', {fireOnce:true});
             this.publish('cohortsloaded');
-            this.publish('performingaction');
-            this.publish('actioncomplete');
             this.publish('defaultcohortroleloaded', {fireOnce:true});
 
+            var base = Y.Node.create('<div class="'+CSS.PANELCONTENT+'"></div>')
+                .append(Y.Node.create('<div class="'+CSS.PANELROLES+'"></div>'))
+                .append(Y.Node.create('<div class="'+CSS.PANELCOHORTS+'"></div>'))
+                .append(Y.Node.create('<div class="'+CSS.FOOTER+'"></div>')
+                    .append(Y.Node.create('<div class="'+CSS.SEARCH+'"><label>'+M.str.enrol_cohort.cohortsearch+':</label></div>')
+                        .append(Y.Node.create('<input type="text" id="enrolcohortsearch" value="" />'))
+                    )
+                )
+                .append(Y.Node.create('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>')
+                    .append(Y.Node.create('<img alt="loading" class="'+CSS.LOADINGICON+'" />')
+                        .setAttribute('src', M.util.image_url('i/loading', 'moodle')))
+                    .setStyle('opacity', 0.5)
+                );
+
             var close = Y.Node.create('<div class="close"></div>');
             var panel = new Y.Overlay({
                 headerContent : Y.Node.create('<div></div>').append(Y.Node.create('<h2>'+M.str.enrol.enrolcohort+'</h2>')).append(close),
-                bodyContent : Y.Node.create('<div class="loading"></div>').append(Y.Node.create('<img alt="loading" />').setAttribute('src', M.cfg.loadingicon)),
+                bodyContent : base,
                 constrain : true,
                 centered : true,
                 id : PANELID+COUNT,
                 visible : false
             });
+
+            // display the wheel on ajax events
+            Y.on('io:start', function() {
+                base.one('.'+CSS.LIGHTBOX).removeClass(CSS.HIDDEN);
+            }, this);
+            Y.on('io:end', function() {
+                base.one('.'+CSS.LIGHTBOX).addClass(CSS.HIDDEN);
+            }, this);
+
+            this.set(SEARCH, base.one('#enrolcohortsearch'));
+            Y.on('key', this.getCohorts, this.get(SEARCH), 'down:13', this, false);
+
             panel.get('boundingBox').addClass(CSS.PANEL);
             panel.render(Y.one(document.body));
             this.on('show', function(){
@@ -60,15 +94,10 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                 this.show();
             }, panel);
             this.on('hide', panel.hide, panel);
-            this.on('performingaction', function(){
-                this.get('boundingBox').append(Y.Node.create('<div class="performing-action"></div>').append(Y.Node.create('<img alt="loading" />').setAttribute('src', M.cfg.loadingicon)).setStyle('opacity', 0.5));
-            }, panel);
-            this.on('actioncomplete', function(){
-                this.get('boundingBox').one('.performing-action').remove();
-            }, panel);
             this.on('assignablerolesloaded', this.updateContent, this, panel);
             this.on('cohortsloaded', this.updateContent, this, panel);
             this.on('defaultcohortroleloaded', this.updateContent, this, panel);
+            Y.on('key', this.hide, document.body, 'down:27', this);
             close.on('click', this.hide, this);
 
             Y.all('.enrol_cohort_plugin input').each(function(node){
@@ -77,38 +106,51 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                 }
             }, this);
 
-            var base = panel.get('boundingBox');
+            base = panel.get('boundingBox');
             base.plug(Y.Plugin.Drag);
             base.dd.addHandle('.yui3-widget-hd h2');
             base.one('.yui3-widget-hd h2').setStyle('cursor', 'move');
         },
         show : function(e) {
             e.preventDefault();
-            this.getCohorts();
+            // prepare the data and display the window
+            this.getCohorts(e, false);
             this.getAssignableRoles();
             this.fire('show');
         },
         updateContent : function(e, panel) {
-            if (panel.get('contentBox').one('.loading')) {
-                panel.set('bodyContent', Y.Node.create('<div class="'+CSS.PANELCONTENT+'"></div>')
-                    .append(Y.Node.create('<div class="'+CSS.PANELCOHORTS+'"><div class="'+CSS.COHORT+' headings"><div class="'+CSS.COHORTBUTTON+'"></div><div class="'+CSS.COHORTNAME+'">'+M.str.cohort.cohort+'</div><div class="'+CSS.COHORTUSERS+'">'+M.str.moodle.users+'</div></div></div>'))
-                    .append(Y.Node.create('<div class="'+CSS.PANELROLES+'"></div>')));
-            }
             var content, i, roles, cohorts, count=0, supportmanual = this.get(MANUALENROLMENT), defaultrole;
             switch (e.type.replace(/^[^:]+:/, '')) {
                 case 'cohortsloaded' :
-                    cohorts = this.get(COHORTS);
-                    content = Y.Node.create('<div class="'+CSS.COHORTS+'"></div>');
-                    if (supportmanual) {
-                        content.addClass(CSS.ENROLUSERS);
+                    if (this.get(FIRSTPAGE)) {
+                        // we are on the page 0, create new element for cohorts list
+                        content = Y.Node.create('<div class="'+CSS.COHORTS+'"></div>');
+                        if (supportmanual) {
+                            content.addClass(CSS.ENROLUSERS);
+                        }
+                    } else {
+                        // we are adding cohorts to existing list
+                        content = Y.Node.one('.'+CSS.PANELCOHORTS+' .'+CSS.COHORTS);
+                        content.one('.'+CSS.MORERESULTS).remove();
                     }
+                    // add cohorts items to the content
+                    cohorts = this.get(COHORTS);
                     for (i in cohorts) {
                         count++;
                         cohorts[i].on('enrolchort', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), false);
                         cohorts[i].on('enrolusers', this.enrolCohort, this, cohorts[i], panel.get('contentBox'), true);
                         content.append(cohorts[i].toHTML(supportmanual).addClass((count%2)?'even':'odd'));
                     }
-                    panel.get('contentBox').one('.'+CSS.PANELCOHORTS).setContent(content);
+                    // add the next link if there are more items expected
+                    if (this.get(MORERESULTS)) {
+                        var fetchmore = Y.Node.create('<div class="'+CSS.MORERESULTS+'"><a href="#">'+M.str.enrol_cohort.ajaxmore+'</a></div>');
+                        fetchmore.on('click', this.getCohorts, this, true);
+                        content.append(fetchmore);
+                    }
+                    // finally assing the content to the block
+                    if (this.get(FIRSTPAGE)) {
+                        panel.get('contentBox').one('.'+CSS.PANELCOHORTS).setContent(content);
+                    }
                     break;
                 case 'assignablerolesloaded':
                     roles = this.get(ASSIGNABLEROLES);
@@ -116,7 +158,7 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                     for (i in roles) {
                         content.append(Y.Node.create('<option value="'+i+'">'+roles[i]+'</option>'));
                     }
-                    panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div>'+M.str.role.assignroles+': </div>').append(content));
+                    panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div><label>'+M.str.role.assignroles+':</label></div>').append(content));
 
                     this.getDefaultCohortRole();
                     break;
@@ -127,12 +169,31 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             }
         },
         hide : function() {
+            if (this.get(REQUIREREFRESH)) {
+                window.location = this.get(URL);
+            }
             this.fire('hide');
         },
-        getCohorts : function() {
+        getCohorts : function(e, append) {
+            if (e) {
+                e.preventDefault();
+            }
+            if (append) {
+                this.set(FIRSTPAGE, false);
+            } else {
+                this.set(FIRSTPAGE, true);
+                this.set(OFFSET, 0);
+            }
+            var params = [];
+            params['id'] = this.get(COURSEID);
+            params['offset'] = this.get(OFFSET);
+            params['search'] = this.get(SEARCH).get('value');
+            params['action'] = 'getcohorts';
+            params['sesskey'] = M.cfg.sesskey;
+
             Y.io(M.cfg.wwwroot+this.get(AJAXURL), {
                 method:'POST',
-                data:'id='+this.get(COURSEID)+'&action=getcohorts&sesskey='+M.cfg.sesskey,
+                data:build_querystring(params),
                 on: {
                     complete: function(tid, outcome, args) {
                         try {
@@ -145,16 +206,16 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                         } catch (e) {
                             return new M.core.exception(e);
                         }
-                        this.getCohorts = function() {
-                            this.fire('cohortsloaded');
-                        };
-                        this.getCohorts();
+                        this.fire('cohortsloaded');
                     }
                 },
                 context:this
             });
         },
-        setCohorts : function(rawcohorts) {
+        setCohorts : function(response) {
+            this.set(MORERESULTS, response.more);
+            this.set(OFFSET, response.offset);
+            var rawcohorts = response.cohorts;
             var cohorts = [], i=0;
             for (i in rawcohorts) {
                 cohorts[rawcohorts[i].cohortid] = new COHORT(rawcohorts[i]);
@@ -201,11 +262,6 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             });
         },
         enrolCohort : function(e, cohort, node, usersonly) {
-            if (this._preformingAction) {
-                return true;
-            }
-            this._preformingAction = true;
-            this.fire('performingaction');
             var params = {
                 id : this.get(COURSEID),
                 roleid : node.one('.'+CSS.PANELROLES+' select').get('value'),
@@ -223,24 +279,13 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                             if (result.error) {
                                 new M.core.ajaxException(result);
                             } else {
-                                var redirecturl = this.get(URL), redirect = function() {
-                                    if (!usersonly || result.response.users) {
-                                        Y.one(document.body).append(
-                                            Y.Node.create('<div class="corelightbox"></div>')
-                                                .setStyle('height', Y.one(document.body).get('docHeight')+'px')
-                                                .setStyle('opacity', '0.4')
-                                                .append(Y.Node.create('<img alt="loading" />').setAttribute('src', M.cfg.loadingicon)));
-                                        window.location.href = redirecturl;
-                                    }
-                                };
                                 if (result.response && result.response.message) {
-                                    new M.core.alert(result.response).on('complete', redirect, this);
-                                } else {
-                                    redirect();
+                                    new M.core.alert(result.response);
                                 }
+                                var enrolled = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
+                                node.one('.'+CSS.COHORT+' #cohortid_'+cohort.get(COHORTID)).replace(enrolled);
+                                this.set(REQUIREREFRESH, true);
                             }
-                            this._preformingAction = false;
-                            this.fire('actioncomplete');
                         } catch (e) {
                             new M.core.exception(e);
                         }
@@ -275,6 +320,10 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             },
             defaultCohortRole : {
                 value : null
+            },
+            requiresRefresh : {
+                value : false,
+                validator : Y.Lang.isBool
             }
         }
     });
@@ -290,7 +339,7 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             if (this.get(ENROLLED)) {
                 button = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
             } else {
-                button = Y.Node.create('<div></div>');
+                button = Y.Node.create('<div id="cohortid_'+this.get(COHORTID)+'"></div>');
 
                 syncbutton = Y.Node.create('<a class="'+CSS.COHORTBUTTON+' notenrolled enrolcohort">'+M.str.enrol.enrolcohort+'</a>');
                 syncbutton.on('click', function(){this.fire('enrolchort');}, this);
@@ -304,9 +353,6 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             }
             name = Y.Node.create('<div class="'+CSS.COHORTNAME+'">'+this.get(NAME)+'</div>');
             users = Y.Node.create('<div class="'+CSS.COHORTUSERS+'">'+this.get(USERS)+'</div>');
-            if (this.get(ENROLLED)) {
-                button.one(CSS.COHORTENROLLED);
-            }
             return result.append(button).append(name).append(users);
         }
     }, {
index 570539c..39516e1 100644 (file)
@@ -77,7 +77,7 @@ class enrol_guest_plugin extends enrol_plugin {
         if (empty($instance->password)) {
             // Temporarily assign them some guest role for this context
             $context = get_context_instance(CONTEXT_COURSE, $instance->courseid);
-            $USER->access = load_temp_role($context, $CFG->guestroleid, $USER->access);
+            load_temp_course_role($context, $CFG->guestroleid);
             return ENROL_REQUIRE_LOGIN_CACHE_PERIOD + time();
         }
 
@@ -131,7 +131,7 @@ class enrol_guest_plugin extends enrol_plugin {
 
                 // add guest role
                 $context = get_context_instance(CONTEXT_COURSE, $instance->courseid);
-                $USER->access = load_temp_role($context, $CFG->guestroleid, $USER->access);
+                load_temp_course_role($context, $CFG->guestroleid);
 
                 // go to the originally requested page
                 if (!empty($SESSION->wantsurl)) {
index 89cb2d0..a8a6557 100644 (file)
@@ -38,9 +38,6 @@ $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
 
 require_login();
 
-// Refreshing enrolment data in the USER session
-load_all_capabilities();
-
 if ($SESSION->wantsurl) {
     $destination = $SESSION->wantsurl;
     unset($SESSION->wantsurl);
diff --git a/enrol/upgrade.txt b/enrol/upgrade.txt
new file mode 100644 (file)
index 0000000..4fb4c49
--- /dev/null
@@ -0,0 +1,8 @@
+This files describes API changes in /enrol/* - plugins,
+information provided here is intended especially for developers.
+
+=== 2.2 ===
+
+required changes in code:
+* load_temp_role() is deprecated, use load_temp_course_role() instead, temp role not loaded
+* remove_temp_role() is deprecated, use remove_temp_course_roles() instead
index b558e0f..343cdc5 100644 (file)
@@ -1002,6 +1002,14 @@ class grade_structure {
 
     public $courseid;
 
+    /**
+    * Reference to modinfo for current course (for performance, to save
+    * retrieving it from courseid every time). Not actually set except for
+    * the grade_tree type.
+    * @var course_modinfo
+    */
+    public $modinfo;
+
     /**
      * 1D array of grade items only
      */
@@ -1104,8 +1112,6 @@ class grade_structure {
      * @return string header
      */
     public function get_element_header(&$element, $withlink=false, $icon=true, $spacerifnone=false) {
-        global $CFG;
-
         $header = '';
 
         if ($icon) {
@@ -1119,31 +1125,54 @@ class grade_structure {
             return $header;
         }
 
-        $itemtype     = $element['object']->itemtype;
-        $itemmodule   = $element['object']->itemmodule;
-        $iteminstance = $element['object']->iteminstance;
-
-        if ($withlink and $itemtype=='mod' and $iteminstance and $itemmodule) {
-            if ($cm = get_coursemodule_from_instance($itemmodule, $iteminstance, $this->courseid)) {
-
+        if ($withlink) {
+            $url = $this->get_activity_link($element);
+            if ($url) {
                 $a = new stdClass();
                 $a->name = get_string('modulename', $element['object']->itemmodule);
                 $title = get_string('linktoactivity', 'grades', $a);
-                $dir = $CFG->dirroot.'/mod/'.$itemmodule;
 
-                if (file_exists($dir.'/grade.php')) {
-                    $url = $CFG->wwwroot.'/mod/'.$itemmodule.'/grade.php?id='.$cm->id;
-                } else {
-                    $url = $CFG->wwwroot.'/mod/'.$itemmodule.'/view.php?id='.$cm->id;
-                }
-
-                $header = '<a href="'.$url.'" title="'.s($title).'">'.$header.'</a>';
+                $header = html_writer::link($url, $header, array('title' => $title));
             }
         }
 
         return $header;
     }
 
+    private function get_activity_link($element) {
+        global $CFG;
+
+        $itemtype = $element['object']->itemtype;
+        $itemmodule = $element['object']->itemmodule;
+        $iteminstance = $element['object']->iteminstance;
+
+        // Links only for module items that have valid instance, module and are
+        // called from grade_tree with valid modinfo
+        if ($itemtype != 'mod' || !$iteminstance || !$itemmodule || !$this->modinfo) {
+            return null;
+        }
+
+        // Get $cm efficiently and with visibility information using modinfo
+        $instances = $this->modinfo->get_instances();
+        if (empty($instances[$itemmodule][$iteminstance])) {
+            return null;
+        }
+        $cm = $instances[$itemmodule][$iteminstance];
+
+        // Do not add link if activity is not visible to the current user
+        if (!$cm->uservisible) {
+            return null;
+        }
+
+        // If module has grade.php, link to that, otherwise view.php
+        $dir = $CFG->dirroot . '/mod/' . $itemmodule;
+        if (file_exists($dir.'/grade.php')) {
+            return new moodle_url('/mod/' . $itemmodule . '/grade.php', array('id' => $cm->id));
+        } else {
+            return new moodle_url('/mod/' . $itemmodule . '/view.php', array('id' => $cm->id));
+        }
+    }
+
     /**
      * Returns the grade eid - the grade may not exist yet.
      *
@@ -1600,12 +1629,19 @@ class grade_tree extends grade_structure {
      */
     public function grade_tree($courseid, $fillers=true, $category_grade_last=false,
                                $collapsed=null, $nooutcomes=false) {
-        global $USER, $CFG;
+        global $USER, $CFG, $COURSE, $DB;
 
         $this->courseid   = $courseid;
         $this->levels     = array();
         $this->context    = get_context_instance(CONTEXT_COURSE, $courseid);
 
+        if (!empty($COURSE->id) && $COURSE->id == $this->courseid) {
+            $course = $COURSE;
+        } else {
+            $course = $DB->get_record('course', array('id' => $this->courseid));
+        }
+        $this->modinfo = get_fast_modinfo($course);
+
         // get course grade tree
         $this->top_element = grade_category::fetch_course_tree($courseid, true);
 
index f8e1c9e..545d487 100644 (file)
@@ -46,7 +46,7 @@ $string['environmentsub2'] = 'У каждой версии Moodle есть ми
 Пожалуйста, свяжитесь с администратором сервера, если не знаете, как установить новую версию или включить расширения PHP.';
 $string['errorsinenvironment'] = 'Проверка окружения не выполнена!';
 $string['installation'] = 'Установка';
-$string['langdownloaderror'] = 'К несчастью, не удалось установить язык "{$a}". Процесс установки продолжится на английском.';
+$string['langdownloaderror'] = 'К сожалению, не удалось установить язык "{$a}". Процесс установки продолжится на английском.';
 $string['memorylimithelp'] = '<p>Сейчас ограничение памяти в PHP на Вашем сервере установлено в {$a}.</p>
 
 <p>Из-за этого у через какое-то время у Moodle могут возникнуть проблемы с памятью, особенно если у Вас будет много модулей и/или пользователей.</p>
index 03c0ed7..0f626f8 100644 (file)
@@ -168,7 +168,6 @@ $string['configdebug'] = 'If you turn this on, then PHP\'s error_reporting will
 $string['configdebugdisplay'] = 'Set to on, the error reporting will go to the HTML page. This is practical, but breaks XHTML, JS, cookies and HTTP headers in general. Set to off, it will send the output to your server logs, allowing better debugging. The PHP setting error_log controls which log this goes to.';
 $string['configdebugpageinfo'] = 'Enable if you want page information printed in page footer.';
 $string['configdebugsmtp'] = 'Enable verbose debug information during sending of email messages to SMTP server.';
-$string['configdebugstringids'] = 'This option is designed to help translators. It shows the language file and string id beside each string that is output. (Changing this setting will only take effect on the next page load.)';
 $string['configdebugvalidators'] = 'Enable if you want to have links to external validator servers in page footer. You may need to create new user with username <em>w3cvalidator</em>, and enable guest access. These changes may allow unauthorized access to server, do not enable on production sites!';
 $string['configdefaultallowedmodules'] = 'For the courses which fall into the above category, which modules do you want to allow by default <b>when the course is created</b>?';
 $string['configdefaulthomepage'] = 'This determines the home page for logged in users';
@@ -352,6 +351,8 @@ $string['cookiesecure'] = 'Secure cookies only';
 $string['country'] = 'Default country';
 $string['coursecontact'] = 'Course contacts';
 $string['coursecontact_desc'] = 'This setting allows you to control who appears on the course description. Users need to have at least one of these roles in a course to be shown on the course description for that course.';
+$string['courselistshortnames'] = 'Display short names';
+$string['courselistshortnames_desc'] = 'Show short name as well as full name when displaying lists of courses.';
 $string['coursemgmt'] = 'Add/edit courses';
 $string['courseoverview'] = 'Course overview';
 $string['courserequestnotify'] = 'Course request notification';
@@ -403,6 +404,7 @@ $string['debugnormal'] = 'NORMAL: Show errors, warnings and notices';
 $string['debugpageinfo'] = 'Show page information';
 $string['debugsmtp'] = 'Debug email sending';
 $string['debugstringids'] = 'Show origin of languages strings';
+$string['debugstringids_desc'] = 'This option is designed to help translators. When this option is enabled, if you add the parameter strings=1 to a request URL, it will show the language file and string id beside each string that is output.';
 $string['debugvalidators'] = 'Show validator links';
 $string['defaultallowedmodules'] = 'Default allowed modules';
 $string['defaultcity'] = 'Default city';
index 0edcd19..ec04a5c 100644 (file)
@@ -56,3 +56,5 @@ $string['removeuserwarning'] = 'Removing users from a cohort may result in unenr
 $string['selectfromcohort'] = 'Select members from cohort';
 $string['unknowncohort'] = 'Unknown cohort ({$a})!';
 $string['useradded'] = 'User added to cohort "{$a}"';
+$string['search'] = 'Search';
+$string['searchcohort'] = 'Search cohort';
index 5c0fd77..ed05e32 100644 (file)
@@ -57,6 +57,7 @@ $string['requires_completion_3'] = 'Not available unless the activity <strong>{$
 $string['requires_date'] = 'Available from {$a}.';
 $string['requires_date_before'] = 'Available until {$a}.';
 $string['requires_date_both'] = 'Available from {$a->from} to {$a->until}.';
+$string['requires_date_both_single_day'] = 'Available on {$a}.';
 $string['requires_grade_any'] = 'Not available until you have a grade in <strong>{$a}</strong>.';
 $string['requires_grade_max'] = 'Not available unless you get an appropriate score in <strong>{$a}</strong>.';
 $string['requires_grade_min'] = 'Not available until you achieve a required score in <strong>{$a}</strong>.';
index f951261..a7e2563 100644 (file)
@@ -35,8 +35,8 @@ $string['configmoodle'] = 'Moodle has not been configured yet. You need to edit
 $string['erroroccur'] = 'An error has occurred during this process';
 $string['invalidarraysize'] = 'Incorrect size of arrays in params of {$a}';
 $string['invalideventdata'] = 'Incorrect eventadata submitted: {$a}';
-$string['invalidparameter'] = 'Invalid parameter value detected, execution can not continue.';
-$string['invalidresponse'] = 'Invalid response value detected, execution can not continue.';
+$string['invalidparameter'] = 'Invalid parameter value detected';
+$string['invalidresponse'] = 'Invalid response value detected';
 $string['missingconfigversion'] = 'Config table does not contain version, can not continue, sorry.';
 $string['modulenotexist'] = '{$a} module doesn\'t exist';
 $string['morethanonerecordinfetch'] = 'Found more than one record in fetch() !';
index d4f16bd..075ca23 100644 (file)
@@ -79,17 +79,8 @@ $string['errorcatcontextnotvalid'] = 'You cannot execute functions in the catego
 $string['errorcodes'] = 'Error message';
 $string['errorcoursecontextnotvalid'] = 'You cannot execute functions in the course context (course id:{$a->courseid}). The context error message was: {$a->message}';
 $string['errorinvalidparam'] = 'The param "{$a}" is invalid.';
-$string['errorinvalidparamsapi'] = 'Invalid external api parameter';
-$string['errorinvalidparamsdesc'] = 'Invalid external api description';
-$string['errorinvalidresponseapi'] = 'Invalid external api response';
-$string['errorinvalidresponsedesc'] = 'Invalid external api response description';
-$string['errormissingkey'] = 'Missing required key in single structure: {$a}';
 $string['errornotemptydefaultparamarray'] = 'The web service description parameter named \'{$a}\' is an single or multiple structure. The default can only be empty array. Check web service description.';
-$string['erroronlyarray'] = 'Only arrays accepted.';
 $string['erroroptionalparamarray'] = 'The web service description parameter named \'{$a}\' is an single or multiple structure. It can not be set as VALUE_OPTIONAL. Check web service description.';
-$string['errorresponsemissingkey'] = 'Error in response - Missing following required key in a single structure: {$a}';
-$string['errorscalartype'] = 'Scalar type expected, array or object received.';
-$string['errorunexpectedkey'] = 'Unexpected keys ({$a}) detected in parameter array.';
 $string['execute'] = 'Execute';
 $string['executewarnign'] = 'WARNING: If you press execute your database will be modified and changes can not be reverted automatically!';
 $string['externalservice'] = 'External service';
index a2b50e2..21ba4b4 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
  * General users probably only care about
  *
  * Context handling
- * - get_context_instance()
- * - get_context_instance_by_id()
- * - get_parent_contexts()
- * - get_child_contexts()
+ * - context_course::instance($courseid), context_module::instance($cm->id), context_coursecat::instance($catid)
+ * - context::instance_by_id($contextid)
+ * - $context->get_parent_contexts();
+ * - $context->get_child_contexts();
  *
  * Whether the user can do something...
  * - has_capability()
  * - has_all_capabilities()
  * - require_capability()
  * - require_login() (from moodlelib)
+ * - is_siteadmin()
  *
  * What courses has this user access to?
- * - get_user_courses_bycap()
+ * - get_enrolled_users()
  *
  * What users can do X in this context?
  * - get_users_by_capability()
  *
- * Enrol/unenrol
- * - enrol_into_course()
- * - role_assign()/role_unassign()
+ * Modify roles
+ * - role_assign()
+ * - role_unassign()
+ * - role_unassign_all()
  *
  *
- * Advanced use
+ * Advanced - for internal use only
  * - load_all_capabilities()
  * - reload_all_capabilities()
  * - has_capability_in_accessdata()
- * - is_siteadmin()
  * - get_user_access_sitewide()
- * - load_subcontext()
- * - get_role_access_bycontext()
+ * - load_course_context()
+ * - load_role_access_by_context()
+ * - etc.
  *
  * <b>Name conventions</b>
  *
@@ -65,7 +66,7 @@
  * which - for the logged-in user, will be in $USER->access
  *
  * For other users can be generated and passed around (but may also be cached
- * against userid in $ACCESSLIB_PRIVATE->accessdatabyuser.
+ * against userid in $ACCESSLIB_PRIVATE->accessdatabyuser).
  *
  * $accessdata is a multidimensional array, holding
  * role assignments (RAs), role-capabilities-perm sets
  * Things are keyed on "contextpaths" (the path field of
  * the context table) for fast walking up/down the tree.
  * <code>
- * $accessdata[ra][$contextpath]= array($roleid)
- *                [$contextpath]= array($roleid)
- *                [$contextpath]= array($roleid)
+ * $accessdata['ra'][$contextpath] = array($roleid=>$roleid)
+ *                  [$contextpath] = array($roleid=>$roleid)
+ *                  [$contextpath] = array($roleid=>$roleid)
  * </code>
  *
  * Role definitions are stored like this
  * (no cap merge is done - so it's compact)
  *
  * <code>
- * $accessdata[rdef][$contextpath:$roleid][mod/forum:viewpost] = 1
- *                                        [mod/forum:editallpost] = -1
- *                                        [mod/forum:startdiscussion] = -1000
+ * $accessdata['rdef']["$contextpath:$roleid"]['mod/forum:viewpost'] = 1
+ *                                            ['mod/forum:editallpost'] = -1
+ *                                            ['mod/forum:startdiscussion'] = -1000
  * </code>
  *
- * See how has_capability_in_accessdata() walks up/down the tree.
+ * See how has_capability_in_accessdata() walks up the tree.
  *
- * Normally - specially for the logged-in user, we only load
- * rdef and ra down to the course level, but not below. This
- * keeps accessdata small and compact. Below-the-course ra/rdef
- * are loaded as needed. We keep track of which courses we
- * have loaded ra/rdef in
+ * First we only load rdef and ra down to the course level, but not below.
+ * This keeps accessdata small and compact. Below-the-course ra/rdef
+ * are loaded as needed. We keep track of which courses we have loaded ra/rdef in
  * <code>
- * $accessdata[loaded] = array($contextpath, $contextpath)
+ * $accessdata['loaded'] = array($courseid1=>1, $courseid2=>1)
  * </code>
  *
  * <b>Stale accessdata</b>
 
 defined('MOODLE_INTERNAL') || die();
 
-/** permission definitions */
+/** No capability change */
 define('CAP_INHERIT', 0);
-/** permission definitions */
+/** Allow permission, overrides CAP_PREVENT defined in parent contexts */
 define('CAP_ALLOW', 1);
-/** permission definitions */
+/** Prevent permission, overrides CAP_ALLOW defined in parent contexts */
 define('CAP_PREVENT', -1);
-/** permission definitions */
+/** Prohibit permission, overrides everything in current and child contexts */
 define('CAP_PROHIBIT', -1000);
 
-/** context definitions */
+/** System context level - only one instance in every system */
 define('CONTEXT_SYSTEM', 10);
-/** context definitions */
+/** User context level -  one instance for each user describing what others can do to user */
 define('CONTEXT_USER', 30);
-/** context definitions */
+/** Course category context level - one instance for each category */
 define('CONTEXT_COURSECAT', 40);
-/** context definitions */
+/** Course context level - one instances for each course */
 define('CONTEXT_COURSE', 50);
-/** context definitions */
+/** Course module context level - one instance for each course module */
 define('CONTEXT_MODULE', 70);
-/** context definitions */
+/**
+ * Block context level - one instance for each block, sticky blocks are tricky
+ * because ppl think they should be able to override them at lower contexts.
+ * Any other context level instance can be parent of block context.
+ */
 define('CONTEXT_BLOCK', 80);
 
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** Capability allow management of trusts - NOT IMPLEMENTED YET - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_MANAGETRUST', 0x0001);
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** Capability allows changes in system configuration - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_CONFIG',      0x0002);
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** Capability allows user to add scritped content - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_XSS',         0x0004);
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** Capability allows access to personal user information - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_PERSONAL',    0x0008);
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** Capability allows users to add content otehrs may see - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_SPAM',        0x0010);
-/** capability risks - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
+/** capability allows mass delete of data belonging to other users - see {@link http://docs.moodle.org/dev/Hardening_new_Roles_system} */
 define('RISK_DATALOSS',    0x0020);
 
 /** rolename displays - the name as defined in the role definition */
 define('ROLENAME_ORIGINAL', 0);
 /** rolename displays - the name as defined by a role alias */
 define('ROLENAME_ALIAS', 1);
-/** rolename displays - Both, like this:  Role alias (Original)*/
+/** rolename displays - Both, like this:  Role alias (Original) */
 define('ROLENAME_BOTH', 2);
-/** rolename displays - the name as defined in the role definition and the shortname in brackets*/
+/** rolename displays - the name as defined in the role definition and the shortname in brackets */
 define('ROLENAME_ORIGINALANDSHORT', 3);
-/** rolename displays - the name as defined by a role alias, in raw form suitable for editing*/
+/** rolename displays - the name as defined by a role alias, in raw form suitable for editing */
 define('ROLENAME_ALIAS_RAW', 4);
-/** rolename displays - the name is simply short role name*/
+/** rolename displays - the name is simply short role name */
 define('ROLENAME_SHORT', 5);
 
-/**
- * Internal class provides a cache of context information. The cache is
- * restricted in size.
- *
- * This cache should NOT be used outside accesslib.php!
- *
- * @private
- * @author Sam Marshall
- */
-class context_cache {
-    private $contextsbyid;
-    private $contexts;
-    private $count;
-
-    /**
-     * @var int Maximum number of contexts that will be cached.
-     */
-    const MAX_SIZE = 2500;
-    /**
-     * @var int Once contexts reach maximum number, this many will be removed from cache.
-     */
-    const REDUCE_SIZE = 1000;
-
-    /**
-     * Initialises (empty)
-     */
-    public function __construct() {
-        $this->reset();
-    }
-
-    /**
-     * Resets the cache to remove all data.
-     */
-    public function reset() {
-        $this->contexts     = array();
-        $this->contextsbyid = array();
-        $this->count        = 0;
-    }
-
-    /**
-     * Adds a context to the cache. If the cache is full, discards a batch of
-     * older entries.
-     * @param stdClass $context New context to add
-     */
-    public function add(stdClass $context) {
-        if ($this->count >= self::MAX_SIZE) {
-            for ($i=0; $i<self::REDUCE_SIZE; $i++) {
-                if ($first = reset($this->contextsbyid)) {
-                    unset($this->contextsbyid[$first->id]);
-                    unset($this->contexts[$first->contextlevel][$first->instanceid]);
-                }
-            }
-            $this->count -= self::REDUCE_SIZE;
-            if ($this->count < 0) {
-                // most probably caused by the drift, the reset() above
-                // might have returned false because there might not be any more elements
-                $this->count = 0;
-            }
-        }
-
-        $this->contexts[$context->contextlevel][$context->instanceid] = $context;
-        $this->contextsbyid[$context->id] = $context;
-
-        // Note the count may get out of synch slightly if you cache a context
-        // that is already cached, but it doesn't really matter much and I
-        // didn't think it was worth the performance hit.
-        $this->count++;
-    }
-
-    /**
-     * Removes a context from the cache.
-     * @param stdClass $context Context object to remove (must include fields
-     *   ->id, ->contextlevel, ->instanceid at least)
-     */
-    public function remove(stdClass $context) {
-        unset($this->contexts[$context->contextlevel][$context->instanceid]);
-        unset($this->contextsbyid[$context->id]);
-
-        // Again the count may get a bit out of synch if you remove things
-        // that don't exist
-        $this->count--;
-
-        if ($this->count < 0) {
-            $this->count = 0;
-        }
-    }
-
-    /**
-     * Gets a context from the cache.
-     * @param int $contextlevel Context level
-     * @param int $instance Instance ID
-     * @return stdClass|bool Context or false if not in cache
-     */
-    public function get($contextlevel, $instance) {
-        if (isset($this->contexts[$contextlevel][$instance])) {
-            return $this->contexts[$contextlevel][$instance];
-        }
-        return false;
-    }
-
-    /**
-     * Gets a context from the cache based on its id.
-     * @param int $id Context ID
-     * @return stdClass|bool Context or false if not in cache
-     */
-    public function get_by_id($id) {
-        if (isset($this->contextsbyid[$id])) {
-            return $this->contextsbyid[$id];
-        }
-        return false;
-    }
-
-    /**
-     * @return int Count of contexts in cache (approximately)
-     */
-    public function get_approx_count() {
-        return $this->count;
-    }
+/** maximum size of context cache - it is possible to tweak this config.php or in any script before inclusion of context.php */
+if (!defined('CONTEXT_CACHE_MAX_SIZE')) {
+    define('CONTEXT_CACHE_MAX_SIZE', 2500);
 }
 
 /**
@@ -302,19 +190,16 @@ class context_cache {
  * Sadly, a PHP global variable is the only way to implement this, without rewriting everything
  * as methods of a class, instead of functions.
  *
+ * @private
  * @global stdClass $ACCESSLIB_PRIVATE
  * @name $ACCESSLIB_PRIVATE
  */
 global $ACCESSLIB_PRIVATE;
 $ACCESSLIB_PRIVATE = new stdClass();
-$ACCESSLIB_PRIVATE->contexcache      = new context_cache();
-$ACCESSLIB_PRIVATE->systemcontext    = null; // Used in get_system_context
-$ACCESSLIB_PRIVATE->dirtycontexts    = null; // Dirty contexts cache
-$ACCESSLIB_PRIVATE->accessdatabyuser = array(); // Holds the $accessdata structure for users other than $USER
-$ACCESSLIB_PRIVATE->roledefinitions  = array(); // role definitions cache - helps a lot with mem usage in cron
-$ACCESSLIB_PRIVATE->croncache        = array(); // Used in get_role_access
-$ACCESSLIB_PRIVATE->preloadedcourses = array(); // Used in preload_course_contexts.
-$ACCESSLIB_PRIVATE->capabilities     = null; // detailed information about the capabilities
+$ACCESSLIB_PRIVATE->dirtycontexts    = null;    // Dirty contexts cache, loaded from DB once per page
+$ACCESSLIB_PRIVATE->accessdatabyuser = array(); // Holds the cache of $accessdata structure for users (including $USER)
+$ACCESSLIB_PRIVATE->rolepermissions  = array(); // role permissions cache - helps a lot with mem usage
+$ACCESSLIB_PRIVATE->capabilities     = null;    // detailed information about the capabilities
 
 /**
  * Clears accesslib's private caches. ONLY BE USED BY UNIT TESTS
@@ -322,88 +207,62 @@ $ACCESSLIB_PRIVATE->capabilities     = null; // detailed information about the c
  * This method should ONLY BE USED BY UNIT TESTS. It clears all of
  * accesslib's private caches. You need to do this before setting up test data,
  * and also at the end of the tests.
+ *
+ * @return void
  */
 function accesslib_clear_all_caches_for_unit_testing() {
-    global $UNITTEST, $USER, $ACCESSLIB_PRIVATE;
+    global $UNITTEST, $USER;
     if (empty($UNITTEST->running)) {
         throw new coding_exception('You must not call clear_all_caches outside of unit tests.');
     }
-    $ACCESSLIB_PRIVATE->contexcache      = new context_cache();
-    $ACCESSLIB_PRIVATE->systemcontext    = null;
-    $ACCESSLIB_PRIVATE->dirtycontexts    = null;
-    $ACCESSLIB_PRIVATE->accessdatabyuser = array();
-    $ACCESSLIB_PRIVATE->roledefinitions  = array();
-    $ACCESSLIB_PRIVATE->croncache        = array();
-    $ACCESSLIB_PRIVATE->preloadedcourses = array();
-    $ACCESSLIB_PRIVATE->capabilities     = null;
+
+    accesslib_clear_all_caches(true);
 
     unset($USER->access);
 }
 
 /**
- * This is really slow!!! do not use above course context level
+ * Clears accesslib's private caches. ONLY BE USED FROM THIS LIBRARY FILE!
  *
- * @param int $roleid
- * @param object $context
- * @return array
+ * This reset does not touch global $USER.
+ *
+ * @private
+ * @param bool $resetcontexts
+ * @return void
  */
-function get_role_context_caps($roleid, $context) {
-    global $DB;
-
-    //this is really slow!!!! - do not use above course context level!
-    $result = array();
-    $result[$context->id] = array();
+function accesslib_clear_all_caches($resetcontexts) {
+    global $ACCESSLIB_PRIVATE;
 
-    // first emulate the parent context capabilities merging into context
-    $searchcontexts = array_reverse(get_parent_contexts($context));
-    array_push($searchcontexts, $context->id);
-    foreach ($searchcontexts as $cid) {
-        if ($capabilities = $DB->get_records('role_capabilities', array('roleid'=>$roleid, 'contextid'=>$cid))) {
-            foreach ($capabilities as $cap) {
-                if (!array_key_exists($cap->capability, $result[$context->id])) {
-                    $result[$context->id][$cap->capability] = 0;
-                }
-                $result[$context->id][$cap->capability] += $cap->permission;
-            }
-        }
-    }
+    $ACCESSLIB_PRIVATE->dirtycontexts    = null;
+    $ACCESSLIB_PRIVATE->accessdatabyuser = array();
+    $ACCESSLIB_PRIVATE->rolepermissions  = array();
+    $ACCESSLIB_PRIVATE->capabilities     = null;
 
-    // now go through the contexts bellow given context
-    $searchcontexts = array_keys(get_child_contexts($context));
-    foreach ($searchcontexts as $cid) {
-        if ($capabilities = $DB->get_records('role_capabilities', array('roleid'=>$roleid, 'contextid'=>$cid))) {
-            foreach ($capabilities as $cap) {
-                if (!array_key_exists($cap->contextid, $result)) {
-                    $result[$cap->contextid] = array();
-                }
-                $result[$cap->contextid][$cap->capability] = $cap->permission;
-            }
-        }
+    if ($resetcontexts) {
+        context_helper::reset_caches();
     }
-
-    return $result;
 }
 
 /**
  * Gets the accessdata for role "sitewide" (system down to course)
  *
+ * @private
  * @param int $roleid
- * @param array $accessdata defaults to null
  * @return array
  */
-function get_role_access($roleid, $accessdata = null) {
-    global $CFG, $DB;
+function get_role_access($roleid) {
+    global $DB, $ACCESSLIB_PRIVATE;
 
-    /* Get it in 1 cheap DB query...
+    /* Get it in 1 DB query...
      * - relevant role caps at the root and down
      *   to the course level - but not below
      */
-    if (is_null($accessdata)) {
-        $accessdata           = array(); // named list
-        $accessdata['ra']     = array();
-        $accessdata['rdef']   = array();
-        $accessdata['loaded'] = array();
-    }
+
+    //TODO: MUC - this could be cached in shared memory to speed up first page loading, web crawlers, etc.
+
+    $accessdata = get_empty_accessdata();
+
+    $accessdata['ra']['/'.SYSCONTEXTID] = array((int)$roleid => (int)$roleid);
 
     //
     // Overrides for the role IN ANY CONTEXTS
@@ -412,92 +271,37 @@ function get_role_access($roleid, $accessdata = null) {
     $sql = "SELECT ctx.path,
                    rc.capability, rc.permission
               FROM {context} ctx
-              JOIN {role_capabilities} rc
-                   ON rc.contextid=ctx.id
-             WHERE rc.roleid = ?
-                   AND ctx.contextlevel <= ".CONTEXT_COURSE."
-          ORDER BY ctx.depth, ctx.path";
+              JOIN {role_capabilities} rc ON rc.contextid = ctx.id
+         LEFT JOIN {context} cctx
+                   ON (cctx.contextlevel = ".CONTEXT_COURSE." AND ctx.path LIKE ".$DB->sql_concat('cctx.path',"'/%'").")
+             WHERE rc.roleid = ? AND cctx.id IS NULL";
     $params = array($roleid);
 
     // we need extra caching in CLI scripts and cron
-    if (CLI_SCRIPT) {
-        global $ACCESSLIB_PRIVATE;
-
-        if (!isset($ACCESSLIB_PRIVATE->croncache[$roleid])) {
-            $ACCESSLIB_PRIVATE->croncache[$roleid] = array();
-            $rs = $DB->get_recordset_sql($sql, $params);
-            foreach ($rs as $rd) {
-                $ACCESSLIB_PRIVATE->croncache[$roleid][] = $rd;
-            }
-            $rs->close();
-        }
-
-        foreach ($ACCESSLIB_PRIVATE->croncache[$roleid] as $rd) {
-            $k = "{$rd->path}:{$roleid}";
-            $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
-        }
-
-    } else {
-        $rs = $DB->get_recordset_sql($sql, $params);
-        if ($rs->valid()) {
-            foreach ($rs as $rd) {
-                $k = "{$rd->path}:{$roleid}";
-                $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
-            }
-            unset($rd);
-        }
-        $rs->close();
+    $rs = $DB->get_recordset_sql($sql, $params);
+    foreach ($rs as $rd) {
+        $k = "{$rd->path}:{$roleid}";
+        $accessdata['rdef'][$k][$rd->capability] = (int)$rd->permission;
     }
+    $rs->close();
 
-    return $accessdata;
-}
-
-/**
- * Gets the accessdata for role "sitewide" (system down to course)
- *
- * @param int $roleid
- * @param array $accessdata defaults to null
- * @return array
- */
-function get_default_frontpage_role_access($roleid, $accessdata = null) {
-
-    global $CFG, $DB;
-
-    $frontpagecontext = get_context_instance(CONTEXT_COURSE, SITEID);
-    $base = '/'. SYSCONTEXTID .'/'. $frontpagecontext->id;
-
-    //
-    // Overrides for the role in any contexts related to the course
-    //
-    $sql = "SELECT ctx.path,
-                   rc.capability, rc.permission
-              FROM {context} ctx
-              JOIN {role_capabilities} rc
-                   ON rc.contextid=ctx.id
-             WHERE rc.roleid = ?
-                   AND (ctx.id = ".SYSCONTEXTID." OR ctx.path LIKE ?)
-                   AND ctx.contextlevel <= ".CONTEXT_COURSE."
-          ORDER BY ctx.depth, ctx.path";
-    $params = array($roleid, "$base/%");
-
-    $rs = $DB->get_recordset_sql($sql, $params);
-    if ($rs->valid()) {
-        foreach ($rs as $rd) {
-            $k = "{$rd->path}:{$roleid}";
-            $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
+    // share the role definitions
+    foreach ($accessdata['rdef'] as $k=>$unused) {
+        if (!isset($ACCESSLIB_PRIVATE->rolepermissions[$k])) {
+            $ACCESSLIB_PRIVATE->rolepermissions[$k] = $accessdata['rdef'][$k];
         }
-        unset($rd);
+        $accessdata['rdef_count']++;
+        $accessdata['rdef'][$k] =& $ACCESSLIB_PRIVATE->rolepermissions[$k];
     }
-    $rs->close();
 
     return $accessdata;
 }
 
-
 /**
- * Get the default guest role
+ * Get the default guest role, this is used for guest account,
+ * search engine spiders, etc.
  *
- * @return stdClass role
+ * @return stdClass role record
  */
 function get_guest_role() {
     global $CFG, $DB;
@@ -515,7 +319,7 @@ function get_guest_role() {
         if ($guestrole = $DB->get_record('role', array('id'=>$CFG->guestroleid))) {
             return $guestrole;
         } else {
-            //somebody is messing with guest roles, remove incorrect setting and try to find a new one
+            // somebody is messing with guest roles, remove incorrect setting and try to find a new one
             set_config('guestroleid', '');
             return get_guest_role();
         }
@@ -525,7 +329,7 @@ function get_guest_role() {
 /**
  * Check whether a user has a particular capability in a given context.
  *
- * For example::
+ * For example:
  *      $context = get_context_instance(CONTEXT_MODULE, $cm->id);
  *      has_capability('mod/forum:replypost',$context)
  *
@@ -536,16 +340,16 @@ function get_guest_role() {
  * or capabilities with XSS, config or data loss risks.
  *
  * @param string $capability the name of the capability to check. For example mod/forum:view
- * @param object $context the context to check the capability in. You normally get this with {@link get_context_instance}.
+ * @param context $context the context to check the capability in. You normally get this with {@link get_context_instance}.
  * @param integer|object $user A user id or object. By default (null) checks the permissions of the current user.
  * @param boolean $doanything If false, ignores effect of admin role assignment
  * @return boolean true if the user has this capability. Otherwise false.
  */
-function has_capability($capability, $context, $user = null, $doanything = true) {
-    global $USER, $CFG, $DB, $SCRIPT, $ACCESSLIB_PRIVATE;
+function has_capability($capability, context $context, $user = null, $doanything = true) {
+    global $USER, $CFG, $SCRIPT, $ACCESSLIB_PRIVATE;
 
     if (during_initial_install()) {
-        if ($SCRIPT === "/$CFG->admin/index.php" or $SCRIPT === "/$CFG->admin/cliupgrade.php") {
+        if ($SCRIPT === "/$CFG->admin/index.php" or $SCRIPT === "/$CFG->admin/cli/install.php" or $SCRIPT === "/$CFG->admin/cli/install_database.php") {
             // we are in an installer - roles can not work yet
             return true;
         } else {
@@ -557,90 +361,64 @@ function has_capability($capability, $context, $user = null, $doanything = true)
         throw new coding_exception('Legacy capabilities can not be used any more!');
     }
 
-    // the original $CONTEXT here was hiding serious errors
-    // for security reasons do not reuse previous context
-    if (empty($context)) {
-        debugging('Incorrect context specified');
+    if (!is_bool($doanything)) {
+        throw new coding_exception('Capability parameter "doanything" is wierd, only true or false is allowed. This has to be fixed in code.');
+    }
+
+    // capability must exist
+    if (!$capinfo = get_capability_info($capability)) {
+        debugging('Capability "'.$capability.'" was not found! This has to be fixed in code.');
         return false;
     }
-    if (!is_bool($doanything)) {
-        throw new coding_exception('Capability parameter "doanything" is wierd ("'.$doanything.'"). This has to be fixed in code.');
+
+    if (!isset($USER->id)) {
+        // should never happen
+        $USER->id = 0;
     }
 
     // make sure there is a real user specified
     if ($user === null) {
-        $userid = isset($USER->id) ? $USER->id : 0;
+        $userid = $USER->id;
     } else {
         $userid = is_object($user) ? $user->id : $user;
     }
 
-    // capability must exist
-    if (!$capinfo = get_capability_info($capability)) {
-        debugging('Capability "'.$capability.'" was not found! This should be fixed in code.');
+    // make sure forcelogin cuts off not-logged-in users if enabled
+    if (!empty($CFG->forcelogin) and $userid == 0) {
         return false;
     }
+
     // make sure the guest account and not-logged-in users never get any risky caps no matter what the actual settings are.
-    if (($capinfo->captype === 'write') or ((int)$capinfo->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
+    if (($capinfo->captype === 'write') or ($capinfo->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
         if (isguestuser($userid) or $userid == 0) {
             return false;
         }
     }
 
-    if (is_null($context->path) or $context->depth == 0) {
-        //this should not happen
-        $contexts = array(SYSCONTEXTID, $context->id);
-        $context->path = '/'.SYSCONTEXTID.'/'.$context->id;
-        debugging('Context id '.$context->id.' does not have valid path, please use build_context_path()', DEBUG_DEVELOPER);
-
-    } else {
-        $contexts = explode('/', $context->path);
-        array_shift($contexts);
-    }
-
-    if (CLI_SCRIPT && !isset($USER->access)) {
-        // In cron, some modules setup a 'fake' $USER,
-        // ensure we load the appropriate accessdata.
-        if (isset($ACCESSLIB_PRIVATE->accessdatabyuser[$userid])) {
-            $ACCESSLIB_PRIVATE->dirtycontexts = null; //load fresh dirty contexts
+    // somehow make sure the user is not deleted and actually exists
+    if ($userid != 0) {
+        if ($userid == $USER->id and isset($USER->deleted)) {
+            // this prevents one query per page, it is a bit of cheating,
+            // but hopefully session is terminated properly once user is deleted
+            if ($USER->deleted) {
+                return false;
+            }
         } else {
-            load_user_accessdata($userid);
-            $ACCESSLIB_PRIVATE->dirtycontexts = array();
-        }
-        $USER->access = $ACCESSLIB_PRIVATE->accessdatabyuser[$userid];
-
-    } else if (isset($USER->id) && ($USER->id == $userid) && !isset($USER->access)) {
-        // caps not loaded yet - better to load them to keep BC with 1.8
-        // not-logged-in user or $USER object set up manually first time here
-        load_all_capabilities();
-        $ACCESSLIB_PRIVATE->accessdatabyuser = array(); // reset the cache for other users too, the dirty contexts are empty now
-        $ACCESSLIB_PRIVATE->roledefinitions = array();
-    }
-
-    // Load dirty contexts list if needed
-    if (!isset($ACCESSLIB_PRIVATE->dirtycontexts)) {
-        if (isset($USER->access['time'])) {
-            $ACCESSLIB_PRIVATE->dirtycontexts = get_dirty_contexts($USER->access['time']);
-        }
-        else {
-            $ACCESSLIB_PRIVATE->dirtycontexts = array();
+            if (!context_user::instance($userid, IGNORE_MISSING)) {
+                // no user context == invalid userid
+                return false;
+            }
         }
     }
 
-    // Careful check for staleness...
-    if (count($ACCESSLIB_PRIVATE->dirtycontexts) !== 0 and is_contextpath_dirty($contexts, $ACCESSLIB_PRIVATE->dirtycontexts)) {
-        // reload all capabilities - preserving loginas, roleswitches, etc
-        // and then cleanup any marks of dirtyness... at least from our short
-        // term memory! :-)
-        $ACCESSLIB_PRIVATE->accessdatabyuser = array();
-        $ACCESSLIB_PRIVATE->roledefinitions = array();
-
-        if (CLI_SCRIPT) {
-            load_user_accessdata($userid);
-            $USER->access = $ACCESSLIB_PRIVATE->accessdatabyuser[$userid];
-            $ACCESSLIB_PRIVATE->dirtycontexts = array();
-
+    // context path/depth must be valid
+    if (empty($context->path) or $context->depth == 0) {
+        // this should not happen often, each upgrade tries to rebuild the context paths
+        debugging('Context id '.$context->id.' does not have valid path, please use build_context_path()');
+        if (is_siteadmin($userid)) {
+            return true;
         } else {
-            reload_all_capabilities();
+            return false;
         }
     }
 
@@ -672,49 +450,29 @@ function has_capability($capability, $context, $user = null, $doanything = true)
         }
     }
 
-    // divulge how many times we are called
-    //// error_log("has_capability: id:{$context->id} path:{$context->path} userid:$userid cap:$capability");
+    // Careful check for staleness...
+    $context->reload_if_dirty();
 
-    if (isset($USER->id) && ($USER->id == $userid)) { // we must accept strings and integers in $userid
-        //
-        // For the logged in user, we have $USER->access
-        // which will have all RAs and caps preloaded for
-        // course and above contexts.
-        //
-        // Contexts below courses && contexts that do not
-        // hang from courses are loaded into $USER->access
-        // on demand, and listed in $USER->access[loaded]
-        //
-        if ($context->contextlevel <= CONTEXT_COURSE) {
-            // Course and above are always preloaded
-            return has_capability_in_accessdata($capability, $context, $USER->access);
+    if ($USER->id == $userid) {
+        if (!isset($USER->access)) {
+            load_all_capabilities();
         }
-        // Load accessdata for below-the-course contexts
-        if (!path_inaccessdata($context->path,$USER->access)) {
-            // error_log("loading access for context {$context->path} for $capability at {$context->contextlevel} {$context->id}");
-            // $bt = debug_backtrace();
-            // error_log("bt {$bt[0]['file']} {$bt[0]['line']}");
-            load_subcontext($USER->id, $context, $USER->access);
-        }
-        return has_capability_in_accessdata($capability, $context, $USER->access);
-    }
+        $access =& $USER->access;
 
-    if (!isset($ACCESSLIB_PRIVATE->accessdatabyuser[$userid])) {
-        load_user_accessdata($userid);
+    } else {
+        // make sure user accessdata is really loaded
+        get_user_accessdata($userid, true);
+        $access =& $ACCESSLIB_PRIVATE->accessdatabyuser[$userid];
     }
 
-    if ($context->contextlevel <= CONTEXT_COURSE) {
-        // Course and above are always preloaded
-        return has_capability_in_accessdata($capability, $context, $ACCESSLIB_PRIVATE->accessdatabyuser[$userid]);
-    }
-    // Load accessdata for below-the-course contexts as needed
-    if (!path_inaccessdata($context->path, $ACCESSLIB_PRIVATE->accessdatabyuser[$userid])) {
-        // error_log("loading access for context {$context->path} for $capability at {$context->contextlevel} {$context->id}");
-        // $bt = debug_backtrace();
-        // error_log("bt {$bt[0]['file']} {$bt[0]['line']}");
-        load_subcontext($userid, $context, $ACCESSLIB_PRIVATE->accessdatabyuser[$userid]);
+
+    // Load accessdata for below-the-course context if necessary,
+    // all contexts at and above all courses are already loaded
+    if ($context->contextlevel != CONTEXT_COURSE and $coursecontext = $context->get_course_context(false)) {
+        load_course_context($userid, $coursecontext, $access);
     }
-    return has_capability_in_accessdata($capability, $context, $ACCESSLIB_PRIVATE->accessdatabyuser[$userid]);
+
+    return has_capability_in_accessdata($capability, $context, $access);
 }
 
 /**
@@ -724,21 +482,14 @@ function has_capability($capability, $context, $user = null, $doanything = true)
  * the capabilities that most users are likely to have first in the list for best
  * performance.
  *
- * There are probably tricks that could be done to improve the performance here, for example,
- * check the capabilities that are already cached first.
- *
  * @see has_capability()
  * @param array $capabilities an array of capability names.
- * @param object $context the context to check the capability in. You normally get this with {@link get_context_instance}.
+ * @param context $context the context to check the capability in. You normally get this with {@link get_context_instance}.
  * @param integer $userid A user id. By default (null) checks the permissions of the current user.
  * @param boolean $doanything If false, ignore effect of admin role assignment
  * @return boolean true if the user has any of these capabilities. Otherwise false.
  */
-function has_any_capability($capabilities, $context, $userid = null, $doanything = true) {
-    if (!is_array($capabilities)) {
-        debugging('Incorrect $capabilities parameter in has_any_capabilities() call - must be an array');
-        return false;
-    }
+function has_any_capability(array $capabilities, context $context, $userid = null, $doanything = true) {
     foreach ($capabilities as $capability) {
         if (has_capability($capability, $context, $userid, $doanything)) {
             return true;
@@ -754,21 +505,14 @@ function has_any_capability($capabilities, $context, $userid = null, $doanything
  * the capabilities that fewest users are likely to have first in the list for best
  * performance.
  *
- * There are probably tricks that could be done to improve the performance here, for example,
- * check the capabilities that are already cached first.
- *
  * @see has_capability()
  * @param array $capabilities an array of capability names.
- * @param object $context the context to check the capability in. You normally get this with {@link get_context_instance}.
+ * @param context $context the context to check the capability in. You normally get this with {@link get_context_instance}.
  * @param integer $userid A user id. By default (null) checks the permissions of the current user.
  * @param boolean $doanything If false, ignore effect of admin role assignment
  * @return boolean true if the user has all of these capabilities. Otherwise false.
  */
-function has_all_capabilities($capabilities, $context, $userid = null, $doanything = true) {
-    if (!is_array($capabilities)) {
-        debugging('Incorrect $capabilities parameter in has_all_capabilities() call - must be an array');
-        return false;
-    }
+function has_all_capabilities(array $capabilities, context $context, $userid = null, $doanything = true) {
     foreach ($capabilities as $capability) {
         if (!has_capability($capability, $context, $userid, $doanything)) {
             return false;
@@ -783,8 +527,8 @@ function has_all_capabilities($capabilities, $context, $userid = null, $doanythi
  * Please note that use of proper capabilities is always encouraged,
  * this function is supposed to be used from core or for temporary hacks.
  *
- * @param   int|object  $user_or_id user id or user object
- * @returns bool true if user is one of the administrators, false otherwise
+ * @param  int|stdClass  $user_or_id user id or user object
+ * @return bool true if user is one of the administrators, false otherwise
  */
 function is_siteadmin($user_or_id = null) {
     global $CFG, $USER;
@@ -797,7 +541,6 @@ function is_siteadmin($user_or_id = null) {
         return false;
     }
     if (!empty($user_or_id->id)) {
-        // we support
         $userid = $user_or_id->id;
     } else {
         $userid = $user_or_id;
@@ -811,8 +554,8 @@ function is_siteadmin($user_or_id = null) {
  * Returns true if user has at least one role assign
  * of 'coursecontact' role (is potentially listed in some course descriptions).
  *
- * @param $userid
- * @return stdClass
+ * @param int $userid
+ * @return bool
  */
 function has_coursecontact_role($userid) {
     global $DB, $CFG;
@@ -826,52 +569,11 @@ function has_coursecontact_role($userid) {
     return $DB->record_exists_sql($sql, array('userid'=>$userid));
 }
 
-/**
- * @param string $path
- * @return string
- */
-function get_course_from_path($path) {
-    // assume that nothing is more than 1 course deep
-    if (preg_match('!^(/.+)/\d+$!', $path, $matches)) {
-        return $matches[1];
-    }
-    return false;
-}
-
-/**
- * @param string $path
- * @param array $accessdata
- * @return bool
- */
-function path_inaccessdata($path, $accessdata) {
-    if (empty($accessdata['loaded'])) {
-        return false;
-    }
-
-    // assume that contexts hang from sys or from a course
-    // this will only work well with stuff that hangs from a course
-    if (in_array($path, $accessdata['loaded'], true)) {
-            // error_log("found it!");
-        return true;
-    }
-    $base = '/' . SYSCONTEXTID;
-    while (preg_match('!^(/.+)/\d+$!', $path, $matches)) {
-        $path = $matches[1];
-        if ($path === $base) {
-            return false;
-        }
-        if (in_array($path, $accessdata['loaded'], true)) {
-            return true;
-        }
-    }
-    return false;
-}
-
 /**
  * Does the user have a capability to do something?
  *
  * Walk the accessdata array and return true/false.
- * Deals with prohibits, roleswitching, aggregating
+ * Deals with prohibits, role switching, aggregating
  * capabilities, etc.
  *
  * The main feature of here is being FAST and with no
@@ -879,12 +581,6 @@ function path_inaccessdata($path, $accessdata) {
  *
  * Notes:
  *
- * Switch Roles exits early
- * ------------------------
- * cap checks within a switchrole need to exit early
- * in our bottom up processing so they don't "see" that
- * there are real RAs that can do all sorts of things.
- *
  * Switch Role merges with default role
  * ------------------------------------
  * If you are a teacher in course X, you have at least
@@ -901,26 +597,25 @@ function path_inaccessdata($path, $accessdata) {
  * and then verify if user has at least one role with allow
  * and at the same time no role with prohibit.
  *
+ * @private
  * @param string $capability
- * @param object $context
+ * @param context $context
  * @param array $accessdata
  * @return bool
  */
-function has_capability_in_accessdata($capability, $context, array $accessdata) {
+function has_capability_in_accessdata($capability, context $context, array &$accessdata) {
     global $CFG;
 
-    if (empty($context->id)) {
-        throw new coding_exception('Invalid context specified');
-    }
-
     // Build $paths as a list of current + all parent "paths" with order bottom-to-top
-    $contextids = explode('/', trim($context->path, '/'));
-    $paths = array($context->path);
-    while ($contextids) {
-        array_pop($contextids);
-        $paths[] = '/' . implode('/', $contextids);
+    $path = $context->path;
+    $paths = array($path);
+    while($path = rtrim($path, '0123456789')) {
+        $path = rtrim($path, '/');
+        if ($path === '') {
+            break;
+        }
+        $paths[] = $path;
     }
-    unset($contextids);
 
     $roles = array();
     $switchedrole = false;
@@ -950,56 +645,25 @@ function has_capability_in_accessdata($capability, $context, array $accessdata)
     }
 
     // Now find out what access is given to each role, going bottom-->up direction
+    $allowed = false;
     foreach ($roles as $roleid => $ignored) {
         foreach ($paths as $path) {
             if (isset($accessdata['rdef']["{$path}:$roleid"][$capability])) {
                 $perm = (int)$accessdata['rdef']["{$path}:$roleid"][$capability];
-                if ($perm === CAP_PROHIBIT or is_null($roles[$roleid])) {
+                if ($perm === CAP_PROHIBIT) {
+                    // any CAP_PROHIBIT found means no permission for the user
+                    return false;
+                }
+                if (is_null($roles[$roleid])) {
                     $roles[$roleid] = $perm;
                 }
             }
         }
-    }
-    // any CAP_PROHIBIT found means no permission for the user
-    if (array_search(CAP_PROHIBIT, $roles) !== false) {
-        return false;
+        // CAP_ALLOW in any role means the user has a permission, we continue only to detect prohibits
+        $allowed = ($allowed or $roles[$roleid] === CAP_ALLOW);
     }
 
-    // at least one CAP_ALLOW means the user has a permission
-    return (array_search(CAP_ALLOW, $roles) !== false);
-}
-
-/**
- * @param object $context
- * @param array $accessdata
- * @return array
- */
-function aggregate_roles_from_accessdata($context, $accessdata) {
-
-    $path = $context->path;
-
-    // build $contexts as a list of "paths" of the current
-    // contexts and parents with the order top-to-bottom
-    $contexts = array($path);
-    while (preg_match('!^(/.+)/\d+$!', $path, $matches)) {
-        $path = $matches[1];
-        array_unshift($contexts, $path);
-    }
-
-    $cc = count($contexts);
-
-    $roles = array();
-    // From the bottom up...
-    for ($n=$cc-1; $n>=0; $n--) {
-        $ctxp = $contexts[$n];
-        if (isset($accessdata['ra'][$ctxp]) && count($accessdata['ra'][$ctxp])) {
-            // Found assignments on this leaf
-            $addroles = $accessdata['ra'][$ctxp];
-            $roles    = array_merge($roles, $addroles);
-        }
-    }
-
-    return array_unique($roles);
+    return $allowed;
 }
 
 /**
@@ -1014,343 +678,269 @@ function aggregate_roles_from_accessdata($context, $accessdata) {
  * @see has_capability()
  *
  * @param string $capability the name of the capability to check. For example mod/forum:view
- * @param object $context the context to check the capability in. You normally get this with {@link get_context_instance}.
- * @param integer $userid A user id. By default (null) checks the permissions of the current user.
+ * @param context $context the context to check the capability in. You normally get this with {@link get_context_instance}.
+ * @param int $userid A user id. By default (null) checks the permissions of the current user.
  * @param bool $doanything If false, ignore effect of admin role assignment
- * @param string $errorstring The error string to to user. Defaults to 'nopermissions'.
+ * @param string $errormessage The error string to to user. Defaults to 'nopermissions'.
  * @param string $stringfile The language file to load the error string from. Defaults to 'error'.
  * @return void terminates with an error if the user does not have the given capability.
  */
-function require_capability($capability, $context, $userid = null, $doanything = true,
+function require_capability($capability, context $context, $userid = null, $doanything = true,
                             $errormessage = 'nopermissions', $stringfile = '') {
     if (!has_capability($capability, $context, $userid, $doanything)) {
         throw new required_capability_exception($context, $capability, $errormessage, $stringfile);
     }
 }
 
-/**
- * Get an array of courses where cap requested is available
- * and user is enrolled, this can be relatively slow.
- *
- * @param string $capability - name of the capability
- * @param array  $accessdata_ignored
- * @param bool   $doanything_ignored
- * @param string $sort - sorting fields - prefix each fieldname with "c."
- * @param array  $fields - additional fields you are interested in...
- * @param int    $limit_ignored
- * @return array $courses - ordered array of course objects - see notes above
- */
-function get_user_courses_bycap($userid, $cap, $accessdata_ignored, $doanything_ignored, $sort = 'c.sortorder ASC', $fields = null, $limit_ignored = 0) {
-
-    //TODO: this should be most probably deprecated
-
-    $courses = enrol_get_users_courses($userid, true, $fields, $sort);
-    foreach ($courses as $id=>$course) {
-        $context = get_context_instance(CONTEXT_COURSE, $id);
-        if (!has_capability($cap, $context, $userid)) {
-            unset($courses[$id]);
-        }
-    }
-
-    return $courses;
-}
-
-
 /**
  * Return a nested array showing role assignments
  * all relevant role capabilities for the user at
  * site/course_category/course levels
  *
  * We do _not_ delve deeper than courses because the number of
- * overrides at the module/block levels is HUGE.
+ * overrides at the module/block levels can be HUGE.
  *
- * [ra]   => [/path/][]=roleid
- * [rdef] => [/path/:roleid][capability]=permission
- * [loaded] => array('/path', '/path')
+ * [ra]   => [/path][roleid]=roleid
+ * [rdef] => [/path:roleid][capability]=permission
  *
+ * @private
  * @param int $userid - the id of the user
- * @return array
+ * @return array access info array
  */
 function get_user_access_sitewide($userid) {
-    global $CFG, $DB;
+    global $CFG, $DB, $ACCESSLIB_PRIVATE;
 
-    /* Get in 3 cheap DB queries...
+    /* Get in a few cheap DB queries...
      * - role assignments
      * - relevant role caps
      *   - above and within this user's RAs
      *   - below this user's RAs - limited to course level
      */
 
-    $accessdata = array(); // named list
-    $accessdata['ra']     = array();
-    $accessdata['rdef']   = array();
-    $accessdata['loaded'] = array();
+    // raparents collects paths & roles we need to walk up the parenthood to build the minimal rdef
+    $raparents = array();
+    $accessdata = get_empty_accessdata();
 
-    //
-    // Role assignments
-    //
+    // start with the default role
+    if (!empty($CFG->defaultuserroleid)) {
+        $syscontext = context_system::instance();
+        $accessdata['ra'][$syscontext->path][(int)$CFG->defaultuserroleid] = (int)$CFG->defaultuserroleid;
+        $raparents[$CFG->defaultuserroleid][$syscontext->path] = $syscontext->path;
+    }
+
+    // load the "default frontpage role"
+    if (!empty($CFG->defaultfrontpageroleid)) {
+        $frontpagecontext = context_course::instance(get_site()->id);
+        if ($frontpagecontext->path) {
+            $accessdata['ra'][$frontpagecontext->path][(int)$CFG->defaultfrontpageroleid] = (int)$CFG->defaultfrontpageroleid;
+            $raparents[$CFG->defaultfrontpageroleid][$frontpagecontext->path] = $frontpagecontext->path;
+        }
+    }
+
+    // preload every assigned role at and above course context
     $sql = "SELECT ctx.path, ra.roleid
               FROM {role_assignments} ra
-              JOIN {context} ctx ON ctx.id=ra.contextid
-             WHERE ra.userid = ? AND ctx.contextlevel <= ".CONTEXT_COURSE;
-    $params = array($userid);
-    $rs = $DB->get_recordset_sql($sql, $params);
+              JOIN {context} ctx ON ctx.id = ra.contextid
+         LEFT JOIN {context} cctx
+                   ON (cctx.contextlevel = ".CONTEXT_COURSE." AND ctx.path LIKE ".$DB->sql_concat('cctx.path',"'/%'").")
+             WHERE ra.userid = :userid AND cctx.id IS NULL";
 
-    //
-    // raparents collects paths & roles we need to walk up
-    // the parenthood to build the rdef
-    //
-    $raparents = array();
-    if ($rs) {
-        foreach ($rs as $ra) {
-            // RAs leafs are arrays to support multi
-            // role assignments...
-            if (!isset($accessdata['ra'][$ra->path])) {
-                $accessdata['ra'][$ra->path] = array();
-            }
-            $accessdata['ra'][$ra->path][$ra->roleid] = $ra->roleid;
 
-            // Concatenate as string the whole path (all related context)
-            // for this role. This is damn faster than using array_merge()
-            // Will unique them later
-            if (isset($raparents[$ra->roleid])) {
-                $raparents[$ra->roleid] .= $ra->path;
-            } else {
-                $raparents[$ra->roleid] = $ra->path;
-            }
-        }
-        unset($ra);
-        $rs->close();
+    $params = array('userid'=>$userid);
+    $rs = $DB->get_recordset_sql($sql, $params);
+    foreach ($rs as $ra) {
+        // RAs leafs are arrays to support multi-role assignments...
+        $accessdata['ra'][$ra->path][(int)$ra->roleid] = (int)$ra->roleid;
+        $raparents[$ra->roleid][$ra->path] = $ra->path;
     }
+    $rs->close();
 
-    // Walk up the tree to grab all the roledefs
-    // of interest to our user...
-    //
-    // NOTE: we use a series of IN clauses here - which
-    // might explode on huge sites with very convoluted nesting of
-    // categories... - extremely unlikely that the number of categories
-    // and roletypes is so large that we hit the limits of IN()
-    $clauses = '';
-    $cparams = array();
-    foreach ($raparents as $roleid=>$strcontexts) {
-        $contexts = implode(',', array_unique(explode('/', trim($strcontexts, '/'))));
-        if ($contexts ==! '') {
-            if ($clauses) {
-                $clauses .= ' OR ';
-            }
-            $clauses .= "(roleid=? AND contextid IN ($contexts))";
-            $cparams[] = $roleid;
-        }
+    if (empty($raparents)) {
+        return $accessdata;
     }
 
-    if ($clauses !== '') {
-        $sql = "SELECT ctx.path, rc.roleid, rc.capability, rc.permission
-                  FROM {role_capabilities} rc
-                  JOIN {context} ctx ON rc.contextid=ctx.id
-                 WHERE $clauses";
+    // now get overrides of interesting roles in all interesting child contexts
+    // hopefully we will not run out of SQL limits here,
+    // users would have to have very many roles above course context...
+    $sqls = array();
+    $params = array();
 
-        unset($clauses);
-        $rs = $DB->get_recordset_sql($sql, $cparams);
+    static $cp = 0;
+    foreach ($raparents as $roleid=>$paths) {
+        $cp++;
+        list($paths, $rparams) = $DB->get_in_or_equal($paths, SQL_PARAMS_NAMED, 'p'.$cp.'_');
+        $params = array_merge($params, $rparams);
+        $params['r'.$cp] = $roleid;
+        $sqls[] = "(SELECT ctx.path, rc.roleid, rc.capability, rc.permission
+                     FROM {role_capabilities} rc
+                     JOIN {context} ctx
+                          ON (ctx.id = rc.contextid)
+                LEFT JOIN {context} cctx
+                          ON (cctx.contextlevel = ".CONTEXT_COURSE."
+                              AND ctx.path LIKE ".$DB->sql_concat('cctx.path',"'/%'").")
+                     JOIN {context} pctx
+                          ON (pctx.path $paths
+                              AND (ctx.id = pctx.id
+                                   OR ctx.path LIKE ".$DB->sql_concat('pctx.path',"'/%'")."
+                                   OR pctx.path LIKE ".$DB->sql_concat('ctx.path',"'/%'")."))
+                    WHERE rc.roleid = :r{$cp}
+                          AND cctx.id IS NULL)";
+    }
+
+    // fixed capability order is necessary for rdef dedupe
+    $rs = $DB->get_recordset_sql(implode("\nUNION\n", $sqls). "ORDER BY capability", $params);
 
-        if ($rs) {
-            foreach ($rs as $rd) {
-                $k = "{$rd->path}:{$rd->roleid}";
-                $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
-            }
-            unset($rd);
-            $rs->close();
-        }
+    foreach ($rs as $rd) {
+        $k = $rd->path.':'.$rd->roleid;
+        $accessdata['rdef'][$k][$rd->capability] = (int)$rd->permission;
     }
+    $rs->close();
 
-    //
-    // Overrides for the role assignments IN SUBCONTEXTS
-    // (though we still do _not_ go below the course level.
-    //
-    // NOTE that the JOIN w sctx is with 3-way triangulation to
-    // catch overrides to the applicable role in any subcontext, based
-    // on the path field of the parent.
-    //
-    $sql = "SELECT sctx.path, ra.roleid,
-                   ctx.path AS parentpath,
-                   rco.capability, rco.permission
-              FROM {role_assignments} ra
-              JOIN {context} ctx
-                   ON ra.contextid=ctx.id
-              JOIN {context} sctx
-                   ON (sctx.path LIKE " . $DB->sql_concat('ctx.path',"'/%'"). " )
-              JOIN {role_capabilities} rco
-                   ON (rco.roleid=ra.roleid AND rco.contextid=sctx.id)
-             WHERE ra.userid = ?
-                   AND ctx.contextlevel <= ".CONTEXT_COURSECAT."
-                   AND sctx.contextlevel <= ".CONTEXT_COURSE."
-          ORDER BY sctx.depth, sctx.path, ra.roleid";
-    $params = array($userid);
-    $rs = $DB->get_recordset_sql($sql, $params);
-    if ($rs) {
-        foreach ($rs as $rd) {
-            $k = "{$rd->path}:{$rd->roleid}";
-            $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
+    // share the role definitions
+    foreach ($accessdata['rdef'] as $k=>$unused) {
+        if (!isset($ACCESSLIB_PRIVATE->rolepermissions[$k])) {
+            $ACCESSLIB_PRIVATE->rolepermissions[$k] = $accessdata['rdef'][$k];
         }
-        unset($rd);
-        $rs->close();
+        $accessdata['rdef_count']++;
+        $accessdata['rdef'][$k] =& $ACCESSLIB_PRIVATE->rolepermissions[$k];
     }
+
     return $accessdata;
 }
 
 /**
- * Add to the access ctrl array the data needed by a user for a given context
+ * Add to the access ctrl array the data needed by a user for a given course.
  *
- * @param integer $userid the id of the user
- * @param object $context needs path!
- * @param array $accessdata accessdata array
- * @return void
+ * This function injects all course related access info into the accessdata array.
+ *
+ * @private
+ * @param int $userid the id of the user
+ * @param context_course $coursecontext course context
+ * @param array $accessdata accessdata array (modified)
+ * @return void modifies $accessdata parameter
  */
-function load_subcontext($userid, $context, &$accessdata) {
-    global $CFG, $DB;
+function load_course_context($userid, context_course $coursecontext, &$accessdata) {
+    global $DB, $CFG, $ACCESSLIB_PRIVATE;
 
-    /* Get the additional RAs and relevant rolecaps
-     * - role assignments - with role_caps
-     * - relevant role caps
-     *   - above this user's RAs
-     *   - below this user's RAs - limited to course level
-     */
+    if (empty($coursecontext->path)) {
+        // weird, this should not happen
+        return;
+    }
 
-    $base = "/" . SYSCONTEXTID;
+    if (isset($accessdata['loaded'][$coursecontext->instanceid])) {
+        // already loaded, great!
+        return;
+    }
 
-    //
-    // Replace $context with the target context we will
-    // load. Normally, this will be a course context, but
-    // may be a different top-level context.
-    //
-    // We have 3 cases
-    //
-    // - Course
-    // - BLOCK/PERSON/USER/COURSE(sitecourse) hanging from SYSTEM
-    // - BLOCK/MODULE/GROUP hanging from a course
-    //
-    // For course contexts, we _already_ have the RAs
-    // but the cost of re-fetching is minimal so we don't care.
-    //
-    if ($context->contextlevel !== CONTEXT_COURSE
-        && $context->path !== "$base/{$context->id}") {
-        // Case BLOCK/MODULE/GROUP hanging from a course
-        // Assumption: the course _must_ be our parent
-        // If we ever see stuff nested further this needs to
-        // change to do 1 query over the exploded path to
-        // find out which one is the course
-        $courses = explode('/',get_course_from_path($context->path));
-        $targetid = array_pop($courses);
-        $context = get_context_instance_by_id($targetid);
+    $roles = array();
 
-    }
+    if (empty($userid)) {
+        if (!empty($CFG->notloggedinroleid)) {
+            $roles[$CFG->notloggedinroleid] = $CFG->notloggedinroleid;
+        }
 
-    //
-    // Role assignments in the context and below
-    //
-    $sql = "SELECT ctx.path, ra.roleid
-              FROM {role_assignments} ra
-              JOIN {context} ctx
-                   ON ra.contextid=ctx.id
-             WHERE ra.userid = ?
-                   AND (ctx.path = ? OR ctx.path LIKE ?)
-          ORDER BY ctx.depth, ctx.path, ra.roleid";
-    $params = array($userid, $context->path, $context->path."/%");
-    $rs = $DB->get_recordset_sql($sql, $params);
+    } else if (isguestuser($userid)) {
+        if ($guestrole = get_guest_role()) {
+            $roles[$guestrole->id] = $guestrole->id;
+        }
 
-    //
-    // Read in the RAs, preventing duplicates
-    //
-    if ($rs) {
-        $localroles = array();
-        $lastseen  = '';
+    } else {
+        // Interesting role assignments at, above and below the course context
+        list($parentsaself, $params) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'pc_');
+        $params['userid'] = $userid;
+        $params['children'] = $coursecontext->path."/%";
+        $sql = "SELECT ra.*, ctx.path
+                  FROM {role_assignments} ra
+                  JOIN {context} ctx ON ra.contextid = ctx.id
+                 WHERE ra.userid = :userid AND (ctx.id $parentsaself OR ctx.path LIKE :children)";
+        $rs = $DB->get_recordset_sql($sql, $params);
+
+        // add missing role definitions
         foreach ($rs as $ra) {
-            if (!isset($accessdata['ra'][$ra->path])) {
-                $accessdata['ra'][$ra->path] = array();
-            }
-            // only add if is not a repeat caused
-            // by capability join...
-            // (this check is cheaper than in_array())
-            if ($lastseen !== $ra->path.':'.$ra->roleid) {
-                $lastseen = $ra->path.':'.$ra->roleid;
-                $accessdata['ra'][$ra->path][$ra->roleid] = $ra->roleid;
-                array_push($localroles,           $ra->roleid);
-            }
+            $accessdata['ra'][$ra->path][(int)$ra->roleid] = (int)$ra->roleid;
+            $roles[$ra->roleid] = $ra->roleid;
         }
         $rs->close();
-    }
 
-    //
-    // Walk up and down the tree to grab all the roledefs
-    // of interest to our user...
-    //
-    // NOTES
-    // - we use IN() but the number of roles is very limited.
-    //
-    $courseroles    = aggregate_roles_from_accessdata($context, $accessdata);
+        // add the "default frontpage role" when on the frontpage
+        if (!empty($CFG->defaultfrontpageroleid)) {
+            $frontpagecontext = context_course::instance(get_site()->id);
+            if ($frontpagecontext->id == $coursecontext->id) {
+                $roles[$CFG->defaultfrontpageroleid] = $CFG->defaultfrontpageroleid;
+            }
+        }
 
-    // Do we have any interesting "local" roles?
-    $localroles = array_diff($localroles,$courseroles); // only "new" local roles
-    $wherelocalroles='';
-    if (count($localroles)) {
-        // Role defs for local roles in 'higher' contexts...
-        $contexts = substr($context->path, 1); // kill leading slash
-        $contexts = str_replace('/', ',', $contexts);
-        $localroleids = implode(',',$localroles);
-        $wherelocalroles="OR (rc.roleid IN ({$localroleids})
-                              AND ctx.id IN ($contexts))" ;
+        // do not forget the default role
+        if (!empty($CFG->defaultuserroleid)) {
+            $roles[$CFG->defaultuserroleid] = $CFG->defaultuserroleid;
+        }
     }
 
-    // We will want overrides for all of them
-    $whereroles = '';
-    if ($roleids  = implode(',',array_merge($courseroles,$localroles))) {
-        $whereroles = "rc.roleid IN ($roleids) AND";
+    if (!$roles) {
+        // weird, default roles must be missing...
+        $accessdata['loaded'][$coursecontext->instanceid] = 1;
+        return;
     }
+
+    // now get overrides of interesting roles in all interesting contexts (this course + children + parents)
+    $params = array('c'=>$coursecontext->id);
+    list($parentsaself, $rparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'pc_');
+    $params = array_merge($params, $rparams);
+    list($roleids, $rparams) = $DB->get_in_or_equal($roles, SQL_PARAMS_NAMED, 'r_');
+    $params = array_merge($params, $rparams);
+
     $sql = "SELECT ctx.path, rc.roleid, rc.capability, rc.permission
-              FROM {role_capabilities} rc
-              JOIN {context} ctx
-                   ON rc.contextid=ctx.id
-             WHERE ($whereroles
-                    (ctx.id=? OR ctx.path LIKE ?))
-                   $wherelocalroles
-          ORDER BY ctx.depth ASC, ctx.path DESC, rc.roleid ASC ";
-    $params = array($context->id, $context->path."/%");
+                 FROM {role_capabilities} rc
+                 JOIN {context} ctx
+                      ON (ctx.id = rc.contextid)
+                 JOIN {context} cctx
+                      ON (cctx.id = :c
+                          AND (ctx.id $parentsaself OR ctx.path LIKE ".$DB->sql_concat('cctx.path',"'/%'")."))
+                WHERE rc.roleid $roleids
+             ORDER BY rc.capability"; // fixed capability order is necessary for rdef dedupe
+    $rs = $DB->get_recordset_sql($sql, $params);
 
     $newrdefs = array();
-    $rs = $DB->get_recordset_sql($sql, $params);
     foreach ($rs as $rd) {
-        $k = "{$rd->path}:{$rd->roleid}";
-        if (!array_key_exists($k, $newrdefs)) {
-            $newrdefs[$k] = array();
+        $k = $rd->path.':'.$rd->roleid;
+        if (isset($accessdata['rdef'][$k])) {
+            continue;
         }
-        $newrdefs[$k][$rd->capability] = $rd->permission;
+        $newrdefs[$k][$rd->capability] = (int)$rd->permission;
     }
     $rs->close();
 
-    compact_rdefs($newrdefs);
-    foreach ($newrdefs as $key=>$value) {
-        $accessdata['rdef'][$key] =& $newrdefs[$key];
+    // share new role definitions
+    foreach ($newrdefs as $k=>$unused) {
+        if (!isset($ACCESSLIB_PRIVATE->rolepermissions[$k])) {
+            $ACCESSLIB_PRIVATE->rolepermissions[$k] = $newrdefs[$k];
+        }
+        $accessdata['rdef_count']++;
+        $accessdata['rdef'][$k] =& $ACCESSLIB_PRIVATE->rolepermissions[$k];
     }
 
-    // error_log("loaded {$context->path}");
-    $accessdata['loaded'][] = $context->path;
+    $accessdata['loaded'][$coursecontext->instanceid] = 1;
+
+    // we want to deduplicate the USER->access from time to time, this looks like a good place,
+    // because we have to do it before the end of session
+    dedupe_user_access();
 }
 
 /**
  * Add to the access ctrl array the data needed by a role for a given context.
  *
  * The data is added in the rdef key.
- *
  * This role-centric function is useful for role_switching
- * and to get an overview of what a role gets under a
- * given context and below...
+ * and temporary course roles.
  *
- * @param integer $roleid the id of the user
- * @param object $context needs path!
- * @param array $accessdata accessdata array null by default
+ * @private
+ * @param int $roleid the id of the user
+ * @param context $context needs path!
+ * @param array $accessdata accessdata array (is modified)
  * @return array
  */
-function get_role_access_bycontext($roleid, $context, $accessdata = null) {
-    global $CFG, $DB;
+function load_role_access_by_context($roleid, context $context, &$accessdata) {
+    global $DB, $ACCESSLIB_PRIVATE;
 
     /* Get the relevant rolecaps into rdef
      * - relevant role caps
@@ -1358,306 +948,277 @@ function get_role_access_bycontext($roleid, $context, $accessdata = null) {
      *   - below this ctx
      */
 
-    if (is_null($accessdata)) {
-        $accessdata           = array(); // named list
-        $accessdata['ra']     = array();
-        $accessdata['rdef']   = array();
-        $accessdata['loaded'] = array();
+    if (empty($context->path)) {
+        // weird, this should not happen
+        return;
     }
 
-    $contexts = substr($context->path, 1); // kill leading slash
-    $contexts = str_replace('/', ',', $contexts);
+    list($parentsaself, $params) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'pc_');
+    $params['roleid'] = $roleid;
+    $params['childpath'] = $context->path.'/%';
 
-    //
-    // Walk up and down the tree to grab all the roledefs
-    // of interest to our role...
-    //
-    // NOTE: we use an IN clauses here - which
-    // might explode on huge sites with very convoluted nesting of
-    // categories... - extremely unlikely that the number of nested
-    // categories is so large that we hit the limits of IN()
-    //
     $sql = "SELECT ctx.path, rc.capability, rc.permission
               FROM {role_capabilities} rc
-              JOIN {context} ctx
-                   ON rc.contextid=ctx.id
-             WHERE rc.roleid=? AND
-                   ( ctx.id IN ($contexts) OR
-                    ctx.path LIKE ? )
-          ORDER BY ctx.depth ASC, ctx.path DESC, rc.roleid ASC ";
-    $params = array($roleid, $context->path."/%");
-
+              JOIN {context} ctx ON (rc.contextid = ctx.id)
+             WHERE rc.roleid = :roleid AND (ctx.id $parentsaself OR ctx.path LIKE :childpath)
+          ORDER BY rc.capability"; // fixed capability order is necessary for rdef dedupe
     $rs = $DB->get_recordset_sql($sql, $params);
+
+    $newrdefs = array();
     foreach ($rs as $rd) {
-        $k = "{$rd->path}:{$roleid}";
- &nb