Merge branch 'MDL-36482_23' of https://github.com/mr-russ/moodle into MOODLE_23_STABLE
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 21 May 2013 00:28:34 +0000 (02:28 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Tue, 21 May 2013 00:28:34 +0000 (02:28 +0200)
84 files changed:
admin/registration/forms.php
admin/registration/register.php
admin/registration/renderer.php
admin/tool/unittest/lang/en/tool_unittest.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
backup/util/dbops/restore_dbops.class.php
blog/index.php
blog/lib.php
course/modedit.php
course/moodleform_mod.php
grade/edit/tree/calculation.php
grade/export/lib.php
grade/export/ods/index.php
grade/export/txt/index.php
grade/export/xls/index.php
grade/export/xml/index.php
grade/grading/form/rubric/lang/en/gradingform_rubric.php
grade/lib.php
grade/report/lib.php
grade/report/overview/lib.php
grade/report/upgrade.txt [new file with mode: 0644]
grade/report/user/lib.php
grade/tests/reportlib_test.php
install/lang/gl/error.php
install/lang/he/moodle.php
install/lang/zh_tw/admin.php
lang/en/admin.php
lang/en/backup.php
lang/en/condition.php
lang/en/error.php
lang/en/grades.php
lang/en/hub.php
lang/en/moodle.php
lib/adminlib.php
lib/db/upgrade.php
lib/externallib.php
lib/formslib.php
lib/grade/grade_item.php
lib/grade/tests/grade_item_test.php
lib/gradelib.php
lib/licenselib.php
lib/moodlelib.php
lib/tests/formslib_test.php
lib/tests/moodlelib_test.php
lib/yui/3.5.1/build/io-xdr/io.swf
lib/yui/3.5.1/build/uploader-deprecated/assets/uploader.swf
lib/yui/3.5.1/build/uploader/assets/flashuploader.swf
mod/assign/lib.php
mod/assign/locallib.php
mod/assignment/lang/en/assignment.php
mod/choice/mod_form.php
mod/feedback/lang/en/feedback.php
mod/feedback/mod_form.php
mod/folder/edit.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/mod_form.php
mod/glossary/mod_form.php
mod/lesson/lang/en/lesson.php
mod/lesson/pagetypes/matching.php
mod/lti/lang/en/lti.php
mod/lti/locallib.php
mod/quiz/report/overview/report.php
mod/scorm/datamodels/scorm_12.js.php
mod/scorm/lang/en/scorm.php
mod/scorm/mod_form.php
mod/scorm/report/basic/lang/en/scormreport_basic.php
mod/scorm/report/interactions/lang/en/scormreport_interactions.php
mod/url/lang/en/url.php
mod/workshop/renderer.php
question/behaviour/adaptive/behaviour.php
question/engine/bank.php
question/type/calculated/edit_calculated_form.php
question/type/match/backup/moodle2/restore_qtype_match_plugin.class.php
question/type/questionbase.php
repository/boxnet/lang/en/repository_boxnet.php
repository/lib.php
repository/manage_instances.php
theme/formal_white/lang/en/theme_formal_white.php
theme/formal_white/style/block.css
version.php
webservice/lib.php
webservice/renderer.php

index 0126722..488682b 100644 (file)
@@ -244,6 +244,8 @@ class site_registration_form extends moodleform {
         $questionsnumber = get_config('hub', 'site_questionsnumber_' . $cleanhuburl);
         $resourcesnumber = get_config('hub', 'site_resourcesnumber_' . $cleanhuburl);
         $mediancoursesize = get_config('hub', 'site_mediancoursesize_' . $cleanhuburl);
+        $participantnumberaveragecfg = get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl);
+        $modulenumberaveragecfg = get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl);
 
         //hidden parameters
         $mform->addElement('hidden', 'huburl', $huburl);
