Skip to content
Browse files

Merge remote branch 'moodle/master' into master_MDL-18392_slash_cleanup

  • Loading branch information...
2 parents 3825bed + 91787c3 commit 4f6e39db5e8178ea1d5219e8652455b174c98b0b @danmarsden danmarsden committed Apr 14, 2011
Showing with 1,776 additions and 693 deletions.
  1. +1 −1 admin/cli/upgrade.php
  2. +13 −1 admin/index.php
  3. +14 −5 admin/settings/frontpage.php
  4. +26 −28 admin/settings/users.php
  5. +1 −1 admin/uploaduser.php
  6. +8 −0 backup/util/helper/restore_inforef_parser_processor.class.php
  7. +8 −0 backup/util/helper/restore_moodlexml_parser_processor.class.php
  8. +8 −0 backup/util/helper/restore_questions_parser_processor.class.php
  9. +8 −0 backup/util/helper/restore_roles_parser_processor.class.php
  10. +8 −0 backup/util/helper/restore_structure_parser_processor.class.php
  11. +8 −0 backup/util/helper/restore_users_parser_processor.class.php
  12. +1 −13 backup/util/ui/backup_ui.class.php
  13. +3 −3 backup/util/ui/backup_ui_stage.class.php
  14. +15 −0 backup/util/ui/base_ui.class.php
  15. +2 −2 backup/util/ui/restore_ui_stage.class.php
  16. +17 −18 backup/util/xml/parser/processors/grouped_parser_processor.class.php
  17. +42 −0 backup/util/xml/parser/processors/simplified_parser_processor.class.php
  18. +80 −0 backup/util/xml/parser/simpletest/testparser.php
  19. +3 −0 blocks/comments/block_comments.php
  20. +3 −2 comment/comment.js
  21. +163 −77 comment/lib.php
  22. +6 −0 enrol/ajax.php
  23. +2 −0 enrol/locallib.php
  24. +5 −2 enrol/renderer.php
  25. +4 −1 enrol/users.php
  26. +15 −1 enrol/yui/enrolmentmanager/enrolmentmanager.js
  27. +0 −3 index.php
  28. +7 −7 lang/en/admin.php
  29. +1 −0 lang/en/enrol.php
  30. +1 −0 lang/en/repository.php
  31. +4 −4 lib/accesslib.php
  32. +10 −0 lib/completionlib.php
  33. +2 −2 lib/form/filemanager.js
  34. +6 −5 lib/form/filemanager.php
  35. +84 −8 lib/gradelib.php
  36. +116 −163 lib/grouplib.php
  37. +3 −3 lib/htmlpurifier/HTMLPurifier.php
  38. +2 −0 lib/htmlpurifier/HTMLPurifier.safe-includes.php
  39. +138 −13 lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php
  40. +9 −0 lib/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php
  41. +6 −0 lib/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php
  42. +41 −0 lib/htmlpurifier/HTMLPurifier/AttrTransform/Nofollow.php
  43. +2 −1 lib/htmlpurifier/HTMLPurifier/AttrTransform/SafeParam.php
  44. +8 −2 lib/htmlpurifier/HTMLPurifier/Bootstrap.php
  45. +21 −0 lib/htmlpurifier/HTMLPurifier/CSSDefinition.php
  46. +181 −52 lib/htmlpurifier/HTMLPurifier/Config.php
  47. +7 −1 lib/htmlpurifier/HTMLPurifier/ConfigSchema.php
  48. BIN lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser
  49. +12 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt
  50. +9 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt
  51. +11 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt
  52. +7 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt
  53. +1 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
  54. +15 −0 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt
  55. +11 −0 lib/htmlpurifier/HTMLPurifier/Definition.php
  56. +24 −11 lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php
  57. 0 lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer/README
  58. +1 −1 lib/htmlpurifier/HTMLPurifier/EntityLookup/entities.ser
  59. +38 −13 lib/htmlpurifier/HTMLPurifier/Generator.php
  60. +19 −0 lib/htmlpurifier/HTMLPurifier/HTMLModule/Nofollow.php
  61. +1 −1 lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php
  62. +0 −1 lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php
  63. +4 −4 lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php
  64. +3 −3 lib/htmlpurifier/HTMLPurifier/Lexer.php
  65. +52 −22 lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php
  66. +79 −22 lib/htmlpurifier/HTMLPurifier/Strategy/MakeWellFormed.php
  67. +9 −7 lib/htmlpurifier/HTMLPurifier/TagTransform/Font.php
  68. +2 −1 lib/htmlpurifier/HTMLPurifier/Token/Tag.php
  69. +62 −31 lib/htmlpurifier/HTMLPurifier/URI.php
  70. +54 −7 lib/htmlpurifier/HTMLPurifier/URIScheme.php
  71. +4 −1 lib/htmlpurifier/HTMLPurifier/URIScheme/data.php
  72. +8 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/file.php
  73. +1 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/ftp.php
  74. +1 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/http.php
  75. +2 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/mailto.php
  76. +2 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/news.php
  77. +1 −2 lib/htmlpurifier/HTMLPurifier/URIScheme/nntp.php
  78. +2 −3 lib/htmlpurifier/readme_moodle.txt
  79. +1 −1 lib/installlib.php
  80. +4 −0 lib/setuplib.php
  81. +133 −0 lib/simpletest/testpurifier.php
  82. +0 −25 lib/simpletest/testweblib.php
  83. +1 −1 lib/thirdpartylibs.xml
  84. +14 −12 lib/weblib.php
  85. +3 −11 lib/xhprof/xhprof_moodle.php
  86. +11 −13 message/output/email/message_output_email.php
  87. +1 −1 mod/assignment/mod_form.php
  88. +4 −3 mod/chat/view.php
  89. +4 −5 mod/choice/view.php
  90. +1 −0 mod/data/templates.php
  91. +4 −5 mod/data/view.php
  92. +4 −4 mod/feedback/complete.php
  93. +4 −4 mod/feedback/lib.php
  94. +5 −2 mod/forum/view.php
  95. +4 −5 mod/glossary/view.php
  96. +1 −1 mod/lesson/locallib.php
  97. +4 −4 mod/lesson/view.php
  98. +4 −6 mod/quiz/view.php
  99. +4 −4 mod/scorm/player.php
  100. +4 −3 mod/workshop/view.php
  101. +11 −10 tag/lib.php
  102. +0 −6 theme/canvas/style/editor.css
  103. +0 −6 theme/canvas/style/text.css
  104. +2 −2 version.php