@@ -376,36 +378,36 @@ class site_registration_form extends moodleform {
         if (HUB_MOODLEORGHUBURL != $huburl) {
             $mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
                     " " . get_string('coursesnumber', 'hub', $coursecount));
-            $mform->setDefault('courses', true);
+            $mform->setDefault('courses', $coursesnumber != -1);
             $mform->addHelpButton('courses', 'sendfollowinginfo', 'hub');
 
             $mform->addElement('checkbox', 'users', '',
                     " " . get_string('usersnumber', 'hub', $usercount));
-            $mform->setDefault('users', true);
+            $mform->setDefault('users', $usersnumber != -1);
 
             $mform->addElement('checkbox', 'roleassignments', '',
                     " " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
-            $mform->setDefault('roleassignments', true);
+            $mform->setDefault('roleassignments', $roleassignmentsnumber != -1);
 
             $mform->addElement('checkbox', 'posts', '',
                     " " . get_string('postsnumber', 'hub', $postcount));
-            $mform->setDefault('posts', true);
+            $mform->setDefault('posts', $postsnumber != -1);
 
             $mform->addElement('checkbox', 'questions', '',
                     " " . get_string('questionsnumber', 'hub', $questioncount));
-            $mform->setDefault('questions', true);
+            $mform->setDefault('questions', $questionsnumber != -1);
 
             $mform->addElement('checkbox', 'resources', '',
                     " " . get_string('resourcesnumber', 'hub', $resourcecount));
-            $mform->setDefault('resources', true);
+            $mform->setDefault('resources', $resourcesnumber != -1);
 
             $mform->addElement('checkbox', 'participantnumberaverage', '',
                     " " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
-            $mform->setDefault('participantnumberaverage', true);
+            $mform->setDefault('participantnumberaverage', $participantnumberaveragecfg != -1);
 
             $mform->addElement('checkbox', 'modulenumberaverage', '',
                     " " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
-            $mform->setDefault('modulenumberaverage', true);
+            $mform->setDefault('modulenumberaverage', $modulenumberaveragecfg != -1);
         } else {
             $mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
                     " " . get_string('coursesnumber', 'hub', $coursecount));
index 7a6bc92..50a4dde 100644 (file)
@@ -62,7 +62,18 @@ $siteregistrationform = new site_registration_form('',
 $fromform = $siteregistrationform->get_data();
 
 if (!empty($fromform) and confirm_sesskey()) {
-    //save the settings
+
+    // Set to -1 all optional data marked as "don't send" by the admin.
+    // The function get_site_info() will not calculate the optional data if config is set to -1.
+    $inputnames = array('courses', 'users', 'roleassignments', 'posts', 'questions', 'resources',
+        'modulenumberaverage', 'participantnumberaverage');
+    foreach ($inputnames as $inputname) {
+        if (empty($fromform->{$inputname})) {
+            $fromform->{$inputname} = -1;
+        }
+    }
+
+    // Save the settings.
     $cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
     set_config('site_name_' . $cleanhuburl, $fromform->name, 'hub');
     set_config('site_description_' . $cleanhuburl, $fromform->description, 'hub');
@@ -113,6 +124,19 @@ if ($update and confirm_sesskey()) {
 if (!empty($fromform) and empty($update) and confirm_sesskey()) {
 
     if (!empty($fromform) and confirm_sesskey()) { // if the register button has been clicked
+
+        // Retrieve the optional info (specially course number, user number, module number average...).
+        $siteinfo = $registrationmanager->get_site_info($huburl);
+        $fromform->courses = $siteinfo['courses'];
+        $fromform->users = $siteinfo['users'];
+        $fromform->enrolments = $siteinfo['enrolments'];
+        $fromform->posts = $siteinfo['posts'];
+        $fromform->questions = $siteinfo['questions'];
+        $fromform->resources = $siteinfo['resources'];
+        $fromform->modulenumberaverage = $siteinfo['modulenumberaverage'];
+        $fromform->participantnumberaverage = $siteinfo['participantnumberaverage'];
+        $fromform->street = $siteinfo['street'];
+
         $params = (array) $fromform; //we are using the form input as the redirection parameters (token, url and name)
 
         $unconfirmedhub = $registrationmanager->get_unconfirmedhub($huburl);
index d5ca165..caf1be7 100644 (file)
@@ -38,7 +38,7 @@ class core_register_renderer extends plugin_renderer_base {
     public function moodleorg_registration_message() {
         $moodleorgurl = html_writer::link('http://moodle.org', 'Moodle.org');
         $moodleorgstatsurl = html_writer::link('http://moodle.org/stats', get_string('statsmoodleorg', 'admin'));
-        $moochurl = html_writer::link(HUB_MOODLEORGHUBURL, 'MOOCH');
+        $moochurl = html_writer::link(HUB_MOODLEORGHUBURL, 'Moodle.net');
         $moodleorgregmsg = get_string('registermoodleorg', 'admin', $moodleorgurl);
         $items = array(get_string('registermoodleorgli1', 'admin'),
             get_string('registermoodleorgli2', 'admin', $moodleorgstatsurl),
@@ -92,4 +92,4 @@ class core_register_renderer extends plugin_renderer_base {
         return html_writer::table($table);
     }
 
-}
\ No newline at end of file
+}
index ce4bb36..705e4a0 100644 (file)
@@ -69,7 +69,7 @@ $string['showsearch'] = 'Show the search for test files.';
 $string['skip'] = 'Skip';
 $string['stacktrace'] = 'Stack trace:';
 $string['summary'] = '{$a->run}/{$a->total} test cases complete: <strong>{$a->passes}</strong> passes, <strong>{$a->fails}</strong> fails and <strong>{$a->exceptions}</strong> exceptions.';
-$string['tablesnotsetup'] = 'Unit test tables are not yet built. Do you want to build them now?.';
+$string['tablesnotsetup'] = 'Unit test tables are not yet built. Do you want to build them now?';
 $string['testdboperations'] = 'Test database operations';
 $string['testtablescsvfileunwritable'] = 'The test tables CSV file is not writable ({$a->filename})';
 $string['testtablesneedupgrade'] = 'The test DB tables need to be upgraded. Do you wish to proceed with the upgrade now?';
index e5e1691..1844aee 100644 (file)
@@ -1764,6 +1764,10 @@ class backup_questions_structure_step extends backup_structure_step {
         $qhint = new backup_nested_element('question_hint', array('id'), array(
             'hint', 'hintformat', 'shownumcorrect', 'clearwrong', 'options'));
 
+        $tags = new backup_nested_element('tags');
+
+        $tag = new backup_nested_element('tag', array('id'), array('name', 'rawname'));
+
         // Build the tree
 
         $qcategories->add_child($qcategory);
@@ -1772,6 +1776,9 @@ class backup_questions_structure_step extends backup_structure_step {
         $question->add_child($qhints);
         $qhints->add_child($qhint);
 
+        $question->add_child($tags);
+        $tags->add_child($tag);
+
         // Define the sources
 
         $qcategory->set_source_sql("
@@ -1791,6 +1798,12 @@ class backup_questions_structure_step extends backup_structure_step {
                 ORDER BY id',
                 array('questionid' => backup::VAR_PARENTID));
 
+        $tag->set_source_sql("SELECT t.id, t.name, t.rawname
+                               FROM {tag} t
+                               JOIN {tag_instance} ti ON ti.tagid = t.id
+                               WHERE ti.itemid = ?
+                               AND ti.itemtype = 'question'", array(backup::VAR_PARENTID));
+
         // don't need to annotate ids nor files
         // (already done by {@link backup_annotate_all_question_files}
 
index aa5b79e..4a72b31 100644 (file)
@@ -2875,10 +2875,13 @@ class restore_create_categories_and_questions extends restore_structure_step {
         $hint = new restore_path_element('question_hint',
                 '/question_categories/question_category/questions/question/question_hints/question_hint');
 
+        $tag = new restore_path_element('tag',
+            '/question_categories/question_category/questions/question/tags/tag');
+
         // Apply for 'qtype' plugins optional paths at question level
         $this->add_plugin_structure('qtype', $question);
 
-        return array($category, $question, $hint);
+        return array($category, $question, $hint, $tag);
     }
 
     protected function process_question_category($data) {
@@ -3025,6 +3028,29 @@ class restore_create_categories_and_questions extends restore_structure_step {
         $this->set_mapping('question_hint', $oldid, $newitemid);
     }
 
+    protected function process_tag($data) {
+        global $CFG, $DB;
+
+        $data = (object)$data;
+        $newquestion = $this->get_new_parentid('question');
+
+        if (!empty($CFG->usetags)) { // if enabled in server
+            // TODO: This is highly inneficient. Each time we add one tag
+            // we fetch all the existing because tag_set() deletes them
+            // so everything must be reinserted on each call
+            $tags = array();
+            $existingtags = tag_get_tags('question', $newquestion);
+            // Re-add all the existitng tags
+            foreach ($existingtags as $existingtag) {
+                $tags[] = $existingtag->rawname;
+            }
+            // Add the one being restored
+            $tags[] = $data->rawname;
+            // Send all the tags back to the question
+            tag_set('question', $newquestion, $tags);
+        }
+    }
+
     protected function after_execute() {
         global $DB;
 
index c4d42d4..f1f253d 100644 (file)
@@ -822,7 +822,7 @@ abstract class restore_dbops {
      * @return array of result object
      */
     public static function send_files_to_pool($basepath, $restoreid, $component, $filearea, $oldcontextid, $dfltuserid, $itemname = null, $olditemid = null, $forcenewcontextid = null, $skipparentitemidctxmatch = false) {
-        global $DB;
+        global $DB, $CFG;
 
         $results = array();
 
@@ -917,6 +917,12 @@ abstract class restore_dbops {
 
                 // create the file in the filepool if it does not exist yet
                 if (!$fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) {
+
+                    // If no license found, use default.
+                    if ($file->license == null){
+                        $file->license = $CFG->sitedefaultlicense;
+                    }
+
                     $file_record = array(
                         'contextid'   => $newcontextid,
                         'component'   => $component,
index c008427..6f4525d 100644 (file)
@@ -183,13 +183,7 @@ if (!empty($userid)) {
             print_error('donothaveblog', 'blog');
         }
     } else {
-        $personalcontext = get_context_instance(CONTEXT_USER, $userid);
-
-        if (!has_capability('moodle/blog:view', $sitecontext) && !has_capability('moodle/user:readuserblogs', $personalcontext)) {
-            print_error('cannotviewuserblog', 'blog');
-        }
-
-        if (!blog_user_can_view_user_entry($userid)) {
+        if (!has_capability('moodle/blog:view', $sitecontext) || !blog_user_can_view_user_entry($userid)) {
             print_error('cannotviewcourseblog', 'blog');
         }
 
index b8e1884..1fb3e6c 100644 (file)
@@ -65,35 +65,36 @@ function blog_user_can_view_user_entry($targetuserid, $blogentry=null) {
     global $CFG, $USER, $DB;
 
     if (empty($CFG->bloglevel)) {
-        return false; // blog system disabled
+        return false; // Blog system disabled.
     }
 
     if (isloggedin() && $USER->id == $targetuserid) {
-        return true; // can view own entries in any case
+        return true; // Can view own entries in any case.
     }
 
     $sitecontext = get_context_instance(CONTEXT_SYSTEM);
     if (has_capability('moodle/blog:manageentries', $sitecontext)) {
-        return true; // can manage all entries
+        return true; // Can manage all entries.
     }
 
-    // coming for 1 entry, make sure it's not a draft
+    // If blog is in draft state, then make sure user have proper capability.
     if ($blogentry && $blogentry->publishstate == 'draft' && !has_capability('moodle/blog:viewdrafts', $sitecontext)) {
-        return false;  // can not view draft of others
+        return false;  // Can not view draft of others.
     }
 
-    // coming for 0 entry, make sure user is logged in, if not a public blog
+    // If blog entry is not public, make sure user is logged in.
     if ($blogentry && $blogentry->publishstate != 'public' && !isloggedin()) {
         return false;
     }
 
+    // If blogentry is not passed or all above checks pass, then check capability based on system config.
     switch ($CFG->bloglevel) {
         case BLOG_GLOBAL_LEVEL:
             return true;
         break;
 
         case BLOG_SITE_LEVEL:
-            if (isloggedin()) { // not logged in viewers forbidden
+            if (isloggedin()) { // Not logged in viewers forbidden.
                 return true;
             }
             return false;
@@ -101,6 +102,7 @@ function blog_user_can_view_user_entry($targetuserid, $blogentry=null) {
 
         case BLOG_USER_LEVEL:
         default:
+            // If user is viewing other user blog, then user should have user:readuserblogs capability.
             $personalcontext = get_context_instance(CONTEXT_USER, $targetuserid);
             return has_capability('moodle/user:readuserblogs', $personalcontext);
         break;
@@ -1001,6 +1003,8 @@ function blog_get_associated_count($courseid, $cmid=null) {
  * may have switch to turn on/off comments option, this callback will
  * affect UI display, not like pluginname_comment_validate only throw
  * exceptions.
+ * blog_comment_validate will be called before viewing/adding/deleting
+ * comment, so don't repeat checks.
  * Capability check has been done in comment->check_permissions(), we
  * don't need to do it again here.
  *
@@ -1017,7 +1021,17 @@ function blog_get_associated_count($courseid, $cmid=null) {
  * @return array
  */
 function blog_comment_permissions($comment_param) {
-    return array('post'=>true, 'view'=>true);
+    global $DB;
+
+    // If blog is public and current usre is guest, then don't let him post comments.
+    $blogentry = $DB->get_record('post', array('id' => $comment_param->itemid), 'publishstate', MUST_EXIST);
+
+    if ($blogentry->publishstate != 'public') {
+        if (!isloggedin() || isguestuser()) {
+            return array('post' => false, 'view' => true);
+        }
+    }
+    return array('post' => true, 'view' => true);
 }
 
 /**
@@ -1036,16 +1050,21 @@ function blog_comment_permissions($comment_param) {
  * @return boolean
  */
 function blog_comment_validate($comment_param) {
-    global $DB;
-    // validate comment itemid
-    if (!$entry = $DB->get_record('post', array('id'=>$comment_param->itemid))) {
-        throw new comment_exception('invalidcommentitemid');
+    global $CFG, $DB, $USER;
+
+    // Check if blogs are enabled user can comment.
+    if (empty($CFG->bloglevel) || empty($CFG->blogusecomments)) {
+        throw new comment_exception('nopermissiontocomment');
     }
-    // validate comment area
+
+    // Validate comment area.
     if ($comment_param->commentarea != 'format_blog') {
         throw new comment_exception('invalidcommentarea');
     }
-    // validation for comment deletion
+
+    $blogentry = $DB->get_record('post', array('id' => $comment_param->itemid), '*', MUST_EXIST);
+
+    // Validation for comment deletion.
     if (!empty($comment_param->commentid)) {
         if ($record = $DB->get_record('comments', array('id'=>$comment_param->commentid))) {
             if ($record->commentarea != 'format_blog') {
@@ -1061,7 +1080,11 @@ function blog_comment_validate($comment_param) {
             throw new comment_exception('invalidcommentid');
         }
     }
-    return true;
+
+    // Validate if user has blog view permission.
+    $sitecontext = context_system::instance();
+    return has_capability('moodle/blog:view', $sitecontext) &&
+            blog_user_can_view_user_entry($blogentry->userid, $blogentry);
 }
 
 /**
index 3e79b85..3b2e575 100644 (file)
@@ -335,7 +335,7 @@ if ($mform->is_cancelled()) {
         $cm->groupmembersonly = $fromform->groupmembersonly;
 
         $completion = new completion_info($course);
-        if ($completion->is_enabled()) {
+        if ($completion->is_enabled() && !empty($fromform->completionunlocked)) {
             // Update completion settings
             $cm->completion                = $fromform->completion;
             $cm->completiongradeitemnumber = $fromform->completiongradeitemnumber;
index a62cb97..1d80117 100644 (file)
@@ -303,8 +303,11 @@ abstract class moodleform_mod extends moodleform {
         }
 
         // Completion: Don't let them choose automatic completion without turning
-        // on some conditions
-        if (array_key_exists('completion', $data) && $data['completion']==COMPLETION_TRACKING_AUTOMATIC) {
+        // on some conditions. Ignore this check when completion settings are
+        // locked, as the options are then disabled.
+        if (array_key_exists('completion', $data) &&
+                $data['completion'] == COMPLETION_TRACKING_AUTOMATIC &&
+                !empty($data['completionunlocked'])) {
             if (empty($data['completionview']) && empty($data['completionusegrade']) &&
                 !$this->completion_rule_enabled($data)) {
                 $errors['completion'] = get_string('badautocompletion', 'completion');
index 4ca8065..6012687 100644 (file)
@@ -30,7 +30,7 @@ require_once 'calculation_form.php';
 $courseid  = required_param('courseid', PARAM_INT);
 $id        = required_param('id', PARAM_INT);
 $section   = optional_param('section', 'calculation', PARAM_ALPHA);
-$idnumbers = optional_param('idnumbers', null, PARAM_RAW);
+$idnumbers = optional_param_array('idnumbers', null, PARAM_RAW);
 
 $url = new moodle_url('/grade/edit/tree/calculation.php', array('id'=>$id, 'courseid'=>$courseid));
 if ($section !== 'calculation') {
index 1530d2c..c9f7517 100644 (file)
@@ -406,3 +406,13 @@ class grade_export_update_buffer {
     }
 }
 
+/**
+ * Verify that there is a valid set of grades to export.
+ * @param $courseid int The course being exported
+ */
+function export_verify_grades($courseid) {
+    $regraderesult = grade_regrade_final_grades($courseid);
+    if (is_array($regraderesult)) {
+        throw new moodle_exception('gradecantregrade', 'error', '', implode(', ', array_unique($regraderesult)));
+    }
+}
index 78cd116..d5b937c 100644 (file)
@@ -34,6 +34,7 @@ require_capability('moodle/grade:export', $context);
 require_capability('gradeexport/ods:view', $context);
 
 print_grade_page_head($COURSE->id, 'export', 'ods', get_string('exportto', 'grades') . ' ' . get_string('pluginname', 'gradeexport_ods'));
+export_verify_grades($COURSE->id);
 
 if (!empty($CFG->gradepublishing)) {
     $CFG->gradepublishing = has_capability('gradeexport/ods:publish', $context);
index 7f5f842..a305925 100644 (file)
@@ -34,6 +34,7 @@ require_capability('moodle/grade:export', $context);
 require_capability('gradeexport/txt:view', $context);
 
 print_grade_page_head($COURSE->id, 'export', 'txt', get_string('exportto', 'grades') . ' ' . get_string('pluginname', 'gradeexport_txt'));
+export_verify_grades($COURSE->id);
 
 if (!empty($CFG->gradepublishing)) {
     $CFG->gradepublishing = has_capability('gradeexport/txt:publish', $context);
index 68d7f67..9bf1c55 100644 (file)
@@ -34,6 +34,7 @@ require_capability('moodle/grade:export', $context);
 require_capability('gradeexport/xls:view', $context);
 
 print_grade_page_head($COURSE->id, 'export', 'xls', get_string('exportto', 'grades') . ' ' . get_string('pluginname', 'gradeexport_xls'));
+export_verify_grades($COURSE->id);
 
 if (!empty($CFG->gradepublishing)) {
     $CFG->gradepublishing = has_capability('gradeexport/xls:publish', $context);
index 3903846..7e4bc8b 100644 (file)
@@ -34,6 +34,7 @@ require_capability('moodle/grade:export', $context);
 require_capability('gradeexport/xml:view', $context);
 
 print_grade_page_head($COURSE->id, 'export', 'xml', get_string('exportto', 'grades') . ' ' . get_string('pluginname', 'gradeexport_xml'));
+export_verify_grades($COURSE->id);
 
 if (!empty($CFG->gradepublishing)) {
     $CFG->gradepublishing = has_capability('gradeexport/xml:publish', $context);
index 527e8fb..dcb11c9 100644 (file)
@@ -36,7 +36,7 @@ $string['criterionmovedown'] = 'Move down';
 $string['criterionmoveup'] = 'Move up';
 $string['definerubric'] = 'Define rubric';
 $string['description'] = 'Description';
-$string['enableremarks'] = 'Allow grader to add text remarks for each criteria';
+$string['enableremarks'] = 'Allow grader to add text remarks for each criterion';
 $string['err_mintwolevels'] = 'Each criterion must have at least two levels';
 $string['err_nocriteria'] = 'Rubric must contain at least one criterion';
 $string['err_nodefinition'] = 'Level definition can not be empty';
index dd7afbf..216acd4 100644 (file)
@@ -22,7 +22,8 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once $CFG->libdir.'/gradelib.php';
+require_once($CFG->libdir . '/gradelib.php');
+require_once($CFG->dirroot . '/grade/export/lib.php');
 
 /**
  * This class iterates over all users that are graded in a course.
@@ -123,7 +124,7 @@ class graded_users_iterator {
 
         $this->close();
 
-        grade_regrade_final_grades($this->course->id);
+        export_verify_grades($this->course->id);
         $course_item = grade_item::fetch_course_item($this->course->id);
         if ($course_item->needsupdate) {
             // can not calculate all final grades - sorry
index 6e6db0b..12b7e04 100644 (file)
@@ -357,7 +357,12 @@ abstract class grade_report {
         // If we're dealing with multiple courses we need to know when we've moved on to a new course.
         static $previous_courseid = null;
 
-        if( $this->showtotalsifcontainhidden==GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN ) {
+        if (!is_array($this->showtotalsifcontainhidden)) {
+            debugging('showtotalsifcontainhidden should be an array', DEBUG_DEVELOPER);
+            $this->showtotalsifcontainhidden = array($courseid => $this->showtotalsifcontainhidden);
+        }
+
+        if ($this->showtotalsifcontainhidden[$courseid] == GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN) {
             return $finalgrade;
         }
 
@@ -395,7 +400,7 @@ abstract class grade_report {
 
         //if the item definitely depends on a hidden item
         if (array_key_exists($course_item->id, $hiding_affected['altered'])) {
-            if( !$this->showtotalsifcontainhidden ) {
+            if( !$this->showtotalsifcontainhidden[$courseid] ) {
                 //hide the grade
                 $finalgrade = null;
             }
@@ -405,7 +410,7 @@ abstract class grade_report {
             }
         } else if (!empty($hiding_affected['unknown'][$course_item->id])) {
             //not sure whether or not this item depends on a hidden item
-            if( !$this->showtotalsifcontainhidden ) {
+            if( !$this->showtotalsifcontainhidden[$courseid] ) {
                 //hide the grade
                 $finalgrade = null;
             }
index 61461e5..7a47f9a 100644 (file)
@@ -71,8 +71,6 @@ class grade_report_overview extends grade_report {
         global $CFG, $COURSE, $DB;
         parent::__construct($COURSE->id, $gpr, $context);
 
-        $this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_overview_showtotalsifcontainhidden', $CFG->grade_report_overview_showtotalsifcontainhidden);
-
         // Get the user (for full name).
         $this->user = $DB->get_record('user', array('id' => $userid));
 
@@ -81,12 +79,17 @@ class grade_report_overview extends grade_report {
 
         $this->showrank = array();
         $this->showrank['any'] = false;
+
+        $this->showtotalsifcontainhidden = array();
+
         if ($this->courses) {
             foreach ($this->courses as $course) {
                 $this->showrank[$course->id] = grade_get_setting($course->id, 'report_overview_showrank', !empty($CFG->grade_report_overview_showrank));
                 if ($this->showrank[$course->id]) {
                     $this->showrank['any'] = true;
                 }
+
+                $this->showtotalsifcontainhidden[$course->id] = grade_get_setting($course->id, 'report_overview_showtotalsifcontainhidden', $CFG->grade_report_overview_showtotalsifcontainhidden);
             }
         }
 
diff --git a/grade/report/upgrade.txt b/grade/report/upgrade.txt
new file mode 100644 (file)
index 0000000..4a8d086
--- /dev/null
@@ -0,0 +1,7 @@
+This files describes API changes in /grade/report/*,
+information provided here is intended especially for developers.
+
+
+=== 2.3.5, 2.4.2 ===
+* class_grade_report::showtotalsifcontainhidden has been switched from a single integer value to an array.
+The array keys are course IDs while the array values are the value of the course setting "report_overview_showtotalsifcontainhidden".
index 1058c07..e9c017d 100644 (file)
@@ -165,7 +165,7 @@ class grade_report_user extends grade_report {
         $this->showrank        = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank);
         $this->showpercentage  = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage);
         $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
-        $this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
+        $this->showtotalsifcontainhidden = array($this->courseid => grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden));
 
         $this->showgrade       = grade_get_setting($this->courseid, 'report_user_showgrade',       !empty($CFG->grade_report_user_showgrade));
         $this->showrange       = grade_get_setting($this->courseid, 'report_user_showrange',       !empty($CFG->grade_report_user_showrange));
index 48b0eaa..af3f791 100644 (file)
@@ -120,15 +120,15 @@ class gradereportlib_testcase extends advanced_testcase {
         $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
 
         // Should return the supplied student total grade regardless of hiding.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals($datagrade + $forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
 
         // Should blank the student total as course grade depends on a hidden item.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
 
         // Should return the course total minus the hidden database activity grade.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals($forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
 
         // Note: we cannot simply hide modules and call $report->blank_hidden_total() again.
@@ -182,16 +182,16 @@ class gradereportlib_testcase extends advanced_testcase {
         $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
 
         // Should return the supplied student total grade regardless of hiding.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals($datagrade + $forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
 
         // Should blank the student total as course grade depends on a hidden item.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
 
         // Should return the course total minus the hidden activity grades.
         // They are both hidden so should return null.
-        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN;
+        $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
         $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
     }
 }
index 5fac766..dfa4b25 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['cannotcreatelangdir'] = 'Non pode crear directorio de idioma';
-$string['cannotcreatetempdir'] = 'Non pode crear directorio de tempo';
-$string['cannotdownloadcomponents'] = 'Non pode descargar compoñentes.';
-$string['cannotdownloadzipfile'] = 'Non pode descargar ficheiros ZIP.';
-$string['cannotfindcomponent'] = 'Non pode encontrar compoñentes';
-$string['cannotsavemd5file'] = 'Non pode gardar o ficheiro md5.';
-$string['cannotsavezipfile'] = 'Non pode gardar un ficheiro ZIP.';
-$string['cannotunzipfile'] = 'Non pode descomprimir o ficheiro.';
-$string['componentisuptodate'] = 'O compoñente está actualizado.';
-$string['downloadedfilecheckfailed'] = 'Fallou a verificación do ficheiro descargado.';
+$string['cannotcreatelangdir'] = 'Non se pode crear o directorio de idioma';
+$string['cannotcreatetempdir'] = 'Non se pode crear un directorio temporal';
+$string['cannotdownloadcomponents'] = 'Non foi posíbel descargar compoñentes';
+$string['cannotdownloadzipfile'] = 'Non foi posíbel descargar o ficheiro ZIP';
+$string['cannotfindcomponent'] = 'Non foi posíbel atopar o compoñente';
+$string['cannotsavemd5file'] = 'Non é posíbel gardar o ficheiro md5';
+$string['cannotsavezipfile'] = 'Non é posíbel gardar o ficheiro ZIP';
+$string['cannotunzipfile'] = 'Non é posíbel descomprimir o ficheiro';
+$string['componentisuptodate'] = 'O compoñente está actualizado';
+$string['downloadedfilecheckfailed'] = 'A comprobación do ficheiro descargado non foi satisfactoria';
 $string['invalidmd5'] = 'md5 non válido';
 $string['missingrequiredfield'] = 'Falta algún campo obrigatorio';
 $string['wrongdestpath'] = 'Camiño de destino errado.';
index 63d637a..46b031b 100644 (file)
@@ -31,6 +31,6 @@
 defined('MOODLE_INTERNAL') || die();
 
 $string['language'] = 'שפת ממשק';
-$string['next'] = '×\94×\9c×\90×\94';
+$string['next'] = '×\94×\91×\90';
 $string['previous'] = 'קודם';
 $string['reload'] = 'טען מחדש';
index da5ca9a..ef3c788 100644 (file)
@@ -32,12 +32,11 @@ defined('MOODLE_INTERNAL') || die();
 
 $string['clianswerno'] = 'n';
 $string['cliansweryes'] = 'y';
-$string['cliincorrectvalueerror'] = '錯誤,不正確的值 "{$a->value}" 用於 "{$a->option}"';
-$string['cliincorrectvalueretry'] = '不正確的值,請再試一次';
+$string['cliincorrectvalueerror'] = '錯誤,將“{$a->option}”的值設為“{$a->value}”是不正確的';
+$string['cliincorrectvalueretry'] = '不正確值,請重試';
 $string['clitypevalue'] = '輸入值';
-$string['clitypevaluedefault'] = '輸入值,按Enter可使用預設值({$a})';
-$string['cliunknowoption'] = '不認得的選項:  {$a}
-請使用 --幫助 選項。';
-$string['cliyesnoprompt'] = '輸入y(是) 或n(否)';
+$string['clitypevaluedefault'] = '輸入值,按回車使用預設值({$a})';
+$string['cliunknowoption'] = '錯誤選項:{$a}請使用 --help 選項。';
+$string['cliyesnoprompt'] = '輸入y(表示是)或n(表示否)';
 $string['environmentrequireinstall'] = '必須安裝並啟用';
-$string['environmentrequireversion'] = 'è¦\81æ±\82ç\89\88æ\9c¬ç\82º {$a->needed} ï¼\8cæ\82¨ç\9b®å\89\8dç\89\88æ\9c¬ç\82º {$a->current}';
+$string['environmentrequireversion'] = 'é\9c\80æ±\82ç\89\88æ\9c¬ç\82º{$a->needed}ï¼\8cè\80\8cæ\82¨ç\9b®å\89\8dç\89\88æ\9c¬ç\82º {$a->current}';
index 5bbb0bc..39e526d 100644 (file)
@@ -353,7 +353,7 @@ $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 extended course names';
-$string['courselistshortnames_desc'] = 'When showing lists of courses, or when referring to courses on administration screens, show the course short name as well as the full name. In fact, when you turn this setting on, the display uses the \'courseextendednamedisplay\' language string, so you can changewhat is displayed using Language customisation.';
+$string['courselistshortnames_desc'] = 'If enabled, course short names will be displayed in addition to full names in course lists. If required, extended course names may be customised by editing the \'courseextendednamedisplay\' language string using the language customisation feature.';
 $string['coursemgmt'] = 'Add/edit courses';
 $string['courseoverview'] = 'Course overview';
 $string['courserequestnotify'] = 'Course request notification';
@@ -825,7 +825,7 @@ $string['profilingallowall_help'] = 'If you enable this setting, then, at any mo
 $string['profilingallowme'] = 'Selective profiling';
 $string['profilingallowme_help'] = 'If you enable this setting, then, selectively, you can use the PROFILEME parameter anywhere (PGC) and profiling for that script will happen. Analogously, you can use the DONTPROFILEME parameter to prevent profiling to happen';
 $string['profilingautofrec'] = 'Automatic profiling';
-$string['profilingautofrec_help'] = 'By configuring this setting, some request (randomly, based on the frecuency specified - 1 of XXX) will be picked and automatically profiled, storing results for further analysis. Note that this way of profiling observes the include/exclude settings. Set it to 0 to disable automatic profiling.';
+$string['profilingautofrec_help'] = 'By configuring this setting, some request (randomly, based on the frequency specified - 1 of N) will be picked and automatically profiled, storing results for further analysis. Note that this way of profiling observes the include/exclude settings. Set it to 0 to disable automatic profiling.';
 $string['profilingenabled'] = 'Enable profiling';
 $string['profilingenabled_help'] = 'If you enable this setting, then profiling will be available in this site and you will be able to define its behavior by configuring the next options.';
 $string['profilingexcluded'] = 'Exclude profiling';
@@ -858,10 +858,10 @@ $string['register'] = 'Register your site';
 $string['registermoodleorg'] = 'When you register your site with {$a}';
 $string['registermoodleorgli1'] = 'You are added to a low-volume mailing list for important notifications such as security alerts and new releases of Moodle.';
 $string['registermoodleorgli2'] = 'Statistics about your site will be added to the {$a} of the worldwide Moodle community.';
-$string['registermoodleorgli3'] = 'Your site is also registered with the Moodle.org Open Community Hub ({$a}), allowing users with the publish courses capability (by default only managers) the option of publishing courses to MOOCH.';
+$string['registermoodleorgli3'] = 'Your site is also registered with Moodle.net ({$a}), allowing users with the publish courses capability (by default only managers) the option of publishing courses to Moodle.net.';
 $string['registerwithmoodleorg'] = 'Register with Moodle.org';
 $string['registration'] = 'Registration';
-$string['registration_help'] = 'Registering your site with Moodle.org is recommended in order to receive security alert notifications, to contribute <a href="http://moodle.org/stats">Moodle usage statistics</a> and to be able to share courses on <a href="http://hub.moodle.org/">MOOCH</a>.';
+$string['registration_help'] = 'Registering your site with Moodle.org is recommended in order to receive security alert notifications, to contribute <a href="http://moodle.org/stats">Moodle usage statistics</a> and to be able to share courses on <a href="http://moodle.net/">Moodle.net</a>.';
 $string['registrationwarning'] = 'Your site is not yet registered.';
 $string['releasenoteslink'] = 'For information about this version of Moodle, please see the online <a target="_blank" href="{$a}">Release Notes</a>';
 $string['rememberusername'] = 'Remember username';
@@ -1025,16 +1025,16 @@ This can cause significant problems later, so in order to continue you must ensu
 The recommended way to clean your Moodle directory is as follows:
 
 * rename the current Moodle directory to "moodle_old"
-* create a new Moodle directory containing only files from either a standard Moodle package download, or from the Moodle CVS or GIT repositories
+* create a new Moodle directory containing only files from either a standard Moodle package download, or from the Moodle Git repository
 * move the original config.php file and any non-standard plugins from the "moodle_old" directory to the new Moodle directory
 
 When you have a clean Moodle directory, refresh this page to resume the Moodle update process.
 
 This warning is often caused by unzipping a standard Moodle package over a previous version of Moodle. While this is OK for minor upgrades, it is strongly discouraged for major Moodle upgrades.
 
-This warning can also be caused by an incomplete checkout or update operation from a CVS, SVN or GIT repository, in which case you may just have to wait for the operation complete, or perhaps run the appropriate clean up command and retry the operation.
+This warning can also be caused by an incomplete checkout or update operation from the Git repository, in which case you may just have to wait for the operation to complete, or perhaps run the appropriate clean-up command and retry the operation.
 
-You can find more information in upgrade documentation at <a href="{$a}">{$a}</a>';
+You can find more information in upgrade documentation at <a href="{$a}">{$a}</a>.';
 $string['upgradesure'] = 'Your Moodle files have been changed, and you are about to automatically upgrade your server to this version: <br /><br />
 <strong>{$a}</strong> <br /><br />
 Once you do this you can not go back again. <br /><br />
index 3658375..dd05149 100644 (file)
@@ -235,7 +235,7 @@ $string['selectacourse'] = 'Select a course';
 $string['setting_overwriteconf'] = 'Overwrite course configuration';
 $string['setting_course_fullname'] = 'Course name';
 $string['setting_course_shortname'] = 'Course short name';
-$string['setting_course_startdate'] = 'Course startdate';
+$string['setting_course_startdate'] = 'Course start date';
 $string['setting_keep_roles_and_enrolments'] = 'Keep current roles and enrolments';
 $string['setting_keep_groups_and_groupings'] = 'Keep current groups and groupings';
 $string['totalcategorysearchresults'] = 'Total categories: {$a}';
index fddd673..d55116e 100644 (file)
@@ -29,7 +29,7 @@ $string['availabilityconditions'] = 'Restrict access';
 $string['availablefrom'] = 'Allow access from';
 $string['availablefrom_help'] = 'Access from/to dates determine when students can access the activity via a link on the course page.
 
-The difference between access from/to dates and availability settings for the activity is that outside the set dates the latter allows students to view the activity description, whereas access from/to dates prevent access completely.';
+The difference between access from/to dates and availability settings for the activity is that outside the set dates, access from/to prevents access completely, while availability allows students to view the activity description.';
 $string['availableuntil'] = 'Allow access until';
 $string['badavailabledates'] = 'Invalid dates. If you set both dates, the \'Allow access from\' date should be before the \'until\' date.';
 $string['badgradelimits'] = 'If you set both an upper and lower grade limit, the upper limit must be higher than the lower limit.';
index cf61481..cb06a00 100644 (file)
@@ -238,6 +238,7 @@ $string['filternotinstalled'] = 'Filter {$a} is not currently installed';
 $string['forumblockingtoomanyposts'] = 'You have exceeded the posting threshold set for this forum';
 $string['generalexceptionmessage'] = 'Exception - {$a}';
 $string['gradepubdisable'] = 'Grade publishing disabled';
+$string['gradecantregrade'] = 'An error occurred during grade calculation: {$a}';
 $string['groupalready'] = 'User already belongs to group {$a}';
 $string['groupexistforcourse'] = 'Group "{$a}" already exists for this course';
 $string['groupexistforcoursewithidnumber'] = '{$a->problemgroup}: Group "{$a->name}" with an idnumber of "{$a->idnumber}" already exists for this course';
index 850e873..b1b0eee 100644 (file)
@@ -172,6 +172,7 @@ $string['enableoutcomes_help'] = 'Support for Outcomes (also known as Competenci
 $string['encoding'] = 'Encoding';
 $string['errorcalculationnoequal'] = 'Formula must start with equal sign (=1+2)';
 $string['errorcalculationunknown'] = 'Invalid formula';
+$string['errorcalculationbroken'] = 'Probably circular reference or broken calculation formula';
 $string['errorgradevaluenonnumeric'] = 'Received non-numeric for low or high grade for';
 $string['errornocalculationallowed'] = 'Calculations are not allowed for this item';
 $string['errornocategorisedid'] = 'Could not get an uncategorised id!';
index 4b8cd53..81e0c1e 100644 (file)
@@ -160,7 +160,7 @@ $string['registeredsites'] = 'Registered sites';
 $string['registrationinfo'] = 'Registration information';
 $string['registeredmoodleorg'] = 'Moodle.org ({$a})';
 $string['registeredon'] = 'Hubs with which you are registered';
-$string['registermoochtips'] = 'To be registered with Moodle.org Open Community Hub (MOOCH), your site must be registered with Moodle.org.';
+$string['registermoochtips'] = 'In order to register with Moodle.net, your site must be registered with Moodle.org.';
 $string['registersite'] = 'Register with {$a}';
 $string['registerwith'] = 'Register with a hub';
 $string['registrationconfirmed'] = 'Site registration confirmed';
index 47796d1..6bffe3b 100644 (file)
@@ -312,7 +312,7 @@ $string['coursehelpforce'] = 'Force the course group mode to every activity in t
 $string['coursehelpformat'] = 'The course main page will be displayed in this format.';
 $string['coursehelphiddensections'] = 'How the hidden sections in the course are displayed to students.';
 $string['coursehelpmaximumupload'] = 'Define the largest size of file that can be uploaded in this course, limited by the site-wide setting.';
-$string['coursehelpnewsitemsnumber'] = 'Number of recent items appearing on the course home page, in a news box down the right-hand side (0 means the news box won\'t appear).';
+$string['coursehelpnewsitemsnumber'] = 'Number of recent items from the news forum appearing in the latest news block on the course page. If set to zero, the latest news block will not be displayed.';
 $string['coursehelpnumberweeks'] = 'Number of sections in the course (applies to certain course formats only).';
 $string['coursehelpshowgrades'] = 'Enable the display of the gradebook. It does not prevent grades from being displayed within the individual activities.';
 $string['coursehidden'] = 'This course is currently unavailable to students';
@@ -322,9 +322,7 @@ $string['coursenotaccessible'] = 'This course does not allow public access';
 $string['courselegacyfiles'] = 'Legacy course files';
 $string['courselegacyfiles_help'] = 'The course files area provides some backward compatibility with Moodle 1.9 and earlier.  All files in this area are always accessible to all participants in the course (whether you link to them or not) and there is no way to know where any of these files are being used in Moodle.
 
-If you use this area to store course files, you can expose yourself to a number of privacy and security issues, as well as experiencing missing files in backups, course imports and any time content is shared or re-used.  It is therefore recommended that you do not use this area unless you really know what you are doing.
-
-The link below provides more information about all this and will show you some better ways to manage files in Moodle 2.';
+If you use this area to store course files, you can expose yourself to a number of privacy and security issues, as well as experiencing missing files in backups, course imports and any time content is shared or re-used.  It is therefore recommended that you do not use this area unless you really know what you are doing.';
 $string['courselegacyfiles_link'] = 'coursefiles2';
 $string['courseoverview'] = 'Course overview';
 $string['courseoverviewgraph'] = 'Course overview graph';
index 18f06e7..fa7adbe 100644 (file)
@@ -7544,7 +7544,7 @@ class admin_setting_managewebservicetokens extends admin_setting {
 
                 $validuntil = '';
                 if (!empty($token->validuntil)) {
-                    $validuntil = date("F j, Y"); //TODO: language support (look for moodle function)
+                    $validuntil = userdate($token->validuntil, get_string('strftimedatetime', 'langconfig'));
                 }
 
                 $iprestriction = '';
index 04ae4e1..cc0cc36 100644 (file)
@@ -1166,5 +1166,26 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012062506.08);
     }
 
+    if ($oldversion < 2012062507.01) {
+        // Fix incorrect cc-nc url. Unfortunately the license 'plugins' do
+        // not give a mechanism to do this.
+
+        $sql = "UPDATE {license}
+                   SET source = :url, version = :newversion
+                 WHERE shortname = :shortname AND version = :oldversion";
+
+        $params = array(
+            'url' => 'http://creativecommons.org/licenses/by-nc/3.0/',
+            'shortname' => 'cc-nc',
+            'newversion' => '2013051500',
+            'oldversion' => '2010033100'
+        );
+
+        $DB->execute($sql, $params);
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2012062507.01);
+    }
+
     return true;
 }
index da21ace..d458d11 100644 (file)
@@ -687,6 +687,7 @@ function external_format_text($text, $textformat, $contextid, $component, $filea
     $settings = external_settings::get_instance();
 
     if ($settings->get_fileurl()) {
+        require_once($CFG->libdir . "/filelib.php");
         $text = file_rewrite_pluginfile_urls($text, $settings->get_file(), $contextid, $component, $filearea, $itemid);
     }
 
index 83b06c9..9d46fe6 100644 (file)
@@ -1513,6 +1513,81 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
         $this->_types = $paramtypes + $this->_types;
     }
 
+    /**
+     * Return the type(s) to use to clean an element.
+     *
+     * In the case where the element has an array as a value, we will try to obtain a
+     * type defined for that specific key, and recursively until done.
+     *
+     * This method does not work reverse, you cannot pass a nested element and hoping to
+     * fallback on the clean type of a parent. This method intends to be used with the
+     * main element, which will generate child types if needed, not the other way around.
+     *
+     * Example scenario:
+     *
+     * You have defined a new repeated element containing a text field called 'foo'.
+     * By default there will always be 2 occurence of 'foo' in the form. Even though
+     * you've set the type on 'foo' to be PARAM_INT, for some obscure reason, you want
+     * the first value of 'foo', to be PARAM_FLOAT, which you set using setType:
+     * $mform->setType('foo[0]', PARAM_FLOAT).
+     *
+     * Now if you call this method passing 'foo', along with the submitted values of 'foo':
+     * array(0 => '1.23', 1 => '10'), you will get an array telling you that the key 0 is a
+     * FLOAT and 1 is an INT. If you had passed 'foo[1]', along with its value '10', you would
+     * get the default clean type returned (param $default).
+     *
+     * @param string $elementname name of the element.
+     * @param mixed $value value that should be cleaned.
+     * @param int $default default constant value to be returned (PARAM_...)
+     * @return string|array constant value or array of constant values (PARAM_...)
+     */
+    public function getCleanType($elementname, $value, $default = PARAM_RAW) {
+        $type = $default;
+        if (array_key_exists($elementname, $this->_types)) {
+            $type = $this->_types[$elementname];
+        }
+        if (is_array($value)) {
+            $default = $type;
+            $type = array();
+            foreach ($value as $subkey => $subvalue) {
+                $typekey = "$elementname" . "[$subkey]";
+                if (array_key_exists($typekey, $this->_types)) {
+                    $subtype = $this->_types[$typekey];
+                } else {
+                    $subtype = $default;
+                }
+                if (is_array($subvalue)) {
+                    $type[$subkey] = $this->getCleanType($typekey, $subvalue, $subtype);
+                } else {
+                    $type[$subkey] = $subtype;
+                }
+            }
+        }
+        return $type;
+    }
+
+    /**
+     * Return the cleaned value using the passed type(s).
+     *
+     * @param mixed $value value that has to be cleaned.
+     * @param int|array $type constant value to use to clean (PARAM_...), typically returned by {@link self::getCleanType()}.
+     * @return mixed cleaned up value.
+     */
+    public function getCleanedValue($value, $type) {
+        if (is_array($type) && is_array($value)) {
+            foreach ($type as $key => $param) {
+                $value[$key] = $this->getCleanedValue($value[$key], $param);
+            }
+        } else if (!is_array($type) && !is_array($value)) {
+            $value = clean_param($value, $type);
+        } else if (!is_array($type) && is_array($value)) {
+            $value = clean_param_array($value, $type, true);
+        } else {
+            throw new coding_exception('Unexpected type or value received in MoodleQuickForm::getCleanedValue()');
+        }
+        return $value;
+    }
+
     /**
      * Updates submitted values
      *
@@ -1525,17 +1600,9 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
         if (empty($submission)) {
             $this->_submitValues = array();
         } else {
-            foreach ($submission as $key=>$s) {
-                if (array_key_exists($key, $this->_types)) {
-                    $type = $this->_types[$key];
-                } else {
-                    $type = PARAM_RAW;
-                }
-                if (is_array($s)) {
-                    $submission[$key] = clean_param_array($s, $type, true);
-                } else {
-                    $submission[$key] = clean_param($s, $type);
-                }
+            foreach ($submission as $key => $s) {
+                $type = $this->getCleanType($key, $s);
+                $submission[$key] = $this->getCleanedValue($s, $type);
             }
             $this->_submitValues = $submission;
             $this->_flagSubmitted = true;
index 4610192..8d66765 100644 (file)
@@ -1503,6 +1503,11 @@ class grade_item extends grade_object {
         $oldgrade->feedback       = $grade->feedback;
         $oldgrade->feedbackformat = $grade->feedbackformat;
 
+        // MDL-31713 rawgramemin and max must be up to date so conditional access %'s works properly.
+        $grade->rawgrademin = $this->grademin;
+        $grade->rawgrademax = $this->grademax;
+        $grade->rawscaleid  = $this->scaleid;
+
         // changed grade?
         if ($finalgrade !== false) {
             if ($this->is_overridable_item()) {
index 78bfa20..1d1f943 100644 (file)
@@ -63,6 +63,7 @@ class grade_item_testcase extends grade_base_testcase {
         $this->sub_test_grade_item_set_calculation();
         $this->sub_test_grade_item_get_calculation();
         $this->sub_test_grade_item_compute();
+        $this->sub_test_update_final_grade();
     }
 
     protected function sub_test_grade_item_construct() {
@@ -552,4 +553,34 @@ class grade_item_testcase extends grade_base_testcase {
         $grade_grade = grade_grade::fetch(array('userid'=>$this->grade_grades[5]->userid, 'itemid'=>$this->grade_grades[5]->itemid));
         $this->assertEquals($this->grade_grades[5]->finalgrade, $grade_grade->finalgrade);
     }
+
+    protected function sub_test_update_final_grade() {
+
+        // MDL-31713 Check that min and max are set on the grade_grade instance
+        // if the grade is overridden before the activity has supplied a grade.
+        $min = 2;
+        $max = 8;
+
+        // Create a brand new grade item.
+        $grade_item = new grade_item();
+        $this->assertTrue(method_exists($grade_item, 'insert'));
+
+        $grade_item->courseid = $this->courseid;
+        $grade_item->categoryid = $this->grade_categories[1]->id;
+        $grade_item->itemname = 'brand new unit test grade item';
+        $grade_item->itemtype = 'mod';
+        $grade_item->itemmodule = 'quiz';
+        $grade_item->iteminfo = 'Grade item used for unit testing';
+        $grade_item->grademin = $min;
+        $grade_item->grademax = $max;
+        $grade_item->insert();
+
+        // Override the student grade.
+        $grade_item->update_final_grade($this->user[1]->id, 7, 'gradebook', '', FORMAT_MOODLE);
+
+        // Check the student's grade has the correct min and max grade.
+        $grade_grade = grade_grade::fetch(array('userid'=>$this->user[1]->id, 'itemid'=>$grade_item->id));
+        $this->assertEquals($min, $grade_grade->rawgrademin);
+        $this->assertEquals($max, $grade_grade->rawgrademax);
+    }
 }
index c59bd1c..6012543 100644 (file)
@@ -1097,9 +1097,9 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
                     continue; // this one is ok
                 }
                 $grade_items[$gid]->force_regrading();
-                $errors[$grade_items[$gid]->id] = 'Probably circular reference or broken calculation formula'; // TODO: localize
+                $errors[$grade_items[$gid]->id] = get_string('errorcalculationbroken', 'grades');
             }
-            break; // oki, found error
+            break; // Found error.
         }
     }
 
index c670055..5cd4c3d 100644 (file)
@@ -192,9 +192,9 @@ class license_manager {
 
         $license->shortname = 'cc-nc';
         $license->fullname = 'Creative Commons - No Commercial';
-        $license->source = 'http://creativecommons.org/licenses/by-nd/3.0/';
+        $license->source = 'http://creativecommons.org/licenses/by-nc/3.0/';
         $license->enabled = 1;
-        $license->version = '2010033100';
+        $license->version = '2013051500';
         $active_licenses[] = $license->shortname;
         self::add($license);
 
index 1ddfafb..90ba8c2 100644 (file)
@@ -901,10 +901,7 @@ function clean_param($param, $type) {
         case PARAM_PLUGIN:
         case PARAM_AREA:
             // we do not want any guessing here, either the name is correct or not
-            if (!preg_match('/^[a-z][a-z0-9_]*[a-z0-9]$/', $param)) {
-                return '';
-            }
-            if (strpos($param, '__') !== false) {
+            if (!is_valid_plugin_name($param)) {
                 return '';
             }
             return $param;
@@ -8009,6 +8006,15 @@ function get_plugin_types($fullpaths=true) {
     return ($fullpaths ? $fullinfo : $info);
 }
 
+/**
+ * This method validates a plug name. It is much faster than calling clean_param.
+ * @param string $name a string that might be a plugin name.
+ * @return bool if this string is a valid plugin name.
+ */
+function is_valid_plugin_name($name) {
+    return (bool) preg_match('/^[a-z](?:[a-z0-9_](?!__))*[a-z0-9]$/', $name);
+}
+
 /**
  * Simplified version of get_list_of_plugins()
  * @param string $plugintype type of plugin
@@ -8070,9 +8076,8 @@ function get_plugin_list($plugintype) {
             if (in_array($pluginname, $ignored)) {
                 continue;
             }
-            $pluginname = clean_param($pluginname, PARAM_PLUGIN);
-            if (empty($pluginname)) {
-                // better ignore plugins with problematic names here
+            if (!is_valid_plugin_name($pluginname)) {
+                // Better ignore plugins with problematic names here.
                 continue;
             }
             $result[$pluginname] = $fulldir.'/'.$pluginname;
index b4bebf3..eab98a3 100644 (file)
@@ -190,6 +190,129 @@ class formslib_testcase extends basic_testcase {
         $this->assertTag(array('tag'=>'input', 'id'=>'id_repeatradio_2_2',
             'attributes'=>array('type'=>'radio', 'name'=>'repeatradio[2]', 'value'=>'2')), $html);
     }
+
+    public function test_type_cleaning() {
+        $expectedtypes = array(
+            'simpleel' => PARAM_INT,
+            'groupel1' => PARAM_INT,
+            'groupel2' => PARAM_FLOAT,
+            'groupel3' => PARAM_INT,
+            'namedgroup' => array(
+                'sndgroupel1' => PARAM_INT,
+                'sndgroupel2' => PARAM_FLOAT,
+                'sndgroupel3' => PARAM_INT
+            ),
+            'namedgroupinherit' => array(
+                'thdgroupel1' => PARAM_INT,
+                'thdgroupel2' => PARAM_INT
+            ),
+            'repeatedel' => array(
+                0 => PARAM_INT,
+                1 => PARAM_INT
+            ),
+            'repeatedelinherit' => array(
+                0 => PARAM_INT,
+                1 => PARAM_INT
+            ),
+            'squaretest' => array(
+                0 => PARAM_INT
+            ),
+            'nested' => array(
+                0 => array(
+                    'bob' => array(
+                        123 => PARAM_INT,
+                        'foo' => PARAM_FLOAT
+                    ),
+                    'xyz' => PARAM_RAW
+                ),
+                1 => PARAM_INT
+            )
+        );
+        $valuessubmitted = array(
+            'simpleel' => '11.01',
+            'groupel1' => '11.01',
+            'groupel2' => '11.01',
+            'groupel3' => '11.01',
+            'namedgroup' => array(
+                'sndgroupel1' => '11.01',
+                'sndgroupel2' => '11.01',
+                'sndgroupel3' => '11.01'
+            ),
+            'namedgroupinherit' => array(
+                'thdgroupel1' => '11.01',
+                'thdgroupel2' => '11.01'
+            ),
+            'repeatedel' => array(
+                0 => '11.01',
+                1 => '11.01'
+            ),
+            'repeatedelinherit' => array(
+                0 => '11.01',
+                1 => '11.01'
+            ),
+            'squaretest' => array(
+                0 => '11.01'
+            ),
+            'nested' => array(
+                0 => array(
+                    'bob' => array(
+                        123 => '11.01',
+                        'foo' => '11.01'
+                    ),
+                    'xyz' => '11.01'
+                ),
+                1 => '11.01'
+            )
+        );
+        $expectedvalues = array(
+            'simpleel' => 11,
+            'groupel1' => 11,
+            'groupel2' => 11.01,
+            'groupel3' => 11,
+            'namedgroup' => array(
+                'sndgroupel1' => 11,
+                'sndgroupel2' => 11.01,
+                'sndgroupel3' => 11
+            ),
+            'namedgroupinherit' => array(
+                'thdgroupel1' => 11,
+                'thdgroupel2' => 11
+            ),
+            'repeatable' => 2,
+            'repeatedel' => array(
+                0 => 11,
+                1 => 11
+            ),
+            'repeatableinherit' => 2,
+            'repeatedelinherit' => array(
+                0 => 11,
+                1 => 11
+            ),
+            'squaretest' => array(
+                0 => 11
+            ),
+            'nested' => array(
+                0 => array(
+                    'bob' => array(
+                        123 => 11,
+                        'foo' => 11.01
+                    ),
+                    'xyz' => '11.01'
+                ),
+                1 => 11
+            )
+        );
+
+        $mform = new formslib_clean_value();
+        $mform->get_form()->updateSubmission($valuessubmitted, null);
+        foreach ($expectedtypes as $elementname => $expected) {
+            $actual = $mform->get_form()->getCleanType($elementname, $valuessubmitted[$elementname]);
+            $this->assertSame($expected, $actual, "Failed validating clean type of '$elementname'");
+        }
+
+        $data = $mform->get_data();
+        $this->assertSame($expectedvalues, (array) $data);
+    }
 }
 
 
@@ -217,4 +340,72 @@ class formslib_test_form extends moodleform {
         );
         $this->repeat_elements($repeatels, 3, array(), 'numradios', 'addradios');
     }
-}
\ No newline at end of file
+}
+
+class formslib_clean_value extends moodleform {
+    public function get_form() {
+        return $this->_form;
+    }
+    public function definition() {
+        $mform = $this->_form;
+
+        // Add a simple int.
+        $mform->addElement('text', 'simpleel', 'simpleel');
+        $mform->setType('simpleel', PARAM_INT);
+
+        // Add a non-named group.
+        $group = array(
+            $mform->createElement('text', 'groupel1', 'groupel1'),
+            $mform->createElement('text', 'groupel2', 'groupel2'),
+            $mform->createElement('text', 'groupel3', 'groupel3')
+        );
+        $mform->setType('groupel1', PARAM_INT);
+        $mform->setType('groupel2', PARAM_FLOAT);
+        $mform->setType('groupel3', PARAM_INT);
+        $mform->addGroup($group);
+
+        // Add a named group.
+        $group = array(
+            $mform->createElement('text', 'sndgroupel1', 'sndgroupel1'),
+            $mform->createElement('text', 'sndgroupel2', 'sndgroupel2'),
+            $mform->createElement('text', 'sndgroupel3', 'sndgroupel3')
+        );
+        $mform->addGroup($group, 'namedgroup');
+        $mform->setType('namedgroup[sndgroupel1]', PARAM_INT);
+        $mform->setType('namedgroup[sndgroupel2]', PARAM_FLOAT);
+        $mform->setType('namedgroup[sndgroupel3]', PARAM_INT);
+
+        // Add a named group, with inheritance.
+        $group = array(
+            $mform->createElement('text', 'thdgroupel1', 'thdgroupel1'),
+            $mform->createElement('text', 'thdgroupel2', 'thdgroupel2')
+        );
+        $mform->addGroup($group, 'namedgroupinherit');
+        $mform->setType('namedgroupinherit', PARAM_INT);
+
+        // Add a repetition.
+        $repeat = $mform->createElement('text', 'repeatedel', 'repeatedel');
+        $this->repeat_elements(array($repeat), 2, array('repeatedel' => array('type' => PARAM_INT)), 'repeatable', 'add', 0);
+
+        // Add a repetition, with inheritance.
+        $repeat = $mform->createElement('text', 'repeatedelinherit', 'repeatedelinherit');
+        $this->repeat_elements(array($repeat), 2, array(), 'repeatableinherit', 'add', 0);
+        $mform->setType('repeatedelinherit', PARAM_INT);
+
+        // Add an arbitrary named element.
+        $mform->addElement('text', 'squaretest[0]', 'squaretest[0]');
+        $mform->setType('squaretest[0]', PARAM_INT);
+
+        // Add an arbitrary nested array named element.
+        $mform->addElement('text', 'nested[0][bob][123]', 'nested[0][bob][123]');
+        $mform->setType('nested[0][bob][123]', PARAM_INT);
+
+        // Add inheritance test cases.
+        $mform->setType('nested', PARAM_INT);
+        $mform->setType('nested[0]', PARAM_RAW);
+        $mform->setType('nested[0][bob]', PARAM_FLOAT);
+        $mform->addElement('text', 'nested[1]', 'nested[1]');
+        $mform->addElement('text', 'nested[0][xyz]', 'nested[0][xyz]');
+        $mform->addElement('text', 'nested[0][bob][foo]', 'nested[0][bob][foo]');
+    }
+}
index 13e7d1e..09999c7 100644 (file)
@@ -833,6 +833,21 @@ class moodlelib_testcase extends advanced_testcase {
         $this->assertSame(clean_param('user_', PARAM_COMPONENT), '');
     }
 
+    function test_is_valid_plugin_name() {
+        $this->assertTrue(is_valid_plugin_name('forum'));
+        $this->assertTrue(is_valid_plugin_name('forum2'));
+        $this->assertTrue(is_valid_plugin_name('online_users'));
+        $this->assertTrue(is_valid_plugin_name('blond_online_users'));
+        $this->assertFalse(is_valid_plugin_name('online__users'));
+        $this->assertFalse(is_valid_plugin_name('forum '));
+        $this->assertFalse(is_valid_plugin_name('forum.old'));
+        $this->assertFalse(is_valid_plugin_name('xx-yy'));
+        $this->assertFalse(is_valid_plugin_name('2xx'));
+        $this->assertFalse(is_valid_plugin_name('Xx'));
+        $this->assertFalse(is_valid_plugin_name('_xx'));
+        $this->assertFalse(is_valid_plugin_name('xx_'));
+    }
+
     function test_clean_param_plugin() {
         // please note the cleaning of plugin names is very strict, no guessing here
         $this->assertSame(clean_param('forum', PARAM_PLUGIN), 'forum');
index dc1e59e..4d5a835 100644 (file)
Binary files a/lib/yui/3.5.1/build/io-xdr/io.swf and b/lib/yui/3.5.1/build/io-xdr/io.swf differ
index 95b853a..43a6206 100644 (file)
Binary files a/lib/yui/3.5.1/build/uploader-deprecated/assets/uploader.swf and b/lib/yui/3.5.1/build/uploader-deprecated/assets/uploader.swf differ
index e10be58..b8fdeee 100644 (file)
Binary files a/lib/yui/3.5.1/build/uploader/assets/flashuploader.swf and b/lib/yui/3.5.1/build/uploader/assets/flashuploader.swf differ
index 240a8f7..8ed7eaf 100644 (file)
@@ -1017,11 +1017,11 @@ function assign_user_outline($course, $user, $coursemodule, $assignment) {
     $gradingitem = $gradinginfo->items[0];
     $gradebookgrade = $gradingitem->grades[$user->id];
 
-    if (!$gradebookgrade) {
+    if (empty($gradebookgrade->str_long_grade)) {
         return null;
     }
     $result = new stdClass();
-    $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->grade);
+    $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->str_long_grade);
     $result->time = $gradebookgrade->dategraded;
 
     return $result;
index 0a5d8c4..e97c2e5 100644 (file)
@@ -1565,6 +1565,8 @@ class assign {
         // more efficient to load this here
         require_once($CFG->libdir.'/filelib.php');
 
+        require_capability('mod/assign:grade', $this->context);
+
         // load all submissions
         $submissions = $this->get_all_submissions('','');
 
index 888f522..0cc20f7 100644 (file)
@@ -57,7 +57,7 @@ $string['availabledate'] = 'Available from';
 $string['cannotdeletefiles'] = 'An error occurred and files could not be deleted';
 $string['cannotviewassignment'] = 'You can not view this assignment';
 $string['changegradewarning'] = 'This assignment has graded submissions and changing the grade will not automatically re-calculate existing submission grades. You must re-grade all existing submissions, if you wish to change the grade.';
-$string['closedassignment'] = 'The submission date for this assignment has been closed.';
+$string['closedassignment'] = 'This assignment is closed, as the submission deadline has passed.';
 $string['comment'] = 'Comment';
 $string['commentinline'] = 'Comment inline';
 $string['commentinline_help'] = 'If enabled, the submission text will be copied into the feedback comment field during grading, making it easier to comment inline (using a different colour, perhaps) or to edit the original text.';
index 04011a0..9923208 100644 (file)
@@ -140,8 +140,10 @@ class mod_choice_mod_form extends moodleform_mod {
             return false;
         }
         // Set up completion section even if checkbox is not ticked
-        if (empty($data->completionsection)) {
-            $data->completionsection=0;
+        if (!empty($data->completionunlocked)) {
+            if (empty($data->completionsubmit)) {
+                $data->completionsubmit = 0;
+            }
         }
         return $data;
     }
index 2e27645..8872450 100644 (file)
@@ -91,9 +91,9 @@ $string['dropdown_values'] = 'Answers';
 $string['drop_feedback'] = 'Remove from this course';
 $string['edit_item'] = 'Edit question';
 $string['edit_items'] = 'Edit questions';
-$string['email_notification'] = 'Send e-mail notifications';
+$string['email_notification'] = 'Enable notification of submissions';
 $string['emailnotification'] = 'emailnotifications';
-$string['emailnotification_help'] = 'If enabled, administrators receive email notification of feedback submissions.';
+$string['emailnotification_help'] = 'If enabled, teachers will receive notification of feedback submissions.';
 $string['emailteachermail'] = '{$a->username} has completed feedback activity : \'{$a->feedback}\'
 
 You can view it here:
index 9edb6cf..2fe4bae 100644 (file)
@@ -203,14 +203,13 @@ class mod_feedback_mod_form extends moodleform_mod {
             $data->page_after_submitformat = $data->page_after_submit_editor['format'];
             $data->page_after_submit = $data->page_after_submit_editor['text'];
 
-            // Turn off completion settings if the checkboxes aren't ticked
-            $autocompletion = !empty($data->completion) AND
-                                    $data->completion==COMPLETION_TRACKING_AUTOMATIC;
-            if (empty($data->completion) || !$autocompletion) {
-                $data->completionsubmit=0;
-            }
-            if (empty($data->completionsubmit)) {
-                $data->completionsubmit=0;
+            if (!empty($data->completionunlocked)) {
+                // Turn off completion settings if the checkboxes aren't ticked
+                $autocompletion = !empty($data->completion) &&
+                    $data->completion == COMPLETION_TRACKING_AUTOMATIC;
+                if (!$autocompletion || empty($data->completionsubmit)) {
+                    $data->completionsubmit=0;
+                }
             }
         }
 
index 0b74e47..09b012c 100644 (file)
@@ -39,8 +39,6 @@ $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
 require_login($course, false, $cm);
 require_capability('mod/folder:managefiles', $context);
 
-add_to_log($course->id, 'folder', 'edit', 'edit.php?id='.$cm->id, $folder->id, $cm->id);
-
 $PAGE->set_url('/mod/folder/edit.php', array('id' => $cm->id));
 $PAGE->set_title($course->shortname.': '.$folder->name);
 $PAGE->set_heading($course->fullname);
@@ -59,6 +57,9 @@ if ($mform->is_cancelled()) {
 } else if ($formdata = $mform->get_data()) {
     $formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $context, 'mod_folder', 'content', 0);
     $DB->set_field('folder', 'revision', $folder->revision+1, array('id'=>$folder->id));
+
+    add_to_log($course->id, 'folder', 'edit', 'edit.php?id='.$cm->id, $folder->id, $cm->id);
+
     redirect(new moodle_url('/mod/folder/view.php', array('id'=>$cm->id)));
 }
 
index 44b91cf..6cb07f9 100644 (file)
@@ -387,9 +387,7 @@ $string['subscribestop'] = 'I don\'t want email copies of posts to this forum';
 $string['subscription'] = 'Subscription';
 $string['subscription_help'] = 'If you are subscribed to a forum it means you will receive email copies of forum posts. Usually you can choose whether you wish to be subscribed, though sometimes subscription is forced so that everyone receives email copies of forum posts.';
 $string['subscriptionmode'] = 'Subscription mode';
-$string['subscriptionmode_help'] = 'When a participant is subscribed to a forum it means they will receive email copies of forum posts.
-
-There are 4 subscription mode options:
+$string['subscriptionmode_help'] = 'When a participant is subscribed to a forum it means they will receive forum post notifications. There are 4 subscription mode options:
 
 * Optional subscription - Participants can choose whether to be subscribed
 * Forced subscription - Everyone is subscribed and cannot unsubscribe
index 928fda4..d9f28be 100644 (file)
@@ -3719,7 +3719,7 @@ function forum_print_discussion_header(&$post, $forum, $group=-1, $datestring=""
     echo "</td>\n";
 
     // User name
-    $fullname = fullname($post, has_capability('moodle/site:viewfullnames', $modcontext));
+    $fullname = fullname($postuser, has_capability('moodle/site:viewfullnames', $modcontext));
     echo '<td class="author">';
     echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->userid.'&amp;course='.$forum->course.'">'.$fullname.'</a>';
     echo "</td>\n";
index 260d5ee..c963b09 100644 (file)
@@ -235,15 +235,17 @@ class mod_forum_mod_form extends moodleform_mod {
             return false;
         }
         // Turn off completion settings if the checkboxes aren't ticked
-        $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC;
-        if (empty($data->completiondiscussionsenabled) || !$autocompletion) {
-            $data->completiondiscussions = 0;
-        }
-        if (empty($data->completionrepliesenabled) || !$autocompletion) {
-            $data->completionreplies = 0;
-        }
-        if (empty($data->completionpostsenabled) || !$autocompletion) {
-            $data->completionposts = 0;
+        if (!empty($data->completionunlocked)) {
+            $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC;
+            if (empty($data->completiondiscussionsenabled) || !$autocompletion) {
+                $data->completiondiscussions = 0;
+            }
+            if (empty($data->completionrepliesenabled) || !$autocompletion) {
+                $data->completionreplies = 0;
+            }
+            if (empty($data->completionpostsenabled) || !$autocompletion) {
+                $data->completionposts = 0;
+            }
         }
         return $data;
     }
index 5610534..79404d1 100644 (file)
@@ -196,10 +196,12 @@ class mod_glossary_mod_form extends moodleform_mod {
         if (!$data) {
             return false;
         }
-        // Turn off completion settings if the checkboxes aren't ticked
-        $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC;
-        if (empty($data->completionentriesenabled) || !$autocompletion) {
-            $data->completionentries = 0;
+        if (!empty($data->completionunlocked)) {
+            // Turn off completion settings if the checkboxes aren't ticked
+            $autocompletion = !empty($data->completion) && $data->completion==COMPLETION_TRACKING_AUTOMATIC;
+            if (empty($data->completionentriesenabled) || !$autocompletion) {
+                $data->completionentries = 0;
+            }
         }
         return $data;
     }
index e7dd8aa..cb136c0 100644 (file)
@@ -242,7 +242,7 @@ $string['maximumnumberofattemptsreached'] = 'Maximum number of attempts reached
 $string['maxtime'] = 'Time limit (minutes)';
 $string['maxtimewarning'] = 'You have {$a} minute(s) to finish the lesson.';
 $string['mediaclose'] = 'Show close button:';
-$string['mediafile'] = 'Pop-up to file or web page';
+$string['mediafile'] = 'File pop-up';
 $string['mediafile_help'] = 'To include a pop-up window at the beginning of a lesson, choose the appropriate file to display. Every lesson page will include a link to re-open the pop-up if necessary.';
 $string['mediafilepopup'] = 'Click here to view';
 $string['mediaheight'] = 'Popup window height:';
@@ -280,7 +280,7 @@ $string['nameapproved'] = 'Name approved';
 $string['namereject'] = 'Sorry, your name has been rejected by the filter.<br />Please try another name.';
 $string['new'] = 'new';
 $string['nextpage'] = 'Next page';
-$string['noanswer'] = 'No answer given.  Please go back and submit an answer.';
+$string['noanswer'] = 'One or more questions have no answer given.  Please go back and submit an answer.';
 $string['noattemptrecordsfound'] = 'No attempt records found: no grade given';
 $string['nobranchtablefound'] = 'No content page found';
 $string['nocommentyet'] = 'No comment yet.';
index 09cdf47..3c77e53 100644 (file)
@@ -161,28 +161,28 @@ class lesson_page_type_matching extends lesson_page {
         }
 
         $response = $data->response;
-        if (!is_array($response)) {
-            $result->noanswer = true;
-            return $result;
-        }
-
-        $answers = $this->get_answers();
+        $getanswers = $this->get_answers();
 
-        $correct = array_shift($answers);
-        $wrong   = array_shift($answers);
+        $correct = array_shift($getanswers);
+        $wrong   = array_shift($getanswers);
 
-        foreach ($answers as $key=>$answer) {
+        $answers = array();
+        foreach ($getanswers as $key=>$answer) {
             if ($answer->answer !== '' or $answer->response !== '') {
                 $answers[$answer->id] = $answer;
             }
-            unset($answers[$key]);
+            unset($getanswers[$key]);
         }
-        // get he users exact responses for record keeping
+        // get the user's exact responses for record keeping
         $hits = 0;
         $userresponse = array();
         foreach ($response as $id => $value) {
+            if ($value == '') {
+                $result->noanswer = true;
+                return $result;
+            }
             $userresponse[] = $value;
-            // Make sure the user's answer is exist in question's answer
+            // Make sure the user's answer exists in question's answer
             if (array_key_exists($id, $answers)) {
                 $answer = $answers[$id];
                 $result->studentanswer .= '<br />'.format_text($answer->answer, $answer->answerformat, $formattextdefoptions).' = '.$answers[$value]->response;
index 0521fc1..337a87f 100644 (file)
@@ -400,48 +400,27 @@ $string['tool_config_not_found'] = 'Tool configuration not found for this URL.';
 $string['tool_settings'] = 'Tool Settings';
 $string['toolsetup'] = 'External Tool Configuration';
 $string['toolurl'] = 'Tool Base URL';
-$string['toolurl_help'] = 'The tool base URL is used to match tool launch URLs to the correct tool configuration. Prefxing the URL with http(s) is optional.
+$string['toolurl_help'] = 'The tool base URL is used to match tool launch URLs to the correct tool configuration. Prefixing the URL with http(s) is optional.
 
 Additionally, the base URL is used as the launch URL if a launch URL is not specified in the external tool instance.
 
-<table>
-    <thead>
-        <tr>
-            <td>
-                <b>Base URL</b>
-            </td>
-            <td>
-                <b>Matches</b>
-            </td>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td>
-                tool.com
-            </td>
-            <td>
-                tool.com, tool.com/quizzes, tool.com/quizzes/quiz.php?id=10, www.tool.com/quizzes
-            </td>
-        </tr>
-        <tr>
-            <td>
-                www.tool.com/quizzes
-            </td>
-            <td>
-                tool.com/quizzes, tool.com/quizzes/take.php?id=10, www.tool.com/quizzes
-            </td>
-        </tr>
-        <tr>
-            <td>
-                quiz.tool.com
-            </td>
-            <td>
-                quiz.tool.com, quiz.tool.com/take.php?id=10
-            </td>
-        </tr>
-    </tbody>
-</table>
+For example, a base URL of *tool.com* would match the following:
+
+* tool.com
+* tool.com/quizzes
+* tool.com/quizzes/quiz.php?id=10
+* www.tool.com/quizzes
+
+A base URL of *www.tool.com/quizzes* would match the following:
+
+* www.tool.com/quizzes
+* tool.com/quizzes
+* tool.com/quizzes/take.php?id=10
+
+A base URL of *quiz.tool.com* would match the following:
+
+* quiz.tool.com
+* quiz.tool.com/take.php?id=10
 
 If two different tool configurations are for the same domain, the most specific match will be used.';
 $string['typename'] = 'Tool Name';
index 63eaacb..3562c46 100644 (file)
@@ -285,7 +285,7 @@ function lti_build_request($instance, $typeconfig, $course) {
     if ($customstr) {
         $custom = lti_split_custom_parameters($customstr);
     }
-    if (!isset($typeconfig['allowinstructorcustom']) || $typeconfig['allowinstructorcustom'] == LTI_SETTING_NEVER) {
+    if (isset($typeconfig['allowinstructorcustom']) && $typeconfig['allowinstructorcustom'] == LTI_SETTING_NEVER) {
         $requestparams = array_merge($custom, $requestparams);
     } else {
         if ($instructorcustomstr) {
index fe1ee96..d4355ec 100644 (file)
@@ -291,6 +291,14 @@ class quiz_overview_report extends quiz_attempts_report {
         }
     }
 
+    /**
+     * Unlock the session and allow the regrading process to run in the background.
+     */
+    protected function unlock_session() {
+        session_get_instance()->write_close();
+        ignore_user_abort(true);
+    }
+
     /**
      * Regrade a particular quiz attempt. Either for real ($dryrun = false), or
      * as a pretend regrade to see which fractions would change. The outcome is
@@ -306,7 +314,8 @@ class quiz_overview_report extends quiz_attempts_report {
      */
     protected function regrade_attempt($attempt, $dryrun = false, $slots = null) {
         global $DB;
-        set_time_limit(30);
+        // Need more time for a quiz with many questions.
+        set_time_limit(300);
 
         $transaction = $DB->start_delegated_transaction();
 
@@ -359,6 +368,7 @@ class quiz_overview_report extends quiz_attempts_report {
     protected function regrade_attempts($quiz, $dryrun = false,
             $groupstudents = array(), $attemptids = array()) {
         global $DB;
+        $this->unlock_session();
 
         $where = "quiz = ? AND preview = 0";
         $params = array($quiz->id);
@@ -400,6 +410,7 @@ class quiz_overview_report extends quiz_attempts_report {
      */
     protected function regrade_attempts_needing_it($quiz, $groupstudents) {
         global $DB;
+        $this->unlock_session();
 
         $where = "quiza.quiz = ? AND quiza.preview = 0 AND qqr.regraded = 0";
         $params = array($quiz->id);
index 5d6a872..5057933 100644 (file)
@@ -646,7 +646,7 @@ function SCORMapi1_2() {
             }
             if (cmi.core.lesson_mode == 'normal') {
                 if (cmi.core.credit == 'credit') {
-                    if (cmi.student_data.mastery_score != '' && cmi.core.score.raw != '') {
+                    if (cmi.student_data.mastery_score !== '' && cmi.core.score.raw !== '') {
                         if (parseFloat(cmi.core.score.raw) >= parseFloat(cmi.student_data.mastery_score)) {
                             cmi.core.lesson_status = 'passed';
                         } else {
index b93e301..7d6a814 100644 (file)
@@ -23,7 +23,7 @@
  */
 $string['toc'] = 'TOC';
 $string['navigation'] = 'Navigation';
-$string['aicchacptimeout'] = 'AICC HACP Timeout';
+$string['aicchacptimeout'] = 'AICC HACP timeout';
 $string['aicchacptimeout_desc'] = 'Length of time in minutes that an external AICC HACP session can remain open';
 $string['aicchacpkeepsessiondata'] = 'AICC HACP session data';
 $string['aicchacpkeepsessiondata_desc'] = 'Length of time in days to keep the external AICC HACP session data (a high setting will fill up the table with old data but may be useful when debugging)';
@@ -34,7 +34,7 @@ $string['adminsettings'] = 'Admin settings';
 $string['advanced'] = 'Parameters';
 $string['allowapidebug'] = 'Activate API debug and tracing (set the capture mask with apidebugmask)';
 $string['allowtypeexternal'] = 'Enable external package type';
-$string['allowtypeexternalaicc'] = 'Enable direct AICC url';
+$string['allowtypeexternalaicc'] = 'Enable direct AICC URL';
 $string['allowtypeexternalaicc_desc'] = 'If enabled this allows a direct url to a simple AICC package';
 $string['allowtypeimsrepository'] = 'Enable IMS package type';
 $string['allowtypelocalsync'] = 'Enable downloaded package type';
@@ -52,7 +52,7 @@ $string['attempt1'] = '1 attempt';
 $string['attr_error'] = 'Bad value for attribute ({$a->attr}) in tag {$a->tag}.';
 $string['autocontinue'] = 'Auto-continue';
 $string['autocontinue_help'] = 'If enabled, subsequent learning objects are launched automatically, otherwise the Continue button must be used.';
-$string['autocontinuedesc'] = 'This preference sets the default auto continue for the activity';
+$string['autocontinuedesc'] = 'If enabled, subsequent learning objects are launched automatically, otherwise the Continue button must be used.';
 $string['averageattempt'] = 'Average attempts';
 $string['badmanifest'] = 'Some manifest errors: see errors log';
 $string['badpackage'] = 'The specified package/manifest is not valid. Check it and try again.';
@@ -86,17 +86,17 @@ $string['disabled'] = 'Disabled';
 $string['display'] = 'Display package';
 $string['displayattemptstatus'] = 'Display attempt status';
 $string['displayattemptstatus_help'] = 'If enabled, scores and grades for attempts are displayed on the SCORM outline page.';
-$string['displayattemptstatusdesc'] = 'This preference sets the default value for the display attempt status setting';
+$string['displayattemptstatusdesc'] = 'Whether a summary of the user\'s attempts is shown in the course overview block in My home and/or the SCORM entry page.';
 $string['displaycoursestructure'] = 'Display course structure on entry page';
 $string['displaycoursestructure_help'] = 'If enabled, the table of contents is displayed on the SCORM outline page.';
-$string['displaycoursestructuredesc'] = 'This preference sets the default value for the display course structure on entry page setting';
-$string['displaydesc'] = 'This preference sets the default of whether to display the package or not for an activity';
-$string['displaysettings'] = 'Display Settings';
+$string['displaycoursestructuredesc'] = 'If enabled, the table of contents is displayed on the SCORM outline page.';
+$string['displaydesc'] = 'Whether to display the SCORM package in a new window.';
+$string['displaysettings'] = 'Display settings';
 $string['dnduploadscorm'] = 'Add a SCORM package';
 $string['domxml'] = 'DOMXML external library';
 $string['duedate'] = 'Due date';
 $string['element'] = 'Element';
-$string['elementdefinition'] = 'Element Definition';
+$string['elementdefinition'] = 'Element definition';
 $string['enter'] = 'Enter';
 $string['entercourse'] = 'Enter course';
 $string['errorlogs'] = 'Errors log';
@@ -113,17 +113,17 @@ $string['finishscormlinkname'] = 'click here to return to the course page';
 $string['firstaccess'] = 'First access';
 $string['firstattempt'] = 'First attempt';
 $string['forcecompleted'] = 'Force completed';
-$string['forcecompleted_help'] = 'If enabled, the status of the current attempt is forced to "completed". This setting is only applicable to SCORM 1.2 packages. It is useful if the SCORM package does not handle revisiting an attempt correctly, in review or browse mode, or otherwise incorrectly issues the completion status.';
+$string['forcecompleted_help'] = 'If enabled, the status of the current attempt is forced to "completed". (Only applicable to SCORM 1.2 packages.)';
 $string['forcecompleteddesc'] = 'This preference sets the default value for the force completed setting';
 $string['forcenewattempt'] = 'Force new attempt';
 $string['forcenewattempt_help'] = 'If enabled, each time a SCORM package is accessed will be counted as a new attempt.';
-$string['forcenewattemptdesc'] = 'This preference sets the default value for the force new attempt setting';
+$string['forcenewattemptdesc'] = 'If enabled, each time a SCORM package is accessed will be counted as a new attempt.';
 $string['forcejavascript'] = 'Force users to enable JavaScript';
-$string['forcejavascript_desc'] = 'If enabled(recommended) this prevents access to SCORM objects when JavaScript is not supported/enabled in a users browser. If disabled the user may view the SCORM but API communication will fail and no grade information will be saved.';
+$string['forcejavascript_desc'] = 'If enabled (recommended) this prevents access to SCORM objects when JavaScript is not supported/enabled in a users browser. If disabled the user may view the SCORM but API communication will fail and no grade information will be saved.';
 $string['forcejavascriptmessage'] = 'JavaScript is required to view this object, please enable JavaScript in your browser and try again.';
 $string['found'] = 'Manifest found';
-$string['frameheight'] = 'This preference set the default height for stage frame or window';
-$string['framewidth'] = 'This preference set the default width for stage frame or window';
+$string['frameheight'] = 'The height of the stage frame or window.';
+$string['framewidth'] = 'The width of the stage frame or window.';
 $string['fullscreen'] = 'Fill the whole screen';
 $string['general'] = 'General data';
 $string['gradeaverage'] = 'Average grade';
@@ -138,7 +138,7 @@ There are 4 grading methods:
 * Highest grade - The highest score obtained in all passed learning objects
 * Average grade - The mean of all the scores
 * Sum grade - The sum of all the scores';
-$string['grademethoddesc'] = 'This preference sets the default grade method for an activity';
+$string['grademethoddesc'] = 'The grading method defines how the grade for a single attempt of the activity is determined.';
 $string['gradereported'] = 'Grade reported';
 $string['gradesettings'] = 'Grade settings';
 $string['gradescoes'] = 'Learning objects';
@@ -147,14 +147,14 @@ $string['height'] = 'Height';
 $string['hidden'] = 'Hidden';
 $string['hidebrowse'] = 'Disable preview mode';
 $string['hidebrowse_help'] = 'Preview mode allows a student to browse an activity before attempting it. If preview mode is disabled, the preview button is hidden.';
-$string['hidebrowsedesc'] = 'This preference sets the default for whether to disable or enable the preview mode';
+$string['hidebrowsedesc'] = 'Preview mode allows a student to browse an activity before attempting it.';
 $string['hideexit'] = 'Hide exit link';
 $string['hidenav'] = 'Hide navigation buttons';
-$string['hidenavdesc'] = 'This preference sets the default for whether to show or hide the navigation buttons';
+$string['hidenavdesc'] = 'Whether to show or hide the navigation buttons.';
 $string['hidereview'] = 'Hide review button';
 $string['hidetoc'] = 'Display course structure in player';
-$string['hidetoc_help'] = 'This setting specifies how the table of contents is displayed in the SCORM player.';
-$string['hidetocdesc'] = 'This preference sets the default for whether to show or hide the course structure (TOC) in the SCORM player';
+$string['hidetoc_help'] = 'How the table of contents is displayed in the SCORM player';
+$string['hidetocdesc'] = 'This setting specifies how the table of contents is displayed in the SCORM player.';
 $string['highestattempt'] = 'Highest attempt';
 $string['chooseapacket'] = 'Choose or update a package';
 $string['identifier'] = 'Question identifier';
@@ -164,27 +164,27 @@ $string['interactions'] = 'Interactions';
 $string['interactionsid'] = 'Id of the element';
 $string['interactionscorrectcount'] = 'Number of correct results for the question';
 $string['interactionspattern'] = 'Pattern of correct response';
-$string['interactionslatency'] = 'Time elapsed between the time the interaction <br />was made available to the learner for response <br />and the time of the first response';
-$string['interactionsresponse'] = 'Student\'s Response';
-$string['interactionsresult'] = 'Result based on student\'s response and <br />correct result';
+$string['interactionslatency'] = 'The time elapsed between the time the interaction was made available to the learner for a response and the time of the first response.';
+$string['interactionsresponse'] = 'Student\'s response';
+$string['interactionsresult'] = 'Result based on student\'s response and correct result';
 $string['interactionsscoremin'] = 'Minimum value in the range for the raw score';
 $string['interactionsscoremax'] = 'Maximum value in the range for the raw score';
-$string['interactionsscoreraw'] = 'Number that reflects the performance of the learner<br /> relative to the range bounded by the values of min and max';
-$string['interactionssuspenddata'] = 'Provides space to store and retrieve data <br />between learner sessions';
-$string['interactionstime'] = 'Time at which the attempt was intiated';
+$string['interactionsscoreraw'] = 'Number that reflects the performance of the learner relative to the range bounded by the values of min and max';
+$string['interactionssuspenddata'] = 'Provides space to store and retrieve data between learner sessions';
+$string['interactionstime'] = 'Time at which the attempt was started';
 $string['interactionstype'] = 'Type of question';
 $string['interactionsweight'] = 'Weight assigned to the element';
-$string['interactionslearnerresponse'] = 'Learner\'s Response';
-$string['invalidactivity'] = 'Scorm activity is incorrect';
+$string['interactionslearnerresponse'] = 'Learner\'s response';
+$string['invalidactivity'] = 'SCORM activity is incorrect';
 $string['invalidurl'] = 'Invalid URL specified';
-$string['invalidhacpsession'] = 'Invalid HACP Session';
+$string['invalidhacpsession'] = 'Invalid HACP session';
 $string['invalidmanifestresource'] = 'WARNING: The following resources were referenced in your manifest but couldn\'t be found:';
 $string['last'] = 'Last accessed on';
 $string['lastaccess'] = 'Last access';
 $string['lastattempt'] = 'Last completed attempt';
 $string['lastattemptlock'] = 'Lock after final attempt';
 $string['lastattemptlock_help'] = 'If enabled, a student is prevented from launching the SCORM player after using up all their allocated attempts.';
-$string['lastattemptlockdesc'] = 'This preference sets the default value for the lock after final attempt setting';
+$string['lastattemptlockdesc'] = 'If enabled, a student is prevented from launching the SCORM player after using up all their allocated attempts.';
 $string['location'] = 'Show the location bar';
 $string['max'] = 'Max score';
 $string['maximumattempts'] = 'Number of attempts';
@@ -192,9 +192,9 @@ $string['maximumattempts_help'] = 'This setting enables the number of attempts t
 $string['maximumattemptsdesc'] = 'This preference sets the default maximum attempts for an activity';
 $string['maximumgradedesc'] = 'This preference sets the default maximum grade for an activity';
 $string['menubar'] = 'Show the menu bar';
-$string['min'] = 'Min score';
+$string['min'] = 'Minimum score';
 $string['missing_attribute'] = 'Missing attribute {$a->attr} in tag {$a->tag}';
-$string['missingparam'] = 'A required is missing or wrong';
+$string['missingparam'] = 'A required parameter is missing or wrong';
 $string['missing_tag'] = 'Missing tag {$a->tag}';
 $string['mode'] = 'Mode';
 $string['modulename'] = 'SCORM package';
@@ -217,7 +217,7 @@ $string['no_attributes'] = 'Tag {$a->tag} must have attributes';
 $string['no_children'] = 'Tag {$a->tag} must have children';
 $string['nolimit'] = 'Unlimited attempts';
 $string['nomanifest'] = 'Manifest not found';
-$string['noprerequisites'] = 'Sorry but you haven\'t reached enough prerequisites to access this learning object';
+$string['noprerequisites'] = 'Sorry but you don\'t have the required prerequisites to access this activity.';
 $string['noreports'] = 'No report to display';
 $string['normal'] = 'Normal';
 $string['noscriptnoscorm'] = 'Your browser does not support JavaScript or it has JavaScript support disabled. This SCORM package may not play or save data correctly.';
@@ -230,9 +230,9 @@ $string['optattemptsonly'] = 'users with attempts only';
 $string['optnoattemptsonly'] = 'users with no attempts only';
 $string['options'] = 'Options (Prevented by some browsers)';
 $string['optionsadv'] = 'Options (Advanced)';
-$string['optionsadv_desc'] = 'If checked the window options will be set as advanced options in the form';
-$string['organization'] = 'Organization';
-$string['organizations'] = 'Organizations';
+$string['optionsadv_desc'] = 'If checked the width and height will be listed as advanced settings.';
+$string['organization'] = 'Organisation';
+$string['organizations'] = 'Organisations';
 $string['othersettings'] = 'Additional settings';
 $string['othertracks'] = 'Other tracks';
 $string['page-mod-scorm-x'] = 'Any SCORM module page';
@@ -245,12 +245,12 @@ $string['packageurl'] = 'URL';
 $string['packageurl_help'] = 'This setting enables a URL for the SCORM package to be specified, rather than choosing a file via the file picker.';
 $string['passed'] = 'Passed';
 $string['php5'] = 'PHP 5 (DOMXML native library)';
-$string['pluginadministration'] = 'SCORM/AICC administration';
+$string['pluginadministration'] = 'SCORM package administration';
 $string['pluginname'] = 'SCORM package';
 $string['popup'] = 'New window';
 $string['popupmenu'] = 'In a drop down menu';
 $string['popupopen'] = 'Open package in a new window';
-$string['popupsblocked'] = 'It appears that popup windows are blocked, stopping this scorm module from playing. Please check your browser settings, before starting again.';
+$string['popupsblocked'] = 'It appears that popup windows are blocked, stopping this SCORM package from playing. Please check your browser settings before trying again.';
 $string['position_error'] = 'The {$a->tag} tag can\'t be child of {$a->parent} tag';
 $string['preferencesuser'] = 'Preferences for this report';
 $string['preferencespage'] = 'Preferences just for this page';
@@ -335,14 +335,13 @@ $string['versionwarning'] = 'The manifest version is older than 1.3, warning at
 $string['viewallreports'] = 'View reports for {$a} attempts';
 $string['viewalluserreports'] = 'View reports for {$a} users';
 $string['whatgrade'] = 'Attempts grading';
-$string['whatgrade_help'] = 'If multiple attempts are allowed, this setting specifies whether the highest, average (mean), first or last completed attempt is recorded in the gradebook.
-The last completed attempt option does not include attempts with a \'failed\' status.
+$string['whatgrade_help'] = 'If multiple attempts are allowed, this setting specifies whether the highest, average (mean), first or last completed attempt is recorded in the gradebook. The last completed attempt option does not include attempts with a \'failed\' status.
 
-Handling of Multiple Attempts
+Notes on handling of multiple attempts:
 
 * The option to start a new attempt is provided by a checkbox above the Enter button on the content structure page, so be sure you\'re providing access to that page if you want to allow more than one attempt.
-* Some scorm packages are intelligent about new attempts, many are not. What this means is that if the learner re-enters an existing attempt, if the SCORM content does not have internal logic to avoid overwriting previous attempts they can be overwritten, even though the attempt was \'completed\' or \'passed\'.
+* Some SCORM packages are intelligent about new attempts, many are not. What this means is that if the learner re-enters an existing attempt, if the SCORM content does not have internal logic to avoid overwriting previous attempts they can be overwritten, even though the attempt was \'completed\' or \'passed\'.
 * The settings "Force completed", "Force new attempt" and "Lock after final attempt" also provide further management of multiple attempts.';
-$string['whatgradedesc'] = 'This preference sets the default attempts grading';
+$string['whatgradedesc'] = 'Whether the highest, average (mean), first or last completed attempt is recorded in the gradebook if multiple attempts are allowed.';
 $string['width'] = 'Width';
 $string['window'] = 'Window';
index f3adbf0..e3ffb34 100644 (file)
@@ -499,24 +499,25 @@ class mod_scorm_mod_form extends moodleform_mod {
             return false;
         }
 
-        // Turn off completion settings if the checkboxes aren't ticked
-        $autocompletion = isset($data->completion) && $data->completion == COMPLETION_TRACKING_AUTOMATIC;
+        if (!empty($data->completionunlocked)) {
+            // Turn off completion settings if the checkboxes aren't ticked
+            $autocompletion = isset($data->completion) && $data->completion == COMPLETION_TRACKING_AUTOMATIC;
+
+            if (isset($data->completionstatusrequired) &&
+                    is_array($data->completionstatusrequired) && $autocompletion) {
+                $total = 0;
+                foreach (array_keys($data->completionstatusrequired) as $state) {
+                    $total |= $state;
+                }
 
-        if (isset($data->completionstatusrequired) && is_array($data->completionstatusrequired)) {
-            $total = 0;
-            foreach (array_keys($data->completionstatusrequired) as $state) {
-                $total |= $state;
+                $data->completionstatusrequired = $total;
+            } else {
+                $data->completionstatusrequired = null;
             }
 
-            $data->completionstatusrequired = $total;
-        }
-
-        if (!$autocompletion) {
-            $data->completionstatusrequired = null;
-        }
-
-        if (!empty($data->completionscoredisabled) || !$autocompletion) {
-            $data->completionscorerequired = null;
+            if (!empty($data->completionscoredisabled) || !$autocompletion) {
+                $data->completionscorerequired = null;
+            }
         }
 
         return $data;
index cbc68d3..6286973 100644 (file)
@@ -23,5 +23,5 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$string['pluginname'] = 'Basic Report';
+$string['pluginname'] = 'Graph report';
 
index be78f52..eb3d7ff 100644 (file)
@@ -25,7 +25,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$string['pluginname'] = 'Interactions Report';
+$string['pluginname'] = 'Interactions report';
 $string['questionx'] = 'Question {$a}';
 $string['responsex'] = 'Response {$a}';
 $string['rightanswerx'] = 'Right answer {$a}';
index 2660296..a876f44 100644 (file)
@@ -37,7 +37,6 @@ $string['displayselect_help'] = 'This setting, together with the URL file type a
 
 * Automatic - The best display option for the URL is selected automatically
 * Embed - The URL is displayed within the page below the navigation bar together with the URL description and any blocks
-* Force download - The user is prompted to download the URL file
 * Open - Only the URL is displayed in the browser window
 * In pop-up - The URL is displayed in a new browser window without menus or an address bar
 * In frame - The URL is displayed within a frame below the the navigation bar and URL description
index eeee5ad..088f6a5 100644 (file)
@@ -131,9 +131,10 @@ class mod_workshop_renderer extends plugin_renderer_base {
 
         $o .= $this->output->container_end(); // end of header
 
-        $content = format_text($submission->content, $submission->contentformat, array('overflowdiv'=>true));
-        $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $this->page->context->id,
+        $content = file_rewrite_pluginfile_urls($submission->content, 'pluginfile.php', $this->page->context->id,
                                                         'mod_workshop', 'submission_content', $submission->id);
+        $content = format_text($content, $submission->contentformat, array('overflowdiv'=>true));
+
         $o .= $this->output->container($content, 'content');
 
         $o .= $this->helper_submission_attachments($submission->id, 'html');
@@ -222,9 +223,9 @@ class mod_workshop_renderer extends plugin_renderer_base {
         $o .= $this->output->heading(format_string($example->title), 3, 'title');
         $o .= $this->output->container_end(); // end of header
 
-        $content = format_text($example->content, $example->contentformat, array('overflowdiv'=>true));
-        $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $this->page->context->id,
+        $content = file_rewrite_pluginfile_urls($example->content, 'pluginfile.php', $this->page->context->id,
                                                         'mod_workshop', 'submission_content', $example->id);
+        $content = format_text($content, $example->contentformat, array('overflowdiv'=>true));
         $o .= $this->output->container($content, 'content');
 
         $o .= $this->helper_submission_attachments($example->id, 'html');
index e85bc68..4fdae48 100644 (file)
@@ -70,10 +70,19 @@ class qbehaviour_adaptive extends question_behaviour_with_save {
     }
 
     public function adjust_display_options(question_display_options $options) {
+        // Save some bits so we can put them back later.
+        $save = clone($options);
+
+        // Do the default thing.
         parent::adjust_display_options($options);
+
+        // Then, if they have just Checked an answer, show them the applicable bits of feedback.
         if (!$this->qa->get_state()->is_finished() &&
                 $this->qa->get_last_behaviour_var('_try')) {
-            $options->feedback = true;
+            $options->feedback        = $save->feedback;
+            $options->correctness     = $save->correctness;
+            $options->numpartscorrect = $save->numpartscorrect;
+
         }
     }
 
index 29277ee..5bbedc0 100644 (file)
@@ -368,14 +368,15 @@ abstract class question_bank {
 
         // The the positive grades in descending order.
         foreach ($rawfractions as $fraction) {
-            $percentage = (100 * $fraction) . '%';
+            $percentage = format_float(100 * $fraction, 5, true, true) . '%';
             self::$fractionoptions["$fraction"] = $percentage;
             self::$fractionoptionsfull["$fraction"] = $percentage;
         }
 
         // The the negative grades in descending order.
         foreach (array_reverse($rawfractions) as $fraction) {
-            self::$fractionoptionsfull['' . (-$fraction)] = (-100 * $fraction) . '%';
+            self::$fractionoptionsfull['' . (-$fraction)] =
+                    format_float(-100 * $fraction, 5, true, true) . '%';
         }
 
         self::$fractionoptionsfull['-1.0'] = '-100%';
index a7af282..8b3fbdd 100644 (file)
@@ -74,6 +74,7 @@ class qtype_calculated_edit_form extends qtype_numerical_edit_form {
 
         // 1 is the answer. 3 is tolerance.
         $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated') . '=');
+        $repeated[1]->setSize(55);
         $repeated[3]->setLabel(get_string('tolerance', 'qtype_calculated') . '=');
         $repeatedoptions['tolerance']['default'] = 0.01;
 
index b58c47a..c303364 100644 (file)
@@ -185,6 +185,9 @@ class restore_qtype_match_plugin extends restore_qtype_plugin {
                   WHERE bi.backupid = ?
                     AND bi.itemname = 'question_created'", array($this->get_restoreid()));
         foreach ($rs as $rec) {
+            if (!$rec->subquestions) {
+                continue;
+            }
             $subquestionsarr = explode(',', $rec->subquestions);
             foreach ($subquestionsarr as $key => $subquestion) {
                 $subquestionsarr[$key] = $this->get_mappingid(
index f2d0a06..1fb2d27 100644 (file)
 /**
  * This file defines the class {@link question_definition} and its subclasses.
  *
+ * The type hierarchy is quite complex. Here is a summary:
+ * - question_definition
+ *   - question_information_item
+ *   - question_with_responses implements question_manually_gradable
+ *     - question_graded_automatically implements question_automatically_gradable
+ *       - question_graded_automatically_with_countback implements question_automatically_gradable_with_countback
+ *       - question_graded_by_strategy
+ *
+ * Other classes:
+ * - question_classified_response
+ * - question_answer
+ * - question_hint
+ *   - question_hint_with_parts
+ * - question_first_matching_answer_grading_strategy implements question_grading_strategy
+ *
+ * Other interfaces:
+ * - question_response_answer_comparer
+ *
  * @package    moodlecore
  * @subpackage questiontypes
  * @copyright  2009 The Open University
index 2ef560c..27defbe 100644 (file)
 $string['apikey'] = 'API key';
 $string['boxnet:view'] = 'View box.net repository';
 $string['configplugin'] = 'Box.net configuration';
-$string['callbackurl'] = 'Callback URL';
-$string['callbackurltext'] = '<ol>
-<li>Visit <a href="http://www.box.net/developers/services">box.net developers site</a> again.</li>
-<li>Make sure you set the callback URL of this box.net service to <strong>{$a}</strong></li></ol>';
-$string['callbackwarning'] = '<ol>
-<li>Get a <a href="http://www.box.net/developers/services">box.net API</a> from box.net for this Moodle site.</li>
-<li>Enter box.net api key here, then click Save and then come back to this page.  You will see that Moodle has generated a callback URL for you.</li>
-<li>Edit your box.net details on box.net website again and set the callback URL.</li></ol>';
+$string['callbackurl'] = 'Redirect URL';
+$string['callbackurltext'] = '1. Visit <a href="http://www.box.net/developers/services">www.box.net/developers/services</a> again.
+2. Make sure you set the redirect URL of this box.net service to {$a}.';
+$string['callbackwarning'] = '1. Get a Box.net API from <a href="http://www.box.net/developers/services">www.box.net/developers/services</a> for this Moodle site.
+2. Enter the Box.net API key here, then click Save and then return to this page. You will see that Moodle has generated a redirect URL for you.
+3. Edit your Box.net details on the box.net website again and set the redirect URL.';
 
 $string['information'] = 'Get an API key from the <a href="http://www.box.net/developers/services">Box.net developer page</a> for your Moodle site.';
 $string['invalidpassword'] = 'Invalid password';
index 0439f52..1d89307 100644 (file)
@@ -2692,8 +2692,9 @@ final class repository_instance_form extends moodleform {
 
         $sql = "SELECT count('x')
                   FROM {repository_instances} i, {repository} r
-                 WHERE r.type=:plugin AND r.id=i.typeid AND i.name=:name";
-        if ($DB->count_records_sql($sql, array('name' => $data['name'], 'plugin' => $data['plugin'])) > 1) {
+                 WHERE r.type=:plugin AND r.id=i.typeid AND i.name=:name AND i.contextid=:contextid";
+        $params = array('name' => $data['name'], 'plugin' => $this->plugin, 'contextid' => $this->contextid);
+        if ($DB->count_records_sql($sql, $params) > 0) {
             $errors['name'] = get_string('erroruniquename', 'repository');
         }
 
index 05de76d..c599e14 100644 (file)
@@ -142,7 +142,6 @@ $title = $pagename;
 /// Display page header
 $PAGE->set_title($title);
 $PAGE->set_heading($fullname);
-echo $OUTPUT->header();
 
 if ($context->contextlevel == CONTEXT_USER) {
     if ( !$course = $DB->get_record('course', array('id'=>$usercourseid))) {
@@ -196,13 +195,13 @@ if (!empty($edit) || !empty($new)) {
         }
         if ($success) {
             $savedstr = get_string('configsaved', 'repository');
-            echo $OUTPUT->heading($savedstr);
             redirect($baseurl);
         } else {
             print_error('instancenotsaved', 'repository', $baseurl);
         }
         exit;
     } else {     // Display the form
+        echo $OUTPUT->header();
         echo $OUTPUT->heading(get_string('configplugin', 'repository_'.$plugin));
         $OUTPUT->box_start();
         $mform->display();
@@ -224,18 +223,19 @@ if (!empty($edit) || !empty($new)) {
         }
         if ($instance->delete()) {
             $deletedstr = get_string('instancedeleted', 'repository');
-            echo $OUTPUT->heading($deletedstr);
             redirect($baseurl, $deletedstr, 3);
         } else {
             print_error('instancenotdeleted', 'repository', $baseurl);
         }
         exit;
     }
+    echo $OUTPUT->header();
     $formcontinue = new single_button(new moodle_url($baseurl, array('delete' => $delete, 'sure' => 'yes')), get_string('yes'));
     $formcancel = new single_button($baseurl, get_string('no'));
     echo $OUTPUT->confirm(get_string('confirmdelete', 'repository', $instance->name), $formcontinue, $formcancel);
     $return = false;
 } else {
+    echo $OUTPUT->header();
     repository::display_instances_list($context);
     $return = false;
 }
index 0839205..e460f68 100644 (file)
@@ -69,7 +69,7 @@ $string['customcssdesc'] = 'Any CSS you enter here will be added to every page a
 <pre>a:link, a:visited, a:hover, a:active, a:focus {color:blue;}</pre>
 Please adjust colors and CSS rules to fit your needs.';
 $string['customlogourl'] = 'Custom logo';
-$string['customlogourldesc'] = 'Change the logo for this theme by entering the full or relatve URL to an image you wish to use (i.e. http://www.yoursite.tld/mylogo.png or ../path/to/your/logo.png). As a reference the default logo is 200px wide, 50px high and a transparent png will work best.';
+$string['customlogourldesc'] = 'Change the logo for this theme by entering the full or relative URL to an image you wish to use (i.e. http://www.yoursite.tld/mylogo.png or ../path/to/your/logo.png). As a reference, the default logo is 200px wide, 50px high and a transparent png will work best.';
 $string['displayheading'] = 'Display page heading';
 $string['displaylogo'] = 'Display logo';
 $string['fontsizereference'] = 'Font size reference';
@@ -79,7 +79,7 @@ $string['footnotedesc'] = 'The content from this textarea will be displayed in t
 $string['framemargin'] = 'Frame margin';
 $string['framemargindesc'] = 'Room between the frame and the edge of the browser window. (This setting will be ignored if "{$a}" is requested).';
 $string['frontpagelogourl'] = 'Custom front page logo';
-$string['frontpagelogourldesc'] = 'Change the logo that is displayed on the front page of your site by entering the full or relatve URL to the image you wish to use (i.e. http://www.yoursite.tld/myfrontpagelogo.png or ../path/to/your/logo.png). This setting overrides the custom logo setting. As a reference the default logo is 300px wide, 80px high and a transparent png will work best.';
+$string['frontpagelogourldesc'] = 'Change the logo that is displayed on the front page of your site by entering the full or relative URL to the image you wish to use. This setting overrides the custom logo setting. As a reference the default logo is 300px wide, 80px high and a transparent png will work best.';
 $string['headerbgc'] = 'Header background colour';
 $string['headerbgcdesc'] = 'This sets the blocks header background colour for the theme.';
 $string['headercontent'] = 'Header content';
index d3c4eb2..5b7647d 100644 (file)
 .block_navigation .block_tree .tree_item a:link,
 .block_navigation .block_tree .tree_item a:visited,
 .block_navigation .block_tree .tree_item a:active {color:#000;}
-
 .block_navigation .block_tree .tree_item {padding-left:19px}
 
+/* block_adminblock */
+.block_adminblock .content .singleselect {width: 100%;}
+.block_adminblock .content .singleselect {margin:0}
+
 .block.list_block .unlist > li > .column {margin-top:3px; margin-bottom:3px;}
index 694b835..f4ca38f 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 
-$version  = 2012062506.10;              // YYYYMMDD      = weekly release date of this DEV branch
+$version  = 2012062507.01;              // YYYYMMDD      = weekly release date of this DEV branch
                                         //         RR    = release increments - 00 in DEV branches
                                         //           .XX = incremental changes
 
-$release  = '2.3.6+ (Build: 20130502)'; // Human-friendly version name
+$release  = '2.3.7 (Build: 20130513)';  // Human-friendly version name
 
 $branch   = '23';                       // this version's branch
 $maturity = MATURITY_STABLE;            // this version's maturity level
index e52474a..faa18be 100644 (file)
@@ -1633,10 +1633,17 @@ abstract class webservice_base_server extends webservice_server {
         if (!$allowed) {
             throw new webservice_access_exception(
                     'Access to the function '.$this->functionname.'() is not allowed.
-                     Please check if a service containing the function is enabled.
-                     In the service settings: if the service is restricted check that
-                     the user is listed. Still in the service settings check for
-                     IP restriction or if the service requires a capability.');
+                     There could be multiple reasons for this:
+                     1. The service linked to the user token does not contain the function.
+                     2. The service is user-restricted and the user is not listed.
+                     3. The service is IP-restricted and the user IP is not listed.
+                     4. The service is time-restricted and the time has expired.
+                     5. The token is time-restricted and the time has expired.
+                     6. The service requires a specific capability which the user does not have.
+                     7. The function is called with username/password (no user token is sent)
+                     and none of the services has the function to allow the user.
+                     These settings can be found in Administration > Site administration
+                     > Plugins > Web services > External services and Manage tokens.');
         }
 
         // we have all we need now
index 52f0e5f..f78309d 100644 (file)
@@ -332,7 +332,7 @@ class core_webservice_renderer extends plugin_renderer_base {
 
                 $validuntil = '';
                 if (!empty($token->validuntil)) {
-                    $validuntil = date("F j, Y"); //TODO MDL-31193 language support (look for moodle function)
+                    $validuntil = userdate($token->validuntil, get_string('strftimedatetime', 'langconfig'));
                 }
 
                 $tokenname = $token->name;