View
2 admin/cli/upgrade.php
@@ -94,7 +94,7 @@
$newversion = "$release ($version)";
// test environment first
-if (!check_moodle_environment($version, $environment_results, false, ENV_SELECT_RELEASE)) {
+if (!check_moodle_environment(normalize_version($release), $environment_results, false, ENV_SELECT_RELEASE)) {
$errors = environment_get_errors($environment_results);
cli_heading(get_string('environment', 'admin'));
foreach ($errors as $error) {
View
14 admin/index.php
@@ -153,7 +153,7 @@
echo $OUTPUT->box($releasenoteslink, 'generalbox releasenoteslink');
require_once($CFG->libdir.'/environmentlib.php');
- if (!check_moodle_environment($release, $environment_results, true, ENV_SELECT_RELEASE)) {
+ if (!check_moodle_environment(normalize_version($release), $environment_results, true, ENV_SELECT_RELEASE)) {
print_upgrade_reload("index.php?agreelicense=1&lang=$CFG->lang");
} else {
echo $OUTPUT->notification(get_string('environmentok', 'admin'), 'notifysuccess');
@@ -194,6 +194,7 @@
}
if ($version > $CFG->version) { // upgrade
+ purge_all_caches();
$PAGE->set_pagelayout('maintenance');
$PAGE->set_popup_notification_allowed(false);
@@ -407,6 +408,17 @@
admin_externalpage_setup('adminnotifications');
echo $OUTPUT->header();
+// Unstable code warning
+if (isset($maturity)) {
+ if ($maturity < MATURITY_STABLE) {
+ $maturitylevel = get_string('maturity'.$maturity, 'admin');
+ echo $OUTPUT->box(
+ get_string('maturitycoreinfo', 'admin', $maturitylevel) . ' ' .
+ $OUTPUT->doc_link('admin/versions', get_string('morehelp')),
+ 'generalbox adminwarning maturityinfo');
+ }
+}
+
if ($insecuredataroot == INSECURE_DATAROOT_WARNING) {
echo $OUTPUT->box(get_string('datarootsecuritywarning', 'admin', $CFG->dataroot), 'generalbox adminwarning');
} else if ($insecuredataroot == INSECURE_DATAROOT_ERROR) {
View
19 admin/settings/frontpage.php
@@ -52,13 +52,22 @@
$temp->add(new admin_setting_configtext('coursesperpage', get_string('coursesperpage', 'admin'), get_string('configcoursesperpage', 'admin'), 20, PARAM_INT));
// front page default role
- $roleoptions = array(0=>get_string('none')); // roles to choose from
- if ($roles = get_all_roles()) {
- foreach ($roles as $role) {
- $roleoptions[$role->id] = strip_tags(format_string($role->name, true));
+ $options = array(0=>get_string('none')); // roles to choose from
+ $defaultfrontpageroleid = 0;
+ foreach (get_all_roles() as $role) {
+ if (empty($role->archetype) or $role->archetype === 'guest' or $role->archetype === 'frontpage' or $role->archetype === 'student') {
+ $options[$role->id] = strip_tags(format_string($role->name)) . ' ('. $role->shortname . ')';
+ if ($role->archetype === 'frontpage') {
+ $defaultfrontpageroleid = $role->id;
+ }
}
}
- $temp->add(new admin_setting_configselect('defaultfrontpageroleid', get_string('frontpagedefaultrole', 'admin'), '', 0, $roleoptions));
+ if ($defaultfrontpageroleid and (!isset($CFG->defaultfrontpageroleid) or $CFG->defaultfrontpageroleid)) {
+ //frotpage role may not exist in old upgraded sites
+ unset($options[0]);
+ }
+ $temp->add(new admin_setting_configselect('defaultfrontpageroleid', get_string('frontpagedefaultrole', 'admin'), '', $defaultfrontpageroleid, $options));
+
$ADMIN->add('frontpage', $temp);
View
54 admin/settings/users.php
@@ -38,76 +38,74 @@
if ($ADMIN->fulltree) {
if (!during_initial_install()) {
$context = get_context_instance(CONTEXT_SYSTEM);
- $allroles = array();
- $generalroles = array();
+
+ $otherroles = array();
$guestroles = array();
$userroles = array();
- $studentroles = array();
- $teacherroles = array();
$creatornewroles = array();
+ $defaultteacherid = null;
+ $defaultuserid = null;
+ $defaultguestid = null;
+
foreach (get_all_roles() as $role) {
$rolename = strip_tags(format_string($role->name)) . ' ('. $role->shortname . ')';
- $allroles[$role->id] = $rolename;
switch ($role->archetype) {
case 'manager':
$creatornewroles[$role->id] = $rolename;
break;
case 'coursecreator':
break;
case 'editingteacher':
- $teacherroles[$role->id] = $rolename;
+ $defaultteacherid = isset($defaultteacherid) ? $defaultteacherid : $role->id;
$creatornewroles[$role->id] = $rolename;
break;
case 'teacher':
$creatornewroles[$role->id] = $rolename;
break;
case 'student':
- $studentroles[$role->id] = $rolename;
break;
case 'guest':
+ $defaultguestid = isset($defaultguestid) ? $defaultguestid : $role->id;
$guestroles[$role->id] = $rolename;
break;
case 'user':
+ $defaultuserid = isset($defaultuserid) ? $defaultuserid : $role->id;
$userroles[$role->id] = $rolename;
break;
case 'frontpage':
break;
default:
$creatornewroles[$role->id] = $rolename;
- $generalroles[$role->id] = $rolename;
+ $otherroles[$role->id] = $rolename;
break;
}
}
- reset($guestroles);
- $defaultguestid = key($guestroles);
- reset($studentroles);
- $defaultstudentid = key($studentroles);
- reset($teacherroles);
- $defaultteacherid = key($teacherroles);
-
- if ($userroles) {
- reset($userroles);
- $defaultuserid = key($userroles);
- } else {
- $userroles = array('0'=>get_string('none'));
+ if (empty($guestroles)) {
+ $guestroles[0] = get_string('none');
+ $defaultguestid = 0;
+ }
+
+ if (empty($userroles)) {
+ $userroles[0] = get_string('none');
$defaultuserid = 0;
}
$temp->add(new admin_setting_configselect('notloggedinroleid', get_string('notloggedinroleid', 'admin'),
- get_string('confignotloggedinroleid', 'admin'), $defaultguestid, ($guestroles + $generalroles)));
+ get_string('confignotloggedinroleid', 'admin'), $defaultguestid, ($guestroles + $otherroles)));
$temp->add(new admin_setting_configselect('guestroleid', get_string('guestroleid', 'admin'),
- get_string('guestroleid_help', 'admin'), $defaultguestid, ($guestroles + $generalroles)));
+ get_string('guestroleid_help', 'admin'), $defaultguestid, ($guestroles + $otherroles)));
$temp->add(new admin_setting_configselect('defaultuserroleid', get_string('defaultuserroleid', 'admin'),
- get_string('configdefaultuserroleid', 'admin'), $defaultuserid, ($userroles + $generalroles)));
- }
-
- $temp->add(new admin_setting_configcheckbox('nodefaultuserrolelists', get_string('nodefaultuserrolelists', 'admin'), get_string('confignodefaultuserrolelists', 'admin'), 0));
-
- if (!during_initial_install()) {
+ get_string('configdefaultuserroleid', 'admin'), $defaultuserid, ($userroles + $otherroles)));
$temp->add(new admin_setting_configselect('creatornewroleid', get_string('creatornewroleid', 'admin'),
get_string('creatornewroleid_help', 'admin'), $defaultteacherid, $creatornewroles));
+
+ // release memory
+ unset($otherroles);
+ unset($guestroles);
+ unset($userroles);
+ unset($creatornewroles);
}
$temp->add(new admin_setting_configcheckbox('autologinguests', get_string('autologinguests', 'admin'), get_string('configautologinguests', 'admin'), 0));
View
2 admin/uploaduser.php
@@ -774,7 +774,7 @@
}
}
- $manual->enrol_user($manualcache[$courseid], $user->id, $rid, $today, $timeend, true);
+ $manual->enrol_user($manualcache[$courseid], $user->id, $rid, $today, $timeend);
$a = new stdClass();
$a->course = $shortname;
View
8 backup/util/helper/restore_inforef_parser_processor.class.php
@@ -53,4 +53,12 @@ protected function dispatch_chunk($data) {
$itemid = $data['tags']['id'];
restore_dbops::set_backup_ids_record($this->restoreid, $itemname, $itemid);
}
+
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
}
View
8 backup/util/helper/restore_moodlexml_parser_processor.class.php
@@ -51,6 +51,14 @@ protected function dispatch_chunk($data) {
$this->accumchunks[] = $data;
}
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
+
public function get_all_chunks() {
return $this->accumchunks;
}
View
8 backup/util/helper/restore_questions_parser_processor.class.php
@@ -75,6 +75,14 @@ protected function dispatch_chunk($data) {
}
}
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
+
/**
* Provide NULL decoding
*/
View
8 backup/util/helper/restore_roles_parser_processor.class.php
@@ -55,6 +55,14 @@ protected function dispatch_chunk($data) {
}
}
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
+
/**
* Provide NULL decoding
*/
View
8 backup/util/helper/restore_structure_parser_processor.class.php
@@ -102,4 +102,12 @@ protected function postprocess_chunk($data) {
protected function dispatch_chunk($data) {
$this->step->process($data);
}
+
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
}
View
8 backup/util/helper/restore_users_parser_processor.class.php
@@ -66,6 +66,14 @@ protected function dispatch_chunk($data) {
}
}
+ protected function notify_path_start($path) {
+ // nothing to do
+ }
+
+ protected function notify_path_end($path) {
+ // nothing to do
+ }
+
/**
* Provide NULL decoding
*/
View
14 backup/util/ui/backup_ui.class.php
@@ -130,19 +130,7 @@ public function execute() {
}
return $backupid;
}
- /**
- * Cancels the current backup and redirects the user back to the relevant place
- */
- public function cancel_backup() {
- global $PAGE;
- // Determine the approriate URL to redirect the user to
- if ($PAGE->context->contextlevel == CONTEXT_MODULE && $PAGE->cm !== null) {
- $relevanturl = new moodle_url('/mod/'.$PAGE->cm->modname.'/view.php', array('id'=>$PAGE->cm->id));
- } else {
- $relevanturl = new moodle_url('/course/view.php', array('id'=>$PAGE->course->id));
- }
- redirect($relevanturl);
- }
+
/**
* Gets an array of progress bar items that can be displayed through the backup renderer.
* @return array Array of items for the progress bar
View
6 backup/util/ui/backup_ui_stage.class.php
@@ -81,7 +81,7 @@ public function process(base_moodleform $m = null) {
$form = $this->initialise_stage_form();
if ($form->is_cancelled()) {
- $this->ui->cancel_backup();
+ $this->ui->cancel_process();
}
$data = $form->get_data();
@@ -180,7 +180,7 @@ public function process(base_moodleform $form = null) {
$form = $this->initialise_stage_form();
// Check it wasn't cancelled
if ($form->is_cancelled()) {
- $this->ui->cancel_backup();
+ $this->ui->cancel_process();
}
// Check it has been submit
@@ -288,7 +288,7 @@ public function process(base_moodleform $form = null) {
$form = $this->initialise_stage_form();
// Check it hasn't been cancelled
if ($form->is_cancelled()) {
- $this->ui->cancel_backup();
+ $this->ui->cancel_process();
}
$data = $form->get_data();
View
15 backup/util/ui/base_ui.class.php
@@ -226,6 +226,21 @@ public function enforce_changed_dependencies() {
public static function load_controller($uniqueid=false) {
throw new coding_exception('load_controller() method needs to be overridden in each subclass of base_ui');
}
+
+ /**
+ * Cancels the current backup/restore and redirects the user back to the relevant place
+ */
+ public function cancel_process() {
+ global $PAGE;
+ // Determine the appropriate URL to redirect the user to
+ if ($PAGE->context->contextlevel == CONTEXT_MODULE && $PAGE->cm !== null) {
+ $relevanturl = new moodle_url('/mod/'.$PAGE->cm->modname.'/view.php', array('id'=>$PAGE->cm->id));
+ } else {
+ $relevanturl = new moodle_url('/course/view.php', array('id'=>$PAGE->course->id));
+ }
+ redirect($relevanturl);
+ }
+
/**
* Gets an array of progress bar items that can be displayed through the backup renderer.
* @return array Array of items for the progress bar
View
4 backup/util/ui/restore_ui_stage.class.php
@@ -392,7 +392,7 @@ public function process(base_moodleform $form = null) {
$form = $this->initialise_stage_form();
// Check it wasn't cancelled
if ($form->is_cancelled()) {
- $this->ui->cancel_backup();
+ $this->ui->cancel_process();
}
// Check it has been submit
@@ -500,7 +500,7 @@ public function process(base_moodleform $form = null) {
$form = $this->initialise_stage_form();
// Check it hasn't been cancelled
if ($form->is_cancelled()) {
- $this->ui->cancel_backup();
+ $this->ui->cancel_process();
}
$data = $form->get_data();
View
35 backup/util/xml/parser/processors/grouped_parser_processor.class.php
@@ -71,7 +71,18 @@ public function add_path($path, $grouped = false) {
}
/**
- * Dispatch grouped chunks safely once their end tag happens
+ * Notify start of path if selected and not under grouped
+ */
+ public function before_path($path) {
+ if ($this->path_is_selected($path) && !$this->grouped_parent_exists($path)) {
+ parent::before_path($path);
+ }
+ }
+
+
+ /**
+ * Dispatch grouped chunks safely once their end tag happens.
+ * Also notify end of path if selected and not under grouped
*/
public function after_path($path) {
if ($this->path_is_grouped($path)) {
@@ -82,6 +93,11 @@ public function after_path($path) {
// TODO: If running under DEBUG_DEVELOPER notice about >1MB grouped chunks
$this->dispatch_chunk($data);
}
+ // Normal notification of path end
+ // Only if path is selected and not child of grouped
+ if ($this->path_is_selected($path) && !$this->grouped_parent_exists($path)) {
+ parent::after_path($path);
+ }
}
// Protected API starts here
@@ -112,23 +128,6 @@ protected function path_is_grouped($path) {
}
/**
- * Function that will look for any
- * parent for the given path, returning it if found,
- * false if not
- */
- protected function processed_parent_exists($path) {
- $parentpath = progressive_parser::dirname($path);
- while ($parentpath != '/') {
- if ($this->path_is_selected($parentpath)) {
- return $parentpath;
- }
- $parentpath = progressive_parser::dirname($parentpath);
- }
- return false;
- }
-
-
- /**
* Function that will look for any grouped
* parent for the given path, returning it if found,
* false if not
View
42 backup/util/xml/parser/processors/simplified_parser_processor.class.php
@@ -64,6 +64,16 @@ public function add_path($path) {
abstract protected function dispatch_chunk($data);
/**
+ * Get one selected path and notify about start
+ */
+ abstract protected function notify_path_start($path);
+
+ /**
+ * Get one selected path and notify about end
+ */
+ abstract protected function notify_path_end($path);
+
+ /**
* Get one chunk of parsed data and make it simpler
* adding attributes as tags and delegating to
* dispatch_chunk() the procesing of the resulting chunk
@@ -139,6 +149,24 @@ public function process_chunk($data) {
return true;
}
+ /**
+ * The parser fires this each time one path is going to be parsed
+ */
+ public function before_path($path) {
+ if ($this->path_is_selected($path)) {
+ $this->notify_path_start($path);
+ }
+ }
+
+ /**
+ * The parser fires this each time one path has been parsed
+ */
+ public function after_path($path) {
+ if ($this->path_is_selected($path)) {
+ $this->notify_path_end($path);
+ }
+ }
+
// Protected API starts here
protected function postprocess_chunk($data) {
@@ -152,4 +180,18 @@ protected function path_is_selected($path) {
protected function path_is_selected_parent($path) {
return in_array($path, $this->parentpaths);
}
+
+ /**
+ * Returns the first selected parent if available or false
+ */
+ protected function selected_parent_exists($path) {
+ $parentpath = progressive_parser::dirname($path);
+ while ($parentpath != '/') {
+ if ($this->path_is_selected($parentpath)) {
+ return $parentpath;
+ }
+ $parentpath = progressive_parser::dirname($parentpath);
+ }
+ return false;
+ }
}
View
80 backup/util/xml/parser/simpletest/testparser.php
@@ -307,6 +307,29 @@ function test_simplified_parser_results() {
$this->assertEqual(count($tags), 2);
$this->assertEqual($tags['name'], 4);
$this->assertEqual($tags['value'], 5);
+
+ // Now check start notifications
+ $snotifs = $pr->get_start_notifications();
+ // Check we have received the correct number of notifications
+ $this->assertEqual(count($snotifs), 12);
+ // Check first, sixth and last notifications
+ $this->assertEqual($snotifs[0], '/activity');
+ $this->assertEqual($snotifs[5], '/activity/glossary/entries/entry');
+ $this->assertEqual($snotifs[11], '/activity/glossary/othertest');
+
+ // Now check end notifications
+ $enotifs = $pr->get_end_notifications();
+ // Check we have received the correct number of notifications
+ $this->assertEqual(count($snotifs), 12);
+ // Check first, sixth and last notifications
+ $this->assertEqual($enotifs[0], '/activity/glossary/entries/entry/aliases/alias');
+ $this->assertEqual($enotifs[5], '/activity/glossary/entries/entry/ratings/rating');
+ $this->assertEqual($enotifs[11], '/activity');
+
+ // Check start and end notifications are balanced
+ sort($snotifs);
+ sort($enotifs);
+ $this->assertEqual($snotifs, $enotifs);
}
/*
@@ -454,6 +477,27 @@ function test_grouped_parser_results() {
$this->assertEqual(count($othertest[0]), 2);
$this->assertEqual($othertest[0]['name'], 4);
$this->assertEqual($othertest[0]['value'], 5);
+
+ // Now check start notifications
+ $snotifs = $pr->get_start_notifications();
+ // Check we have received the correct number of notifications
+ $this->assertEqual(count($snotifs), 2);
+ // Check first and last notifications
+ $this->assertEqual($snotifs[0], '/activity');
+ $this->assertEqual($snotifs[1], '/activity/glossary');
+
+ // Now check end notifications
+ $enotifs = $pr->get_end_notifications();
+ // Check we have received the correct number of notifications
+ $this->assertEqual(count($snotifs), 2);
+ // Check first, and last notifications
+ $this->assertEqual($enotifs[0], '/activity/glossary');
+ $this->assertEqual($enotifs[1], '/activity');
+
+ // Check start and end notifications are balanced
+ sort($snotifs);
+ sort($enotifs);
+ $this->assertEqual($snotifs, $enotifs);
}
}
@@ -526,14 +570,32 @@ public function get_chunks() {
class mock_simplified_parser_processor extends simplified_parser_processor {
private $chunksarr = array(); // To accumulate the found chunks
+ private $startarr = array(); // To accumulate all the notified path starts
+ private $endarr = array(); // To accumulate all the notified path ends
public function dispatch_chunk($data) {
$this->chunksarr[] = $data;
}
+ public function notify_path_start($path) {
+ $this->startarr[] = $path;
+ }
+
+ public function notify_path_end($path) {
+ $this->endarr[] = $path;
+ }
+
public function get_chunks() {
return $this->chunksarr;
}
+
+ public function get_start_notifications() {
+ return $this->startarr;
+ }
+
+ public function get_end_notifications() {
+ return $this->endarr;
+ }
}
/*
@@ -542,12 +604,30 @@ public function get_chunks() {
class mock_grouped_parser_processor extends grouped_parser_processor {
private $chunksarr = array(); // To accumulate the found chunks
+ private $startarr = array(); // To accumulate all the notified path starts
+ private $endarr = array(); // To accumulate all the notified path ends
public function dispatch_chunk($data) {
$this->chunksarr[] = $data;
}
+ public function notify_path_start($path) {
+ $this->startarr[] = $path;
+ }
+
+ public function notify_path_end($path) {
+ $this->endarr[] = $path;
+ }
+
public function get_chunks() {
return $this->chunksarr;
}
+
+ public function get_start_notifications() {
+ return $this->startarr;
+ }
+
+ public function get_end_notifications() {
+ return $this->endarr;
+ }
}
View
3 blocks/comments/block_comments.php
@@ -47,6 +47,9 @@ function get_content() {
$args->env = 'block_comments';
$args->component = 'block_comments';
$args->linktext = get_string('showcomments');
+ $args->notoggle = true;
+ $args->autostart = true;
+ $args->displaycancel = true;
$comment = new comment($args);
$comment->set_view_permission(true);
View
5 comment/comment.js
@@ -41,8 +41,9 @@ M.core_comment = {
this.courseid = args.courseid;
this.contextid = args.contextid;
this.env = args.env;
+ this.autostart = (args.autostart);
// expand comments?
- if (args.autostart) {
+ if (this.autostart) {
this.view(args.page);
}
// load comments
@@ -347,7 +348,7 @@ bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-
var d = container.getStyle('display');
if (d=='none'||d=='') {
// show
- if (this.env != 'block_comments') {
+ if (this.autostart) {
this.load(page);
} else {
this.register_delete_buttons();
View
240 comment/lib.php
@@ -80,13 +80,34 @@ class comment {
*/
private $linktext;
+ /**
+ * If set to true then comment sections won't be able to be opened and closed
+ * instead they will always be visible.
+ * @var bool
+ */
+ protected $notoggle = false;
+
+ /**
+ * If set to true comments are automatically loaded as soon as the page loads.
+ * Normally this happens when the user expands the comment section.
+ * @var bool
+ */
+ protected $autostart = false;
+
+ /**
+ * If set to true a cancel button will be shown on the form used to submit comments.
+ * @var bool
+ */
+ protected $displaycancel = false;
+
// static variable will be used by non-js comments UI
private static $nonjs = false;
private static $comment_itemid = null;
private static $comment_context = null;
private static $comment_area = null;
private static $comment_page = null;
private static $comment_component = null;
+
/**
* Construct function of comment class, initialise
* class members
@@ -173,6 +194,21 @@ public function __construct($options) {
$this->ignore_permission = false;
}
+ // setup notoggle
+ if (!empty($options->notoggle)) {
+ $this->set_notoggle($options->notoggle);
+ }
+
+ // setup notoggle
+ if (!empty($options->autostart)) {
+ $this->set_autostart($options->autostart);
+ }
+
+ // setup displaycancel
+ if (!empty($options->displaycancel)) {
+ $this->set_displaycancel($options->displaycancel);
+ }
+
if (!empty($options->showcount)) {
$count = $this->count();
if (empty($count)) {
@@ -265,114 +301,164 @@ private function check_permissions() {
}
/**
+ * Gets a link for this page that will work with JS disabled.
+ *
+ * @global moodle_page $PAGE
+ * @param moodle_page $page
+ * @return moodle_url
+ */
+ public function get_nojslink(moodle_page $page = null) {
+ if ($page === null) {
+ global $PAGE;
+ $page = $PAGE;
+ }
+
+ $link = new moodle_url($page->url, array(
+ 'nonjscomment' => true,
+ 'comment_itemid' => $this->itemid,
+ 'comment_context' => $this->context->id,
+ 'comment_area' => $this->commentarea,
+ ));
+ $link->remove_params(array('nonjscomment', 'comment_page'));
+ return $link;
+ }
+
+ /**
+ * Sets the value of the notoggle option.
+ *
+ * If set to true then the user will not be able to expand and collase
+ * the comment section.
+ *
+ * @param bool $newvalue
+ */
+ public function set_notoggle($newvalue = true) {
+ $this->notoggle = (bool)$newvalue;
+ }
+
+ /**
+ * Sets the value of the autostart option.
+ *
+ * If set to true then the comments will be loaded during page load.
+ * Normally this happens only once the user expands the comment section.
+ *
+ * @param bool $newvalue
+ */
+ public function set_autostart($newvalue = true) {
+ $this->autostart = (bool)$newvalue;
+ }
+
+ /**
+ * Sets the displaycancel option
+ *
+ * If set to true then a cancel button will be shown when using the form
+ * to post comments.
+ *
+ * @param bool $newvalue
+ */
+ public function set_displaycancel($newvalue = true) {
+ $this->displaycancel = (bool)$newvalue;
+ }
+
+ /**
+ * Initialises the JavaScript that enchances the comment API.
+ *
+ * @param moodle_page $page The moodle page object that the JavaScript should be
+ * initialised for.
+ */
+ public function initialise_javascript(moodle_page $page) {
+
+ $options = new stdClass;
+ $options->client_id = $this->cid;
+ $options->commentarea = $this->commentarea;
+ $options->itemid = $this->itemid;
+ $options->page = 0;
+ $options->courseid = $this->courseid;
+ $options->contextid = $this->contextid;
+ $options->env = $this->env;
+ $options->component = $this->component;
+ $options->notoggle = $this->notoggle;
+ $options->autostart = $this->autostart;
+
+ $page->requires->js_init_call('M.core_comment.init', array($options), true);
+
+ return true;
+ }
+
+ /**
* Prepare comment code in html
* @param boolean $return
* @return mixed
*/
public function output($return = true) {
global $PAGE, $OUTPUT;
- static $template_printed;
-
- $this->link = $PAGE->url;
- $murl = new moodle_url($this->link);
- $murl->remove_params('nonjscomment');
- $murl->param('nonjscomment', 'true');
- $murl->param('comment_itemid', $this->itemid);
- $murl->param('comment_context', $this->context->id);
- $murl->param('comment_area', $this->commentarea);
- $murl->remove_params('comment_page');
- $this->link = $murl->out();
-
- $options = new stdClass();
- $options->client_id = $this->cid;
- $options->commentarea = $this->commentarea;
- $options->itemid = $this->itemid;
- $options->page = 0;
- $options->courseid = $this->courseid;
- $options->contextid = $this->contextid;
- $options->env = $this->env;
- $options->component = $this->component;
- if ($this->env == 'block_comments') {
- $options->notoggle = true;
- $options->autostart = true;
- }
+ static $template_printed;
- $PAGE->requires->js_init_call('M.core_comment.init', array($options), true);
+ $this->initialise_javascript($PAGE);
if (!empty(self::$nonjs)) {
// return non js comments interface
return $this->print_comments(self::$comment_page, $return, true);
}
- $strsubmit = get_string('savecomment');
- $strcancel = get_string('cancel');
- $strshowcomments = get_string('showcommentsnonjs');
- $sesskey = sesskey();
$html = '';
+
// print html template
// Javascript will use the template to render new comments
if (empty($template_printed) && !empty($this->viewcap)) {
- $html .= '<div style="display:none" id="cmt-tmpl">' . $this->template . '</div>';
+ $html .= html_writer::tag('div', $this->template, array('style' => 'display:none', 'id' => 'cmt-tmpl'));
$template_printed = true;
}
if (!empty($this->viewcap)) {
// print commenting icon and tooltip
- $icon = $OUTPUT->pix_url('t/collapsed');
- $html .= <<<EOD
-<div class="mdl-left">
-<a class="showcommentsnonjs" href="{$this->link}">{$strshowcomments}</a>
-EOD;
- if ($this->env != 'block_comments') {
- $html .= <<<EOD
-<a id="comment-link-{$this->cid}" class="comment-link" href="#">
- <img id="comment-img-{$this->cid}" src="$icon" alt="{$this->linktext}" title="{$this->linktext}" />
- <span id="comment-link-text-{$this->cid}">{$this->linktext} {$this->count}</span>
-</a>
-EOD;
+ $html .= html_writer::start_tag('div', array('class' => 'mdl-left'));
+ $html .= html_writer::link($this->get_nojslink($PAGE), get_string('showcommentsnonjs'), array('class' => 'showcommentsnonjs'));
+
+ if (!$this->notoggle) {
+ // If toggling is enabled (notoggle=false) then print the controls to toggle
+ // comments open and closed
+ $html .= html_writer::start_tag('a', array('class' => 'comment-link', 'id' => 'comment-link-'.$this->cid, 'href' => '#'));
+ $html .= html_writer::empty_tag('img', array('id' => 'comment-img-'.$this->cid, 'src' => $OUTPUT->pix_url('t/collapsed'), 'alt' => $this->linktext, 'title' => $this->linktext));
+ $html .= html_writer::tag('span', $this->linktext.' '.$this->count, array('id' => 'comment-link-text-'.$this->cid));
+ $html .= html_writer::end_tag('a');
}
- $html .= <<<EOD
-<div id="comment-ctrl-{$this->cid}" class="comment-ctrl">
- <ul id="comment-list-{$this->cid}" class="comment-list">
- <li class="first"></li>
-EOD;
- // in comments block, we print comments list right away
- if ($this->env == 'block_comments') {
+ $html .= html_writer::start_tag('div', array('id' => 'comment-ctrl-'.$this->cid, 'class' => 'comment-ctrl'));
+ $html .= html_writer::start_tag('ul', array('id' => 'comment-list-'.$this->cid, 'class' => 'comment-list'));
+ $html .= html_writer::tag('li', '', array('class' => 'first'));
+
+ if ($this->autostart) {
+ // If autostart has been enabled print the comments list immediatly
$html .= $this->print_comments(0, true, false);
- $html .= '</ul>';
+ $html .= html_writer::end_tag('ul'); // .comment-list
$html .= $this->get_pagination(0);
} else {
- $html .= <<<EOD
- </ul>
- <div id="comment-pagination-{$this->cid}" class="comment-pagination"></div>
-EOD;
+ $html .= html_writer::end_tag('ul'); // .comment-list
+ $html .= html_writer::tag('div', '', array('id' => 'comment-pagination-'.$this->cid, 'class' => 'comment-pagination'));
}
- // print posting textarea
if (!empty($this->postcap)) {
- $html .= <<<EOD
-<div class='comment-area'>
- <div class="bd">
- <textarea name="content" rows="2" cols="20" id="dlg-content-{$this->cid}"></textarea>
- </div>
- <div class="fd" id="comment-action-{$this->cid}">
- <a href="#" id="comment-action-post-{$this->cid}"> {$strsubmit} </a>
-EOD;
- if ($this->env != 'block_comments') {
- $html .= "<span> | </span><a href=\"#\" id=\"comment-action-cancel-{$this->cid}\"> {$strcancel} </a>";
+ // print posting textarea
+ $html .= html_writer::start_tag('div', array('class' => 'comment-area'));
+ $html .= html_writer::start_tag('div', array('class' => 'db'));
+ $html .= html_writer::tag('textarea', '', array('name' => 'content', 'rows' => 2, 'cols' => 20, 'id' => 'dlg-content-'.$this->cid));
+ $html .= html_writer::end_tag('div'); // .db
+
+ $html .= html_writer::start_tag('div', array('class' => 'fd', 'id' => 'comment-action-'.$this->cid));
+ $html .= html_writer::link('#', get_string('savecomment'), array('id' => 'comment-action-post-'.$this->cid));
+
+ if ($this->displaycancel) {
+ $html .= html_writer::tag('span', ' | ');
+ $html .= html_writer::link('#', get_string('cancel'), array('id' => 'comment-action-cancel-'.$this->cid));
}
- $html .= <<<EOD
- </div>
-</div>
-<div class="clearer"></div>
-EOD;
+
+ $html .= html_writer::end_tag('div'); // .fd
+ $html .= html_writer::end_tag('div'); // .comment-area
+ $html .= html_writer::tag('div', '', array('class' => 'clearer'));
}
- $html .= <<<EOD
-</div><!-- end of comment-ctrl -->
-</div>
-EOD;
+ $html .= html_writer::end_tag('div'); // .comment-ctrl
+ $html .= html_writer::end_tag('div'); // .mdl-left
} else {
$html = '';
}
@@ -457,11 +543,11 @@ public function get_pagination($page = 0) {
$count = $this->count();
$pages = (int)ceil($count/$CFG->commentsperpage);
if ($pages == 1 || $pages == 0) {
- return '';
+ return html_writer::tag('div', '', array('id' => 'comment-pagination-'.$this->cid, 'class' => 'comment-pagination'));
}
if (!empty(self::$nonjs)) {
// used in non-js interface
- return $OUTPUT->paging_bar($count, $page, $CFG->commentsperpage, $this->link, 'comment_page');
+ return $OUTPUT->paging_bar($count, $page, $CFG->commentsperpage, $this->get_nojslink(), 'comment_page');
} else {
// return ajax paging bar
$str = '';
View
6 enrol/ajax.php
@@ -154,6 +154,8 @@
$roleid = optional_param('role', null, PARAM_INT);
$duration = optional_param('duration', 0, PARAM_INT);
$startdate = optional_param('startdate', 0, PARAM_INT);
+ $recovergrades = optional_param('recovergrades', 0, PARAM_INT);
+
if (empty($roleid)) {
$roleid = null;
}
@@ -185,6 +187,10 @@
$plugin = $plugins[$instance->enrol];
if ($plugin->allow_enrol($instance) && has_capability('enrol/'.$plugin->get_name().':enrol', $context)) {
$plugin->enrol_user($instance, $user->id, $roleid, $timestart, $timeend);
+ if ($recovergrades) {
+ require_once($CFG->libdir.'/gradelib.php');
+ grade_recover_history_grades($user->id, $instance->courseid);
+ }
} else {
throw new enrol_ajax_exception('enrolnotpermitted');
}
View
2 enrol/locallib.php
@@ -613,6 +613,8 @@ public function get_group($groupid) {
* @return bool
*/
public function edit_enrolment($userenrolment, $data) {
+ //Only allow editing if the user has the appropriate capability
+ //Already checked in /enrol/users.php but checking again in case this function is called from elsewhere
list($instance, $plugin) = $this->get_user_enrolment_components($userenrolment);
if ($instance && $plugin && $plugin->allow_manage($instance) && has_capability("enrol/$instance->enrol:manage", $this->context)) {
if (!isset($data->status)) {
View
7 enrol/renderer.php
@@ -626,6 +626,7 @@ public function get_cohort_enrolment_control() {
* @return single_button|url_select
*/
public function get_enrolment_selector() {
+ global $CFG;
static $count = 0;
$instances = $this->manager->get_enrolment_instances();
@@ -686,7 +687,8 @@ public function get_enrolment_selector() {
'startdatetoday',
'durationdays',
'enrolperiod',
- 'finishenrollingusers'), 'enrol');
+ 'finishenrollingusers',
+ 'recovergrades'), 'enrol');
$this->moodlepage->requires->string_for_js('assignroles', 'role');
$this->moodlepage->requires->string_for_js('startingfrom', 'moodle');
@@ -698,7 +700,8 @@ public function get_enrolment_selector() {
'ajaxurl'=>'/enrol/ajax.php',
'url'=>$this->moodlepage->url->out(false),
'optionsStartDate'=>$startdateoptions,
- 'defaultRole'=>$instance->roleid);
+ 'defaultRole'=>$instance->roleid,
+ 'disableGradeHistory'=>$CFG->disablegradehistory);
$this->moodlepage->requires->yui_module($modules, $function, array($arguments));
}
return $control;
View
5 enrol/users.php
@@ -62,7 +62,7 @@
switch ($action) {
/**
- * Unenrols a user from this course
+ * Unenrols a user from this course (includes removing all of their grades)
*/
case 'unenrol':
$ue = $DB->get_record('user_enrolments', array('id'=>required_param('ue', PARAM_INT)), '*', MUST_EXIST);
@@ -73,6 +73,7 @@
} else {
$user = $DB->get_record('user', array('id'=>$ue->userid), '*', MUST_EXIST);
$yesurl = new moodle_url($PAGE->url, array('action'=>'unenrol', 'ue'=>$ue->id, 'confirm'=>1, 'sesskey'=>sesskey()));
+
$message = get_string('unenrolconfirm', 'enrol', array('user'=>fullname($user, true), 'course'=>format_string($course->fullname)));
$pagetitle = get_string('unenrol', 'enrol');
$pagecontent = $OUTPUT->confirm($message, $yesurl, $PAGE->url);
@@ -166,6 +167,8 @@
*/
case 'edit':
$ue = $DB->get_record('user_enrolments', array('id'=>required_param('ue', PARAM_INT)), '*', MUST_EXIST);
+
+ //Only show the edit form if the user has the appropriate capability
list($instance, $plugin) = $manager->get_user_enrolment_components($ue);
if ($instance && $plugin && $plugin->allow_manage($instance) && has_capability("enrol/$instance->enrol:manage", $manager->get_context())) {
$user = $DB->get_record('user', array('id'=>$ue->userid), '*', MUST_EXIST);
View
16 enrol/yui/enrolmentmanager/enrolmentmanager.js
@@ -20,7 +20,8 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
DEFAULTROLE : 'defaultRole',
DEFAULTSTARTDATE : 'defaultStartDate',
DEFAULTDURATION : 'defaultDuration',
- ASSIGNABLEROLES : 'assignableRoles'
+ ASSIGNABLEROLES : 'assignableRoles',
+ DISABLEGRADEHISTORY : 'disableGradeHistory'
};
/** CSS classes for nodes in structure **/
var CSS = {
@@ -48,6 +49,8 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
ODD : 'odd',
EVEN : 'even',
HIDDEN : 'hidden',
+ RECOVERGRADESCHECK : 'uep-recovergradescheck',
+ RECOVERGRADESCHECKTITLE : 'uep-recovergradeschecktitle',
SEARCHOPTIONS : 'uep-searchoptions',
COLLAPSIBLEHEADING : 'collapsibleheading',
COLLAPSIBLEAREA : 'collapsiblearea',
@@ -70,6 +73,11 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
_loadingNode : null,
_escCloseEvent : null,
initializer : function(config) {
+ recovergradescheckbox = null;
+ if (this.get(UEP.DISABLEGRADEHISTORY) != true) {
+ recovergradescheckbox = Y.Node.create('<div class="'+CSS.RECOVERGRADESCHECK+'"><input type="checkbox" id="recovergrades" name="recovergrades" /><span class="'+CSS.RECOVERGRADESCHECKTITLE+'"><label for="recovergrades">'+M.str.enrol.recovergrades+'</label></span></div>');
+ }
+
this.set(UEP.BASE, Y.Node.create('<div class="'+CSS.PANEL+' '+CSS.HIDDEN+'"></div>')
.append(Y.Node.create('<div class="'+CSS.WRAP+'"></div>')
.append(Y.Node.create('<div class="'+CSS.HEADER+' header"></div>')
@@ -80,6 +88,7 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
.append(Y.Node.create('<div class="'+CSS.SEARCHOPTION+' '+CSS.ROLE+'">'+M.str.role.assignroles+'</div>')
.append(Y.Node.create('<select><option value="">'+M.str.enrol.none+'</option></select>'))
)
+ .append(recovergradescheckbox)
.append(Y.Node.create('<div class="'+CSS.SEARCHOPTIONS+'"></div>')
.append(Y.Node.create('<div class="'+CSS.COLLAPSIBLEHEADING+'"><img alt="" />'+M.str.enrol.enrolmentoptions+'</div>'))
.append(Y.Node.create('<div class="'+CSS.COLLAPSIBLEAREA+' '+CSS.HIDDEN+'"></div>')
@@ -367,6 +376,8 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
params['role'] = this.get(UEP.BASE).one('.'+CSS.SEARCHOPTION+'.'+CSS.ROLE+' select').get('value');
params['startdate'] = this.get(UEP.BASE).one('.'+CSS.SEARCHOPTION+'.'+CSS.STARTDATE+' select').get('value');
params['duration'] = this.get(UEP.BASE).one('.'+CSS.SEARCHOPTION+'.'+CSS.DURATION+' select').get('value');
+ params['recovergrades'] = this.get(UEP.BASE).one('#recovergrades').get('checked')?1:0;
+
Y.io(M.cfg.wwwroot+this.get(UEP.AJAXURL), {
method:'POST',
data:build_querystring(params),
@@ -487,6 +498,9 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) {
},
optionsStartDate : {
value : []
+ },
+ disableGradeHistory : {
+ value : 0
}
}
});
View
3 index.php
@@ -88,9 +88,6 @@
$PAGE->set_heading($SITE->fullname);
echo $OUTPUT->header();
- //TODO: remove this notice once admins know they need to switch CVS and git branches, the reason is once we start changing DB there will not be any way back!
- echo $OUTPUT->box('WARNING: this site is using 2.1dev codebase, please make sure this is is not a production server!!!', 'errorbox');
-
/// Print Section
if ($SITE->numsections > 0) {
View
14 lang/en/admin.php
@@ -183,7 +183,7 @@
$string['configdefaulthomepage'] = 'This determines the home page for logged in users';
$string['configdefaultrequestcategory'] = 'Courses requested by users will be automatically placed in this category.';
$string['configdefaultrequestedcategory'] = 'Default category to put courses that were requested into, if they\'re approved.';
-$string['configdefaultuserroleid'] = 'All logged in users will be given the capabilities of the role you specify here, at the site level, in ADDITION to any other roles they may have been given. The default is the Authenticated user role (or Guest role in older versions). Note that this will not conflict with other roles they have, it just ensures that all users have capabilities that are not assignable at the course level (eg post blog entries, manage own calendar, etc).';
+$string['configdefaultuserroleid'] = 'All logged in users will be given the capabilities of the role you specify here, at the site level, in ADDITION to any other roles they may have been given. The default is the Authenticated user role. Note that this will not conflict with other roles they have unless you prohibit capabilities, it just ensures that all users have capabilities that are not assignable at the course level (eg post blog entries, manage own calendar, etc).';
$string['configdeleteincompleteusers'] = 'After this period, old not fully setup accounts are deleted.';
$string['configdeleteunconfirmed'] = 'If you are using email authentication, this is the period within which a response will be accepted from users. After this period, old unconfirmed accounts are deleted.';
$string['configdenyemailaddresses'] = 'To deny email addresses from particular domains list them here in the same way. All other domains will be accepted. To deny subdomains add the domain with a preceding \'.\'. eg <strong>hotmail.com yahoo.co.uk .live.com</strong>';
@@ -226,7 +226,7 @@
$string['configfrontpageloggedin'] = 'The items selected above will be displayed on the site\'s front page when a user is logged in.';
$string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. For most mono-lingual sites the most efficient setting is the default "First name + Surname", but you may choose to hide surnames altogether, or to leave it up to the current language pack to decide (some languages have different conventions).';
$string['configgdversion'] = 'Indicate the version of GD that is installed. The version shown by default is the one that has been auto-detected. Don\'t change this unless you really know what you\'re doing.';
-$string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version.<br />Simply download <a href="http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz" >http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a> and extract it into "{$a}" directory on your server.';
+$string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version.<br />Simply download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz" >http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a> and extract it into "{$a}" directory on your server.';
$string['configgetremoteaddrconf'] = 'If your server is behind a reverse proxy, you can use this setting to specify which HTTP headers can be trusted to contain the remote IP address. The headers are read in order, using the first one that is available.';
$string['configgooglemapkey'] = 'You need to enter a special key to use Google Maps for IP address lookup visualization. You can obtain the key free of charge at <a href="http://code.google.com/apis/maps/signup.html" >http://code.google.com/apis/maps/signup.html</a>.<br />Your web site URL is: {$a}';
$string['configgradebookroles'] = 'This setting allows you to control who appears on the gradebook. Users need to have at least one of these roles in a course to be shown in the gradebook for that course.';
@@ -276,7 +276,6 @@
$string['confignavcourselimit'] = 'Limits the number of courses shown to the user when they are either not logged in or are not enrolled in any courses.';
$string['confignavshowallcourses'] = 'Setting this ensures that all courses on the site are shown in the navigation at all times.';
$string['confignavshowcategories'] = 'Show course categories in the navigation bar and navigation blocks. This does not occur with courses the user is currently enrolled in, they will still be listed under mycourses without categories.';
-$string['confignodefaultuserrolelists'] = 'This setting prevents all users from being returned from the database from deprecated calls of get_course_user, etc., for the site course if the default role provides that access. Check this, if you suffer a performance hit.';
$string['confignoreplyaddress'] = 'Emails are sometimes sent out on behalf of a user (eg forum posts). The email address you specify here will be used as the "From" address in those cases when the recipients should not be able to reply directly to the user (eg when a user chooses to keep their address private).';
$string['confignotifyloginfailures'] = 'If login failures have been recorded, email notifications can be sent out. Who should see these notifications?';
$string['confignotifyloginthreshold'] = 'If notifications about failed logins are active, how many failed login attempts by one user or one IP address is it worth notifying about?';
@@ -685,9 +684,11 @@
$string['maturity100'] = 'Beta';
$string['maturity150'] = 'Release candidate';
$string['maturity200'] = 'Stable version';
-$string['maturitycorewarning'] = 'You are going to install or upgrade Moodle to a version marked as "{$a}"
-that is not considered as production-ready yet. Please make sure this is intentional
-and that you are using correct checkout of Moodle source code.';
+$string['maturitycoreinfo'] = 'Your site is currently running unstable "{$a}" development code.';
+$string['maturitycorewarning'] = 'The version of Moodle that you are about to install or upgrade to contains
+unstable "{$a}" development code that is not suitable for use on most production
+sites. If this is not what you wanted then you should make sure you are updating
+from a STABLE branch of the Moodle code. See Moodle Docs for more details.';
$string['maxbytes'] = 'Maximum uploaded file size';
$string['maxconsecutiveidentchars'] = 'Consecutive identical characters';
$string['maxeditingtime'] = 'Maximum time to edit posts';
@@ -748,7 +749,6 @@
$string['neverdeleteruns'] = 'Never delete runs';
$string['nobookmarksforuser'] = 'You do not have any bookmarks.';
$string['nodatabase'] = 'No database';
-$string['nodefaultuserrolelists'] = 'Don\'t return all default role users';
$string['nochanges'] = 'No changes';
$string['nolangupdateneeded'] = 'All your language packs are up to date, no update is needed';
$string['nomissingstrings'] = 'No missing strings';
View
1 lang/en/enrol.php
@@ -77,6 +77,7 @@
$string['periodend'] = 'until {$a}';
$string['periodstart'] = 'from {$a}';
$string['periodstartend'] = 'from {$a->start} until {$a->end}';
+$string['recovergrades'] = 'Recover user\'s old grades if possible';
$string['rolefromthiscourse'] = '{$a->role} (Assigned in this course)';
$string['rolefrommetacourse'] = '{$a->role} (Inherited from parent course)';
$string['rolefromcategory'] = '{$a->role} (Inherited from course category)';
View
1 lang/en/repository.php
@@ -123,6 +123,7 @@
$string['manage'] = 'Manage repositories';
$string['manageurl'] = 'Manage';
$string['manageuserrepository'] = 'Manage individual repository';
+$string['moving'] = 'Moving';
$string['noenter'] = 'Nothing entered';
$string['nofilesattached'] = 'No files attached';
$string['nofilesavailable'] = 'No files available';
View
8 lib/accesslib.php
@@ -3142,8 +3142,8 @@ function get_enrolled_sql($context, $withcapability = '', $groupid = 0, $onlyact
}
}
- $defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : null;
- $defaultfrontpageroleid = isset($CFG->defaultfrontpageroleid) ? $CFG->defaultfrontpageroleid : null;
+ $defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : 0;
+ $defaultfrontpageroleid = isset($CFG->defaultfrontpageroleid) ? $CFG->defaultfrontpageroleid : 0;
$nobody = false;
@@ -4851,8 +4851,8 @@ function get_users_by_capability($context, $capability, $fields = '', $sort = ''
throw new coding_exception('Invalid context specified');
}
- $defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : null;
- $defaultfrontpageroleid = isset($CFG->defaultfrontpageroleid) ? $CFG->defaultfrontpageroleid : null;
+ $defaultuserroleid = isset($CFG->defaultuserroleid) ? $CFG->defaultuserroleid : 0;
+ $defaultfrontpageroleid = isset($CFG->defaultfrontpageroleid) ? $CFG->defaultfrontpageroleid : 0;
$ctxids = trim($context->path, '/');
$ctxids = str_replace('/', ',', $ctxids);
View
10 lib/completionlib.php
@@ -592,6 +592,9 @@ function internal_get_state($cm, $userid, $current) {
* Should be called whenever a module is 'viewed' (it is up to the module how to
* determine that). Has no effect if viewing is not set as a completion condition.
*
+ * Note that this function must be called before you print the page header because
+ * it is possible that the navigation block may depend on it. If you call it after
+ * printing the header, it shows a developer debug warning.
* @uses COMPLETION_VIEW_NOT_REQUIRED
* @uses COMPLETION_VIEWED
* @uses COMPLETION_COMPLETE
@@ -600,6 +603,11 @@ function internal_get_state($cm, $userid, $current) {
* @return void
*/
public function set_module_viewed($cm, $userid=0) {
+ global $PAGE;
+ if ($PAGE->headerprinted) {
+ debugging('set_module_viewed must be called before header is printed',
+ DEBUG_DEVELOPER);
+ }
// Don't do anything if view condition is not turned on
if ($cm->completionview == COMPLETION_VIEW_NOT_REQUIRED || !$this->is_enabled($cm)) {
return;
@@ -932,6 +940,8 @@ function internal_set_data($cm, $data) {
if ($data->userid == $USER->id) {
$SESSION->completioncache[$cm->course][$cm->id] = $data;
+ $reset = 'reset';
+ get_fast_modinfo($reset);
}
}
View
4 lib/form/filemanager.js
@@ -636,7 +636,7 @@ M.form_filemanager.init = function(Y, options) {
dialog = Y.one('#fm-move-dlg');
}
- dialog.set('innerHTML', '<div class="hd">Moving</div><div class="bd"><div id="fm-move-div">'+M.str.repository.nopathselected+'</div><div id="fm-tree"></div></div>');
+ dialog.set('innerHTML', '<div class="hd">'+M.str.repository.moving+'</div><div class="bd"><div id="fm-move-div">'+M.str.repository.nopathselected+'</div><div id="fm-tree"></div></div>');
this.movefile_dialog = new YAHOO.widget.Dialog("fm-move-dlg", {
width : "600px",
@@ -717,7 +717,7 @@ M.form_filemanager.init = function(Y, options) {
var rootNode = treeview.getRoot();
treeview.setDynamicLoad(loadDataForNode);
treeview.removeChildren(rootNode);
- var textnode = {label: "Files", path: '/'};
+ var textnode = {label: M.str.moodle.files, path: '/'};
var tmpNode = new YAHOO.widget.TextNode(textnode, rootNode, true);
treeview.draw();
}, this, true);
View
11 lib/form/filemanager.php
@@ -246,7 +246,7 @@ function form_filemanager_render($options) {
$html = '';
$options = $fm->options;
- $straddfile = get_string('add', 'repository') . '...';
+ $straddfile = get_string('addfile', 'repository');
$strmakedir = get_string('makeafolder', 'moodle');
$strdownload = get_string('downloadfolder', 'repository');
$strloading = get_string('loading', 'repository');
@@ -280,9 +280,9 @@ function form_filemanager_render($options) {
<div id="filemanager-wrapper-{$client_id}" style="display:none">
<div class="fm-breadcrumb" id="fm-path-{$client_id}"></div>
<div class="filemanager-toolbar">
- <input type="button" class="fm-btn-add" id="btnadd-{$client_id}" onclick="return false" value=" {$straddfile}" />
- <input type="button" class="fm-btn-mkdir" id="btncrt-{$client_id}" onclick="return false" value=" $strmakedir" />
- <input type="button" class="fm-btn-download" id="btndwn-{$client_id}" onclick="return false" {$extra} value=" $strdownload" />
+ <input type="button" class="fm-btn-add" id="btnadd-{$client_id}" onclick="return false" value="{$straddfile}" />
+ <input type="button" class="fm-btn-mkdir" id="btncrt-{$client_id}" onclick="return false" value="{$strmakedir}" />
+ <input type="button" class="fm-btn-download" id="btndwn-{$client_id}" onclick="return false" {$extra} value="{$strdownload}" />
<span> $maxsize </span>
</div>
<div class="filemanager-container" id="filemanager-{$client_id}">
@@ -311,7 +311,8 @@ function form_filemanager_render($options) {
array('zip', 'editor'), array('unzip', 'moodle'), array('rename', 'moodle'), array('delete', 'moodle'),
array('cannotdeletefile', 'error'), array('confirmdeletefile', 'repository'),
array('nopathselected', 'repository'), array('popupblockeddownload', 'repository'),
- array('draftareanofiles', 'repository'), array('path', 'moodle'), array('setmainfile', 'repository')
+ array('draftareanofiles', 'repository'), array('path', 'moodle'), array('setmainfile', 'repository'),
+ array('moving', 'repository'), array('files', 'moodle')
)
);
$PAGE->requires->js_module($module);
View
92 lib/gradelib.php
@@ -914,6 +914,84 @@ function grade_force_site_regrading() {
}
/**
+ * Recover a user's grades from grade_grades_history
+ * @param int $userid the user ID whose grades we want to recover
+ * @param int $courseid the relevant course
+ * @return bool true if successful or false if there was an error or no grades could be recovered
+ */
+function grade_recover_history_grades($userid, $courseid) {
+ global $CFG, $DB;
+
+ if ($CFG->disablegradehistory) {
+ debugging('Attempting to recover grades when grade history is disabled.');
+ return false;
+ }
+
+ //Were grades recovered? Flag to return.
+ $recoveredgrades = false;
+
+ //Check the user is enrolled in this course
+ //Dont bother checking if they have a gradeable role. They may get one later so recover
+ //whatever grades they have now just in case.
+ $course_context = get_context_instance(CONTEXT_COURSE, $courseid);
+ if (!is_enrolled($course_context, $userid)) {
+ debugging('Attempting to recover the grades of a user who is deleted or not enrolled. Skipping recover.');
+ return false;
+ }
+
+ //Check for existing grades for this user in this course
+ //Recovering grades when the user already has grades can lead to duplicate indexes and bad data
+ //In the future we could move the existing grades to the history table then recover the grades from before then
+ $sql = "SELECT gg.id
+ FROM {grade_grades} gg
+ JOIN {grade_items} gi ON gi.id = gg.itemid
+ WHERE gi.courseid = :courseid AND gg.userid = :userid";
+ $params = array('userid' => $userid, 'courseid' => $courseid);
+ if ($DB->record_exists_sql($sql, $params)) {
+ debugging('Attempting to recover the grades of a user who already has grades. Skipping recover.');
+ return false;
+ } else {
+ //Retrieve the user's old grades
+ //have history ID as first column to guarantee we a unique first column
+ $sql = "SELECT h.id, gi.itemtype, gi.itemmodule, gi.iteminstance as iteminstance, gi.itemnumber, h.source, h.itemid, h.userid, h.rawgrade, h.rawgrademax,
+ h.rawgrademin, h.rawscaleid, h.usermodified, h.finalgrade, h.hidden, h.locked, h.locktime, h.exported, h.overridden, h.excluded, h.feedback,
+ h.feedbackformat, h.information, h.informationformat, h.timemodified, itemcreated.tm AS timecreated
+ FROM {grade_grades_history} h
+ JOIN (SELECT itemid, MAX(id) AS id
+ FROM {grade_grades_history}
+ WHERE userid = :userid1
+ GROUP BY itemid) maxquery ON h.id = maxquery.id AND h.itemid = maxquery.itemid
+ JOIN {grade_items} gi ON gi.id = h.itemid
+ JOIN (SELECT itemid, MAX(timemodified) AS tm
+ FROM {grade_grades_history}
+ WHERE userid = :userid2 AND action = :insertaction
+ GROUP BY itemid) itemcreated ON itemcreated.itemid = h.itemid
+ WHERE gi.courseid = :courseid";
+ $params = array('userid1' => $userid, 'userid2' => $userid , 'insertaction' => GRADE_HISTORY_INSERT, 'courseid' => $courseid);
+ $oldgrades = $DB->get_records_sql($sql, $params);
+
+ //now move the old grades to the grade_grades table
+ foreach ($oldgrades as $oldgrade) {
+ unset($oldgrade->id);
+
+ $grade = new grade_grade($oldgrade, false);//2nd arg false as dont want to try and retrieve a record from the DB
+ $grade->insert($oldgrade->source);
+
+ //dont include default empty grades created when activities are created
+ if (!is_null($oldgrade->finalgrade) || !is_null($oldgrade->feedback)) {
+ $recoveredgrades = true;
+ }
+ }
+ }
+
+ //Some activities require manual grade synching (moving grades from the activity into the gradebook)
+ //If the student was deleted when synching was done they may have grades in the activity that haven't been moved across
+ grade_grab_course_grades($courseid, null, $userid);
+
+ return $recoveredgrades;
+}
+
+/**
* Updates all final grades in course.
*
* @param int $courseid
@@ -1032,14 +1110,12 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
/**
* Refetches data from all course activities
- *
- * @global object
- * @global object
- * @param int $courseid
- * @param string $modname
+ * @param int $courseid the course ID
+ * @param string $modname limit the grade fetch to a single module type
+ * @param int $userid limit the grade fetch to a single user
* @return void
*/
-function grade_grab_course_grades($courseid, $modname=null) {
+function grade_grab_course_grades($courseid, $modname=null, $userid=0) {
global $CFG, $DB;
if ($modname) {
@@ -1050,7 +1126,7 @@ function grade_grab_course_grades($courseid, $modname=null) {
if ($modinstances = $DB->get_records_sql($sql, $params)) {
foreach ($modinstances as $modinstance) {
- grade_update_mod_grades($modinstance);
+ grade_update_mod_grades($modinstance, $userid);
}
}
return;
@@ -1075,7 +1151,7 @@ function grade_grab_course_grades($courseid, $modname=null) {
if ($modinstances = $DB->get_records_sql($sql, $params)) {
foreach ($modinstances as $modinstance) {
- grade_update_mod_grades($modinstance);
+ grade_update_mod_grades($modinstance, $userid);
}
}
}
View
279 lib/grouplib.php
@@ -141,11 +141,10 @@ function groups_get_grouping($groupingid, $fields='*', $strictness=IGNORE_MISSIN
* @param mixed $userid optional user id or array of ids, returns only groups of the user.
* @param int $groupingid optional returns only groups in the specified grouping.
* @param string $fields
- * @return array|bool Returns an array of the group objects or false if no records
- * or an error occurred. (userid field returned if array in $userid)
+ * @return array Returns an array of the group objects (userid field returned if array in $userid)
*/
function groups_get_all_groups($courseid, $userid=0, $groupingid=0, $fields='g.*') {
- global $CFG, $DB;
+ global $DB;
if (empty($userid)) {
$userfrom = "";
@@ -178,15 +177,12 @@ function groups_get_all_groups($courseid, $userid=0, $groupingid=0, $fields='g.*
/**
* Returns info about user's groups in course.
*
- * @global object
- * @global object
- * @global object
* @param int $courseid
* @param int $userid $USER if not specified
* @return array Array[groupingid][groupid] including grouping id 0 which means all groups
*/
function groups_get_user_groups($courseid, $userid=0) {
- global $CFG, $USER, $DB;
+ global $USER, $DB;
if (empty($userid)) {
$userid = $USER->id;
@@ -392,15 +388,13 @@ function groups_get_activity_groupmode($cm, $course=null) {
/**
* Print group menu selector for course level.
*
- * @global object
- * @global object
- * @param object $course course object
- * @param string $urlroot return address
+ * @param stdClass $course course object
+ * @param string|moodle_url $urlroot return address
* @param boolean $return return as string instead of printing
* @return mixed void or string depending on $return param
*/
function groups_print_course_menu($course, $urlroot, $return=false) {
- global $CFG, $USER, $SESSION, $OUTPUT;
+ global $USER, $OUTPUT;
if (!$groupmode = $course->groupmode) {
if ($return) {
@@ -411,44 +405,18 @@ function groups_print_course_menu($course, $urlroot, $return=false) {
}
$context = get_context_instance(CONTEXT_COURSE, $course->id);
- if ($groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
- $allowedgroups = groups_get_all_groups($course->id, 0, $course->defaultgroupingid);
- // detect changes related to groups and fix active group
- if (!empty($SESSION->activegroup[$course->id][VISIBLEGROUPS][0])) {
- if (!array_key_exists($SESSION->activegroup[$course->id][VISIBLEGROUPS][0], $allowedgroups)) {
- // active does not exist anymore
- unset($SESSION->activegroup[$course->id][VISIBLEGROUPS][0]);
- }