Merge branch 'wip-mdl-30144' of git://github.com/rajeshtaneja/moodle
authorDan Poltawski <dan@moodle.com>
Mon, 4 Feb 2013 05:54:27 +0000 (13:54 +0800)
committerDan Poltawski <dan@moodle.com>
Mon, 4 Feb 2013 05:54:27 +0000 (13:54 +0800)
29 files changed:
calendar/lib.php
course/lib.php
help.php
lib/ajax/blocks.php
lib/navigationlib.php
lib/outputrequirementslib.php
lib/yui/blocks/blocks.js
lib/yui/notification/assets/skins/sam/notification.css [deleted file]
lib/yui/notification/notification.js
mod/assign/locallib.php
mod/assign/renderer.php
mod/assign/submission/comments/lib.php
mod/assign/submission/file/lib.php
mod/assign/submission/onlinetext/lib.php
mod/assign/tests/locallib_test.php
mod/scorm/datamodels/aicc.js.php
mod/scorm/datamodels/callback.js.php
mod/scorm/datamodels/scorm_12.js.php
mod/scorm/datamodels/scorm_13.js.php
mod/workshop/assessment.php
mod/workshop/form/assessment_form.php
mod/workshop/lang/en/workshop.php
mod/workshop/locallib.php
question/type/shortanswer/question.php
theme/base/pix/sprite.png [moved from lib/yui/notification/assets/skins/sam/sprite.png with 100% similarity]
theme/base/style/core.css
theme/magazine/style/core.css
theme/mymobile/style/core.css
user/profile.php

index 654a5b9..fc8d32b 100644 (file)
@@ -798,7 +798,7 @@ function calendar_get_events_by_id($eventids) {
  * @return string $content return available control for the calender in html
  */
 function calendar_top_controls($type, $data) {
-    global $CFG;
+    global $CFG, $PAGE;
     $content = '';
     if(!isset($data['d'])) {
         $data['d'] = 1;
@@ -821,6 +821,7 @@ function calendar_top_controls($type, $data) {
 
     $data['m'] = $date['mon'];
     $data['y'] = $date['year'];
+    $urlbase = $PAGE->url;
 
     //Accessibility: calendar block controls, replaced <table> with <div>.
     //$nexttext = link_arrow_right(get_string('monthnext', 'access'), $url='', $accesshide=true);
@@ -830,8 +831,8 @@ function calendar_top_controls($type, $data) {
         case 'frontpage':
             list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
             list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
-            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'index.php?', 0, $nextmonth, $nextyear, $accesshide=true);
-            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'index.php?', 0, $prevmonth, $prevyear, true);
+            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), $urlbase, 0, $nextmonth, $nextyear, true);
+            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), $urlbase, 0, $prevmonth, $prevyear, true);
 
             $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'month')), 1, $data['m'], $data['y']);
             if (!empty($data['id'])) {
@@ -857,8 +858,8 @@ function calendar_top_controls($type, $data) {
         case 'course':
             list($prevmonth, $prevyear) = calendar_sub_month($data['m'], $data['y']);
             list($nextmonth, $nextyear) = calendar_add_month($data['m'], $data['y']);
-            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), 'view.php?id='.$data['id'].'&amp;', 0, $nextmonth, $nextyear, $accesshide=true);
-            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), 'view.php?id='.$data['id'].'&amp;', 0, $prevmonth, $prevyear, true);
+            $nextlink = calendar_get_link_next(get_string('monthnext', 'access'), $urlbase, 0, $nextmonth, $nextyear, true);
+            $prevlink = calendar_get_link_previous(get_string('monthprev', 'access'), $urlbase, 0, $prevmonth, $prevyear, true);
 
             $calendarlink = calendar_get_link_href(new moodle_url(CALENDAR_URL.'view.php', array('view'=>'month')), 1, $data['m'], $data['y']);
             if (!empty($data['id'])) {
index c5e9d86..be41f42 100644 (file)
@@ -3837,16 +3837,6 @@ function include_course_ajax($course, $usedmodules = array(), $enabledmodules =
             )), null, true);
     }
 
-    // Include blocks dragdrop
-    $params = array(
-        'courseid' => $course->id,
-        'pagetype' => $PAGE->pagetype,
-        'pagelayout' => $PAGE->pagelayout,
-        'subpage' => $PAGE->subpage,
-        'regions' => $PAGE->blocks->get_regions(),
-    );
-    $PAGE->requires->yui_module('moodle-core-blocks', 'M.core_blocks.init_dragdrop', array($params), null, true);
-
     // Require various strings for the command toolbox
     $PAGE->requires->strings_for_js(array(
             'moveleft',
index 390b29e..6afdd97 100644 (file)
--- a/help.php
+++ b/help.php
@@ -67,7 +67,13 @@ if ($sm->string_exists($identifier.'_help', $component)) {
     $options->newlines = false;
     $options->overflowdiv = !$ajax;
 
-    echo $OUTPUT->heading(format_string(get_string($identifier, $component)), 1, 'helpheading');
+    if ($ajax) {
+        // When using AJAX, the header should be H2 as it is in the same DOM as the calling page.
+        echo $OUTPUT->heading(format_string(get_string($identifier, $component)), 2, 'helpheading');
+    } else {
+        // When not using AJAX, the header should be H1 as it is in it's own window.
+        echo $OUTPUT->heading(format_string(get_string($identifier, $component)), 1, 'helpheading');
+    }
     // Should be simple wiki only MDL-21695
     echo format_text(get_string($identifier.'_help', $component), FORMAT_MARKDOWN, $options);
 
index 470106d..ab24525 100644 (file)
@@ -30,6 +30,7 @@ require_once(dirname(__FILE__) . '/../../config.php');
 $courseid = required_param('courseid', PARAM_INT);
 $pagelayout = required_param('pagelayout', PARAM_ALPHAEXT);
 $pagetype = required_param('pagetype', PARAM_ALPHAEXT);
+$contextid = required_param('contextid', PARAM_INT);
 $subpage = optional_param('subpage', '', PARAM_ALPHANUMEXT);
 $cmid = optional_param('cmid', null, PARAM_INT);
 $action = optional_param('action', '', PARAM_ALPHA);
@@ -50,9 +51,33 @@ if (!is_null($cmid)) {
 require_login($courseid, false, $cm);
 require_sesskey();
 
+// Set context from ID, so we don't have to guess it from other info.
+$PAGE->set_context(context::instance_by_id($contextid));
+
 // Setting layout to replicate blocks configuration for the page we edit
 $PAGE->set_pagelayout($pagelayout);
 $PAGE->set_subpage($subpage);
+$pagetype = explode('-', $pagetype);
+switch ($pagetype[0]) {
+    case 'my':
+        // My Home page needs to have 'content' block region set up.
+        $PAGE->set_blocks_editing_capability('moodle/my:manageblocks');
+        $PAGE->blocks->add_region('content');
+        break;
+    case 'user':
+        if ($pagelayout == 'mydashboard') {
+            // User profile pages also need the 'content' block region set up.
+            $PAGE->blocks->add_region('content');
+            // If it's not the current user's profile, we need a different capability.
+            if ($PAGE->context->contextlevel == CONTEXT_USER && $PAGE->context->instanceid != $USER->id) {
+                $PAGE->set_blocks_editing_capability('moodle/user:manageblocks');
+            } else {
+                $PAGE->set_blocks_editing_capability('moodle/user:manageownblocks');
+            }
+        }
+        break;
+}
+
 echo $OUTPUT->header(); // send headers
 
 switch ($action) {
index 185d960..9319081 100644 (file)
@@ -2157,8 +2157,7 @@ class global_navigation extends navigation_node {
             $usernode->add(get_string('messages', 'message'), $url, self::TYPE_SETTING, null, 'messages');
         }
 
-        $context = context_user::instance($USER->id);
-        if ($iscurrentuser && has_capability('moodle/user:manageownfiles', $context)) {
+        if ($iscurrentuser && has_capability('moodle/user:manageownfiles', context_user::instance($USER->id))) {
             $url = new moodle_url('/user/files.php');
             $usernode->add(get_string('myfiles'), $url, self::TYPE_SETTING);
         }
index d4eff1c..8c97eac 100644 (file)
@@ -282,6 +282,22 @@ class page_requirements_manager {
         if ($page->pagelayout === 'frametop') {
             $this->js_init_call('M.util.init_frametop');
         }
+
+        // Include block drag/drop if editing is on
+        if ($page->user_is_editing()) {
+            $params = array(
+                'courseid' => $page->course->id,
+                'pagetype' => $page->pagetype,
+                'pagelayout' => $page->pagelayout,
+                'subpage' => $page->subpage,
+                'regions' => $page->blocks->get_regions(),
+                'contextid' => $page->context->id,
+            );
+            if (!empty($page->cm->id)) {
+                $params['cmid'] = $page->cm->id;
+            }
+            $page->requires->yui_module('moodle-core-blocks', 'M.core_blocks.init_dragdrop', array($params), null, true);
+        }
     }
 
     /**
index edb655f..baa06be 100644 (file)
@@ -10,7 +10,9 @@ YUI.add('moodle-core-blocks', function(Y) {
         LIGHTBOX : 'lightbox',
         REGIONCONTENT : 'region-content',
         SKIPBLOCK : 'skip-block',
-        SKIPBLOCKTO : 'skip-block-to'
+        SKIPBLOCKTO : 'skip-block-to',
+        MYINDEX : 'page-my-index',
+        REGIONMAIN : 'region-main'
     }
 
     var DRAGBLOCK = function() {
@@ -26,6 +28,15 @@ YUI.add('moodle-core-blocks', function(Y) {
             this.samenodeclass = CSS.BLOCK;
             this.parentnodeclass = CSS.REGIONCONTENT;
 
+            // Add relevant classes and ID to 'content' block region on My Home page.
+            var myhomecontent = Y.Node.all('body#'+CSS.MYINDEX+' #'+CSS.REGIONMAIN+' > .'+CSS.REGIONCONTENT);
+            if (myhomecontent.size() > 0) {
+                var contentregion = myhomecontent.item(0);
+                contentregion.addClass(CSS.BLOCKREGION);
+                contentregion.set('id', CSS.REGIONCONTENT);
+                contentregion.one('div').addClass(CSS.REGIONCONTENT);
+            }
+
             // Initialise blocks dragging
             // Find all block regions on the page
             var blockregionlist = Y.Node.all('div.'+CSS.BLOCKREGION);
@@ -42,17 +53,18 @@ YUI.add('moodle-core-blocks', function(Y) {
                 var regioncontent = Y.Node.create('<div></div>')
                     .addClass(CSS.REGIONCONTENT);
                 blockregion.appendChild(regioncontent);
+                var pre = blockregionlist.filter('#region-pre');
+                var post = blockregionlist.filter('#region-post');
 
-                var regionid = this.get_region_id(blockregionlist.item(0));
-                if (regionid === 'post') {
+                if (pre.size() === 0 && post.size() === 1) {
                     // pre block is missing, instert it before post
                     blockregion.setAttrs({id : 'region-pre'});
-                    blockregionlist.item(0).insert(blockregion, 'before');
+                    post.item(0).insert(blockregion, 'before');
                     blockregionlist.unshift(blockregion);
-                } else {
+                } else if (post.size() === 0 && pre.size() === 1) {
                     // post block is missing, instert it after pre
                     blockregion.setAttrs({id : 'region-post'});
-                    blockregionlist.item(0).insert(blockregion, 'after');
+                    pre.item(0).insert(blockregion, 'after');
                     blockregionlist.push(blockregion);
                 }
             }
@@ -214,6 +226,7 @@ YUI.add('moodle-core-blocks', function(Y) {
                 pagelayout : this.get('pagelayout'),
                 pagetype : this.get('pagetype'),
                 subpage : this.get('subpage'),
+                contextid : this.get('contextid'),
                 action : 'move',
                 bui_moveid : this.get_block_id(dragnode),
                 bui_newregion : this.get_block_region(dropnode)
@@ -263,6 +276,9 @@ YUI.add('moodle-core-blocks', function(Y) {
             cmid : {
                 value : null
             },
+            contextid : {
+                value : null
+            },
             pagelayout : {
                 value : null
             },
diff --git a/lib/yui/notification/assets/skins/sam/notification.css b/lib/yui/notification/assets/skins/sam/notification.css
deleted file mode 100644 (file)
index 91fd8d2..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-.moodle-dialogue-base .hidden,
-.moodle-dialogue-base .moodle-dialogue-hidden {display:none;}
-.moodle-dialogue-base .moodle-dialogue-lightbox {background-color:#AAA;}
-.moodle-dialogue-base .moodle-dialogue {background-color:#666;border:0 solid #666;border-right-width:3px;border-bottom-width:3px;}
-.moodle-dialogue-base .moodle-dialogue-wrap {background-color:#FFF;margin-top:-3px;margin-left:-3px;border:1px solid #555;height:auto;}
-.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd {font-size:110%;color:inherit;font-weight:bold;text-align:left;padding:5px 6px;margin:0;border-bottom:1px solid #ccc;background:#f6f6f6;}
-.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd h1{font-size:100%;font-weight:bold;margin:0;padding:0;display:inline;}
-.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons {padding: 5px;}
-.moodle-dialogue-base .closebutton {background-image:url(sprite.png);width:25px;height:15px;background-repeat:no-repeat;float:right;vertical-align:middle;display:inline-block;cursor:pointer;padding:0px;border-style:none;}
-.moodle-dialogue-base .moodle-dialogue-bd {padding:5px; overflow: auto;}
-.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-content {background:#FFF;padding:0px;}
-.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-content .moodle-dialogue-ft {padding:0px;}
-
-.moodle-dialogue-confirm .confirmation-dialogue {text-align:center;}
-.moodle-dialogue-confirm .confirmation-message {margin:0.5em 1em;}
-.moodle-dialogue-confirm .confirmation-dialogue input {min-width:80px;text-align:center;}
-
-.moodle-dialogue-exception .moodle-exception-message {text-align:center;margin:1em;}
-.moodle-dialogue-exception .moodle-exception-param {margin-bottom:0.5em;}
-.moodle-dialogue-exception .moodle-exception-param label {width:150px;font-weight:bold;}
-.moodle-dialogue-exception .param-stacktrace label {display:block;background-color:#EEE;margin:0;padding:4px 1em;border:1px solid #ccc;border-bottom-width:0;}
-.moodle-dialogue-exception .param-stacktrace pre {display:block;border:1px solid #ccc;background-color:#fff;height:200px;overflow:auto;}
-.moodle-dialogue-exception .param-stacktrace .stacktrace-file {color:navy;display:inline-block;font-size:80%;margin:4px 0;}
-.moodle-dialogue-exception .param-stacktrace .stacktrace-line {color:#AA0000;display:inline-block;font-size:80%;width:50px;margin:4px 1em;}
-.moodle-dialogue-exception .param-stacktrace .stacktrace-call {color:#333;font-size:90%;padding-left:25px;margin-bottom:4px;padding-bottom:4px;border-bottom:1px solid #eee;}
index 8969f6a..83d4f4e 100644 (file)
@@ -401,4 +401,4 @@ M.core.confirm = CONFIRM;
 M.core.exception = EXCEPTION;
 M.core.ajaxException = AJAXEXCEPTION;
 
-}, '@VERSION@', {requires:['base','node','panel','event-key', 'moodle-core-notification-skin', 'dd-plugin']});
+}, '@VERSION@', {requires:['base','node','panel','event-key', 'dd-plugin']});
index b418500..e28ba43 100644 (file)
@@ -1806,7 +1806,8 @@ class assign {
                 }
             }
             $grading_info = grade_get_grades($course->id, 'mod', 'assign', $cm->instance, $USER->id);
-            if (isset($grading_info->items[0]) && !$grading_info->items[0]->grades[$USER->id]->hidden ) {
+            if (isset($grading_info->items[0]->grades[$USER->id]) &&
+                    !$grading_info->items[0]->grades[$USER->id]->hidden ) {
                 $grade = $grading_info->items[0]->grades[$USER->id]->str_grade;
             } else {
                 $grade = '-';
@@ -2784,6 +2785,30 @@ class assign {
         return false;
     }
 
+    /**
+     * Perform an access check to see if the current $USER can view this group submission.
+     *
+     * @param int $groupid
+     * @return bool
+     */
+    public function can_view_group_submission($groupid) {
+        global $USER;
+
+        if (!is_enrolled($this->get_course_context(), $USER->id)) {
+            return false;
+        }
+        if (has_capability('mod/assign:grade', $this->context)) {
+            return true;
+        }
+        $members = $this->get_submission_group_members($groupid, true);
+        foreach ($members as $member) {
+            if ($member->id == $USER->id) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Perform an access check to see if the current $USER can view this users submission.
      *
@@ -3040,8 +3065,12 @@ class assign {
                                         $instance->id,
                                         $user->id);
 
-            $gradingitem = $gradinginfo->items[0];
-            $gradebookgrade = $gradingitem->grades[$user->id];
+            $gradingitem = null;
+            $gradebookgrade = null;
+            if (isset($gradinginfo->items[0])) {
+                $gradingitem = $gradinginfo->items[0];
+                $gradebookgrade = $gradingitem->grades[$user->id];
+            }
 
             // Check to see if all feedback plugins are empty.
             $emptyplugins = true;
@@ -3055,25 +3084,34 @@ class assign {
                 }
             }
 
-            if (!($gradebookgrade->hidden) && ($gradebookgrade->grade !== null || !$emptyplugins)) {
+            $cangrade = has_capability('mod/assign:grade', $this->get_context());
+            // If there is feedback or a visible grade, show the summary.
+            if ((!empty($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) ||
+                    !$emptyplugins) {
 
-                $gradefordisplay = '';
+                $gradefordisplay = null;
+                $gradeddate = null;
+                $grader = null;
                 $gradingmanager = get_grading_manager($this->get_context(), 'mod_assign', 'submissions');
 
-                if ($controller = $gradingmanager->get_active_controller()) {
-                    $controller->set_grade_range(make_grades_menu($this->get_instance()->grade));
-                    $cangrade = has_capability('mod/assign:grade', $this->get_context());
-                    $gradefordisplay = $controller->render_grade($PAGE,
-                                                                 $grade->id,
-                                                                 $gradingitem,
-                                                                 $gradebookgrade->str_long_grade,
-                                                                 $cangrade);
-                } else {
-                    $gradefordisplay = $this->display_grade($gradebookgrade->grade, false);
+                // Only show the grade if it is not hidden in gradebook.
+                if (!empty($gradebookgrade->grade) && ($cangrade || !$gradebookgrade->hidden)) {
+                    if ($controller = $gradingmanager->get_active_controller()) {
+                        $controller->set_grade_range(make_grades_menu($this->get_instance()->grade));
+                        $gradefordisplay = $controller->render_grade($PAGE,
+                                                                     $grade->id,
+                                                                     $gradingitem,
+                                                                     $gradebookgrade->str_long_grade,
+                                                                     $cangrade);
+                    } else {
+                        $gradefordisplay = $this->display_grade($gradebookgrade->grade, false);
+                    }
+                    $gradeddate = $gradebookgrade->dategraded;
+                    if (isset($grade->grader)) {
+                        $grader = $DB->get_record('user', array('id'=>$grade->grader));
+                    }
                 }
 
-                $gradeddate = $gradebookgrade->dategraded;
-                $grader = $DB->get_record('user', array('id'=>$grade->grader));
 
                 $feedbackstatus = new assign_feedback_status($gradefordisplay,
                                                       $gradeddate,
@@ -3877,6 +3915,9 @@ class assign {
             $record->userid = $userid;
             if ($modified >= 0) {
                 $record->grade = unformat_float(optional_param('quickgrade_' . $record->userid, -1, PARAM_TEXT));
+            } else {
+                // This user was not in the grading table.
+                continue;
             }
             $record->lastmodified = $modified;
             $record->gradinginfo = grade_get_grades($this->get_course()->id,
@@ -4401,10 +4442,18 @@ class assign {
         if (has_all_capabilities($capabilitylist, $this->get_course_context())) {
             $urlparams = array('id'=>$this->get_course()->id);
             $url = new moodle_url('/grade/report/grader/index.php', $urlparams);
-            $usergrade = $gradinginfo->items[0]->grades[$userid]->str_grade;
+            $usergrade = '-';
+            if (isset($gradinginfo->items[0]->grades[$userid]->str_grade)) {
+                $usergrade = $gradinginfo->items[0]->grades[$userid]->str_grade;
+            }
             $gradestring = $this->get_renderer()->action_link($url, $usergrade);
         } else {
-            $gradestring = $gradinginfo->items[0]->grades[$userid]->str_grade;
+            $usergrade = '-';
+            if (isset($gradinginfo->items[0]->grades[$userid]) &&
+                    !$grading_info->items[0]->grades[$userid]->hidden) {
+                $usergrade = $gradinginfo->items[0]->grades[$userid]->str_grade;
+            }
+            $gradestring = $usergrade;
         }
         $name = get_string('currentgrade', 'assign') . ':' . $gradestring;
         $mform->addElement('static', 'finalgrade', $name);
index cbf7a56..181e353 100644 (file)
@@ -321,18 +321,20 @@ class mod_assign_renderer extends plugin_renderer_base {
         $t = new html_table();
 
         // Grade.
-        $row = new html_table_row();
-        $cell1 = new html_table_cell(get_string('grade'));
-        $cell2 = new html_table_cell($status->gradefordisplay);
-        $row->cells = array($cell1, $cell2);
-        $t->data[] = $row;
+        if (isset($status->gradefordisplay)) {
+            $row = new html_table_row();
+            $cell1 = new html_table_cell(get_string('grade'));
+            $cell2 = new html_table_cell($status->gradefordisplay);
+            $row->cells = array($cell1, $cell2);
+            $t->data[] = $row;
 
-        // Grade date.
-        $row = new html_table_row();
-        $cell1 = new html_table_cell(get_string('gradedon', 'assign'));
-        $cell2 = new html_table_cell(userdate($status->gradeddate));
-        $row->cells = array($cell1, $cell2);
-        $t->data[] = $row;
+            // Grade date.
+            $row = new html_table_row();
+            $cell1 = new html_table_cell(get_string('gradedon', 'assign'));
+            $cell2 = new html_table_cell(userdate($status->gradeddate));
+            $row->cells = array($cell1, $cell2);
+            $t->data[] = $row;
+        }
 
         if ($status->grader) {
             // Grader.
index 5844463..5509350 100644 (file)
@@ -92,21 +92,15 @@ function assignsubmission_comments_comment_permissions(stdClass $options) {
     if ($assignment->get_instance()->id != $submission->assignment) {
         throw new comment_exception('invalidcontext');
     }
-    if (!has_capability('mod/assign:grade', $context)) {
-        if (!has_capability('mod/assign:submit', $context)) {
-            return array('post' => false, 'view' => false);
-        } else if ($assignment->get_instance()->teamsubmission) {
-            $group = $assignment->get_submission_group($USER->id);
-            $groupid = 0;
-            if ($group) {
-                $groupid = $group->id;
-            }
-            if ($groupid != $submission->groupid) {
-                return array('post' => false, 'view' => false);
-            }
-        } else if ($submission->userid != $USER->id) {
-            return array('post' => false, 'view' => false);
-        }
+
+    if ($assignment->get_instance()->teamsubmission &&
+        !$assignment->can_view_group_submission($submission->groupid)) {
+        return array('post' => false, 'view' => false);
+    }
+
+    if (!$assignment->get_instance()->teamsubmission &&
+        !$assignment->can_view_submission($submission->userid)) {
+        return array('post' => false, 'view' => false);
     }
 
     return array('post' => true, 'view' => true);
index 8b58fe2..c8fcbae 100644 (file)
@@ -40,7 +40,7 @@ function assignsubmission_file_pluginfile($course,
                                           $filearea,
                                           $args,
                                           $forcedownload) {
-    global $USER, $DB;
+    global $DB, $CFG;
 
     if ($context->contextlevel != CONTEXT_MODULE) {
         return false;
@@ -50,20 +50,26 @@ function assignsubmission_file_pluginfile($course,
     $itemid = (int)array_shift($args);
     $record = $DB->get_record('assign_submission',
                               array('id'=>$itemid),
-                              'userid, assignment',
+                              'userid, assignment, groupid',
                               MUST_EXIST);
     $userid = $record->userid;
+    $groupid = $record->groupid;
 
-    if (!$assign = $DB->get_record('assign', array('id'=>$cm->instance))) {
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+    $assign = new assign($context, $cm, $course);
+
+    if ($assign->get_instance()->id != $record->assignment) {
         return false;
     }
 
-    if ($assign->id != $record->assignment) {
+    if ($assign->get_instance()->teamsubmission &&
+        !$assign->can_view_group_submission($groupid)) {
         return false;
     }
 
-    // Check if this is the current users submission or the user has grading permission.
-    if ($USER->id != $userid and !has_capability('mod/assign:grade', $context)) {
+    if (!$assign->get_instance()->teamsubmission &&
+        !$assign->can_view_submission($userid)) {
         return false;
     }
 
@@ -72,7 +78,7 @@ function assignsubmission_file_pluginfile($course,
     $fullpath = "/{$context->id}/assignsubmission_file/$filearea/$itemid/$relativepath";
 
     $fs = get_file_storage();
-    if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) || $file->is_directory()) {
         return false;
     }
 
index 19e8e73..a2bcde9 100644 (file)
@@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool false if file not found, does not return if found - just send the file
  */
 function assignsubmission_onlinetext_pluginfile($course, $cm, context $context, $filearea, $args, $forcedownload) {
-    global $USER, $DB;
+    global $DB, $CFG;
 
     if ($context->contextlevel != CONTEXT_MODULE) {
         return false;
@@ -43,19 +43,28 @@ function assignsubmission_onlinetext_pluginfile($course, $cm, context $context,
 
     require_login($course, false, $cm);
     $itemid = (int)array_shift($args);
-    $record = $DB->get_record('assign_submission', array('id'=>$itemid), 'userid, assignment', MUST_EXIST);
+    $record = $DB->get_record('assign_submission',
+                              array('id'=>$itemid),
+                              'userid, assignment, groupid',
+                              MUST_EXIST);
     $userid = $record->userid;
+    $groupid = $record->groupid;
 
-    if (!$assign = $DB->get_record('assign', array('id'=>$cm->instance))) {
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+    $assign = new assign($context, $cm, $course);
+
+    if ($assign->get_instance()->id != $record->assignment) {
         return false;
     }
 
-    if ($assign->id != $record->assignment) {
+    if ($assign->get_instance()->teamsubmission &&
+        !$assign->can_view_group_submission($groupid)) {
         return false;
     }
 
-    // Check is users submission or has grading permission.
-    if ($USER->id != $userid and !has_capability('mod/assign:grade', $context)) {
+    if (!$assign->get_instance()->teamsubmission &&
+        !$assign->can_view_submission($userid)) {
         return false;
     }
 
@@ -64,7 +73,7 @@ function assignsubmission_onlinetext_pluginfile($course, $cm, context $context,
     $fullpath = "/{$context->id}/assignsubmission_onlinetext/$filearea/$itemid/$relativepath";
 
     $fs = get_file_storage();
-    if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) || $file->is_directory()) {
         return false;
     }
 
index a9b8ab2..6f533b8 100644 (file)
@@ -658,6 +658,63 @@ class mod_assign_locallib_testcase extends advanced_testcase {
         }
     }
 
+    public function test_show_student_summary() {
+        global $CFG;
+
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        // No feedback should be available because this student has not been graded.
+        $this->setUser($this->students[0]);
+        $output = $assign->view_student_summary($this->students[0], true);
+        $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if there is no grade');
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        // Now we should see the feedback
+        $this->setUser($this->students[0]);
+        $output = $assign->view_student_summary($this->students[0], true);
+        $this->assertNotEquals(false, strpos($output, 'Feedback'), 'Show feedback if there is a grade');
+
+        // Now hide the grade in gradebook.
+        $this->setUser($this->teachers[0]);
+        require_once($CFG->libdir.'/gradelib.php');
+        $gradeitem = new grade_item(array(
+            'itemtype'      => 'mod',
+            'itemmodule'    => 'assign',
+            'iteminstance'  => $assign->get_instance()->id,
+            'courseid'      => $this->course->id));
+
+        $gradeitem->set_hidden(1, false);
+
+        // No feedback should be available because the grade is hidden.
+        $this->setUser($this->students[0]);
+        $output = $assign->view_student_summary($this->students[0], true);
+        $this->assertEquals(false, strpos($output, 'Feedback'), 'Do not show feedback if the grade is hidden in the gradebook');
+
+        // Do the same but add feedback
+        $assign = $this->create_instance(array('assignfeedback_comments_enabled' => 1));
+
+        $this->setUser($this->teachers[0]);
+        $grade = $assign->get_user_grade($this->students[0]->id, true);
+        $data = new stdClass();
+        $data->assignfeedbackcomments_editor = array('text'=>'Tomato sauce',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_feedback_plugin_by_type('comments');
+        $plugin->save($grade, $data);
+
+        // Should have feedback but no grade
+        $this->setUser($this->students[0]);
+        $output = $assign->view_student_summary($this->students[0], true);
+        $this->assertNotEquals(false, strpos($output, 'Tomato sauce'), 'Show feedback even if there is no grade');
+        $this->assertEquals(false, strpos($output, 'Grade'), 'Do not show grade when there is no grade.');
+        $this->assertEquals(false, strpos($output, 'Graded on'), 'Do not show graded date when there is no grade.');
+    }
+
+
 }
 
 /**
index a5dd434..8a76338 100644 (file)
@@ -246,7 +246,7 @@ require_once($CFG->dirroot.'/mod/scorm/datamodels/callback.js.php');
                 // trigger TOC update
                 var sURL = "<?php echo $CFG->wwwroot; ?>" + "/mod/scorm/prereqs.php?a=<?php echo $scorm->id ?>&scoid=<?php echo $scoid ?>&attempt=<?php echo $attempt ?>&mode=<?php echo $mode ?>&currentorg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
                 var callback = this.connectPrereqCallback;
-                YUI.use('yui2-connection', function(Y) {
+                YUI().use('yui2-connection', function(Y) {
                     Y.YUI2.util.Connect.asyncRequest('GET', sURL, callback, null);
                 });
                 return "true";
index a51fc44..520f22b 100644 (file)
@@ -18,7 +18,7 @@
    this.connectPrereqCallback = {
 
         success: function(o) {
-            YUI.use('yui2-treeview', 'yui2-layout', function(Y) {
+            YUI().use('yui2-treeview', 'yui2-layout', function(Y) {
                 scorm_tree_node = Y.YUI2.widget.TreeView.getTree('scorm_tree');
                 if (o.responseText !== undefined) {
                     //alert('got a response: ' + o.responseText);
index f8b6963..f2623b1 100644 (file)
@@ -236,7 +236,7 @@ function SCORMapi1_2() {
                 // trigger TOC update
                 var sURL = "<?php echo $CFG->wwwroot; ?>" + "/mod/scorm/prereqs.php?a=<?php echo $scorm->id ?>&scoid=<?php echo $scoid ?>&attempt=<?php echo $attempt ?>&mode=<?php echo $mode ?>&currentorg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
                 var callback = this.connectPrereqCallback;
-                YUI.use('yui2-connection', function(Y) {
+                YUI().use('yui2-connection', function(Y) {
                     Y.YUI2.util.Connect.asyncRequest('GET', sURL, callback, null);
                 });
                 return result;
index a4ad5db..0d6dd23 100644 (file)
@@ -367,7 +367,7 @@ function SCORMapi1_3() {
                     // trigger TOC update
                     var sURL = "<?php echo $CFG->wwwroot; ?>" + "/mod/scorm/prereqs.php?a=<?php echo $scorm->id ?>&scoid=<?php echo $scoid ?>&attempt=<?php echo $attempt ?>&mode=<?php echo $mode ?>&currentorg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
                     var callback = this.connectPrereqCallback;
-                    YUI.use('yui2-connection', function(Y) {
+                    YUI().use('yui2-connection', function(Y) {
                         Y.YUI2.util.Connect.asyncRequest('GET', sURL, callback, null);
                     });
                 } else {
index 851f290..64cbf3f 100644 (file)
@@ -128,9 +128,15 @@ $strategy = $workshop->grading_strategy_instance();
 if (is_null($assessment->grade) and !$assessmenteditable) {
     $mform = null;
 } else {
+    // Are there any other pending assessments to do but this one?
+    if ($assessmenteditable) {
+        $pending = $workshop->get_pending_assessments_by_reviewer($assessment->reviewerid, $assessment->id);
+    } else {
+        $pending = array();
+    }
     // load the assessment form and process the submitted data eventually
     $mform = $strategy->get_assessment_form($PAGE->url, 'assessment', $assessment, $assessmenteditable,
-                                        array('editableweight' => $cansetassessmentweight));
+                                        array('editableweight' => $cansetassessmentweight, 'pending' => !empty($pending)));
     $mform->set_data(array('weight' => $assessment->weight)); // other values are set by subplugins
     if ($mform->is_cancelled()) {
         redirect($workshop->view_url());
@@ -146,6 +152,13 @@ if (is_null($assessment->grade) and !$assessmenteditable) {
         }
         if (!is_null($rawgrade) and isset($data->saveandclose)) {
             redirect($workshop->view_url());
+        } else if (!is_null($rawgrade) and isset($data->saveandshownext)) {
+            $next = reset($pending);
+            if (!empty($next)) {
+                redirect($workshop->assess_url($next->id));
+            } else {
+                redirect($PAGE->url); // This should never happen but just in case...
+            }
         } else {
             // either it is not possible to calculate the $rawgrade
             // or the reviewer has chosen "Save and continue"
index f6e5e03..43cd3fc 100644 (file)
@@ -77,8 +77,11 @@ class workshop_assessment_form extends moodleform {
             $buttonarray[] = $mform->createElement('cancel', 'backtoeditform', get_string('backtoeditform', 'workshop'));
         }
         if ($this->mode == 'assessment') {
-            $buttonarray[] = $mform->createElement('submit', 'saveandcontinue', get_string('saveandcontinue', 'workshop'));
+            if (!empty($this->options['pending'])) {
+                $buttonarray[] = $mform->createElement('submit', 'saveandshownext', get_string('saveandshownext', 'workshop'));
+            }
             $buttonarray[] = $mform->createElement('submit', 'saveandclose', get_string('saveandclose', 'workshop'));
+            $buttonarray[] = $mform->createElement('submit', 'saveandcontinue', get_string('saveandcontinue', 'workshop'));
             $buttonarray[] = $mform->createElement('cancel');
         }
         $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
index 5e1d515..25a4fbb 100644 (file)
@@ -208,6 +208,7 @@ $string['recentsubmissions'] = 'Workshop submissions:';
 $string['saveandclose'] = 'Save and close';
 $string['saveandcontinue'] = 'Save and continue editing';
 $string['saveandpreview'] = 'Save and preview';
+$string['saveandshownext'] = 'Save and show next';
 $string['selfassessmentdisabled'] = 'Self-assessment disabled';
 $string['showingperpage'] = 'Showing {$a} items per page';
 $string['showingperpagechange'] = 'Change ...';
index a534f4c..3d77819 100644 (file)
@@ -1169,6 +1169,37 @@ class workshop {
         return $DB->get_records_sql($sql, $params);
     }
 
+    /**
+     * Get allocated assessments not graded yet by the given reviewer
+     *
+     * @see self::get_assessments_by_reviewer()
+     * @param int $reviewerid the reviewer id
+     * @param null|int|array $exclude optional assessment id (or list of them) to be excluded
+     * @return array
+     */
+    public function get_pending_assessments_by_reviewer($reviewerid, $exclude = null) {
+
+        $assessments = $this->get_assessments_by_reviewer($reviewerid);
+
+        foreach ($assessments as $id => $assessment) {
+            if (!is_null($assessment->grade)) {
+                unset($assessments[$id]);
+                continue;
+            }
+            if (!empty($exclude)) {
+                if (is_array($exclude) and in_array($id, $exclude)) {
+                    unset($assessments[$id]);
+                    continue;
+                } else if ($id == $exclude) {
+                    unset($assessments[$id]);
+                    continue;
+                }
+            }
+        }
+
+        return $assessments;
+    }
+
     /**
      * Allocate a submission to a user for review
      *
index cb3c8a4..ba1dfc7 100644 (file)
@@ -87,6 +87,11 @@ class qtype_shortanswer_question extends question_graded_by_strategy
     }
 
     public static function compare_string_with_wildcard($string, $pattern, $ignorecase) {
+
+        // Normalise any non-canonical UTF-8 characters before we start.
+        $pattern = self::safe_normalize($pattern);
+        $string = self::safe_normalize($string);
+
         // Break the string on non-escaped asterisks.
         $bits = preg_split('/(?<!\\\\)\*/', $pattern);
         // Escape regexp special characters in the bits.
@@ -102,12 +107,32 @@ class qtype_shortanswer_question extends question_graded_by_strategy
             $regexp .= 'i';
         }
 
-        if (function_exists('normalizer_normalize')) {
-            $regexp = normalizer_normalize($regexp, Normalizer::FORM_C);
-            $string = normalizer_normalize($string, Normalizer::FORM_C);
+        return preg_match($regexp, trim($string));
+    }
+
+    /**
+     * Normalise a UTf-8 string to FORM_C, avoiding the pitfalls in PHP's
+     * normalizer_normalize function.
+     * @param string $string the input string.
+     * @return string the normalised string.
+     */
+    protected static function safe_normalize($string) {
+        if (!$string) {
+            return '';
         }
 
-        return preg_match($regexp, trim($string));
+        if (!function_exists('normalizer_normalize')) {
+            return $string;
+        }
+
+        $normalised = normalizer_normalize($string, Normalizer::FORM_C);
+        if (!$normalised) {
+            // An error occurred in normalizer_normalize, but we have no idea what.
+            debugging('Failed to normalise string: ' . $string, DEBUG_DEVELOPER);
+            return $string; // Return the original string, since it is the best we have.
+        }
+
+        return $normalised;
     }
 
     public function get_correct_response() {
index f9bf057..9160201 100644 (file)
@@ -867,58 +867,180 @@ sup {vertical-align: super;}
 #page-admin-grade-edit-scale-edit.dir-rtl .error input#id_name {margin-right: 170px;}
 .initialbar a {padding-right: 2px;}
 
-/**
- * Chooser Dialogue
- *
- * This CSS belong to the chooser dialogue which should work both with, and
- * without javascript enabled
- */
-/* Hide the dialog and it's title */
-.chooserdialoguebody,
-.choosertitle {
-    display:none;
+/* Moodle Dialogue Settings (moodle-core-dialogue)  */
+.moodle-dialogue-base .moodle-dialogue-lightbox {
+    background-color:#AAA;
 }
 
+.moodle-dialogue-base .hidden,
+.moodle-dialogue-base .moodle-dialogue-hidden {display:none;}
 .moodle-dialogue-base .moodle-dialogue {
-    background: none!important;
-    border: 0 none!important;
+    padding: 0;
+    margin: 0;
+    background: none;
+    border: none;
+    /* Override the z-index set incorrectly by the YUI dialogue */
+    z-index: 600!important;
 }
 
-.chooserdialogue .moodle-dialogue-wrap {
-    height: auto;
+
+.moodle-dialogue-base .moodle-dialogue-wrap {
+    margin-top:-3px;
+    margin-left:-3px;
     background-color: #FFFFFF;
-    border: 1px solid #CCCCCC!important;
+    border: 1px solid #CCCCCC;
     border-radius:10px;
     box-shadow: 5px 5px 20px 0px #666666;
     -webkit-box-shadow: 5px 5px 20px 0px #666666;
     -moz-box-shadow: 5px 5px 20px 0px #666666;
 }
 
-.chooserdialogue .moodle-dialogue-wrap .moodle-dialogue-hd {
-    font-size:12px!important;
-    font-weight: normal!important;
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd {
+    margin:0;
+    padding:5px;
+    font-size:12px;
+    font-weight: normal;
     letter-spacing: 1px;
-    color:#333333!important;
-    text-align: center!important;
+    color:#333333;
+    text-align: center;
     text-shadow: 1px 1px 1px #FFFFFF;
-    padding:5px 5px 5px 5px;
     border-radius: 10px 10px 0px 0px;
-    border-bottom: 1px solid #BBBBBB!important;
-    background: #CCCCCC!important;
-    background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC))!important;
-    background: -moz-linear-gradient(top,  #FFFFFF,  #CCCCCC)!important;
+    border-bottom: 1px solid #BBBBBB;
+    background: #CCCCCC;
+    background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#CCCCCC));
+    background: -moz-linear-gradient(top,  #FFFFFF,  #CCCCCC);
     filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#CCCCCC')!important;
     filter: dropshadow(color=#FFFFFF, offx=1, offy=1);
 }
-/* Activity Chooser "Close" button */
-.dir-rtl .moodle-dialogue-base .closebutton {float: left;}
+
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd h1 {
+    margin:0;
+    padding:0;
+    display:inline;
+    font-size: 100%;
+    font-weight: bold;
+}
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons {
+    padding: 5px;
+}
+.moodle-dialogue-base .closebutton {
+    width:25px;
+    height:15px;
+    float:right;
+    vertical-align:middle;
+    display:inline-block;
+    cursor:pointer;
+    padding:0px;
+    background-image:url([[pix:theme|sprite]]);
+    background-repeat:no-repeat;
+    border-style:none;
+}
+.dir-rtl .moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons {
+    left: 0px;
+    right: auto;
+}
+
+.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-bd {
+    overflow: auto;
+    padding: 1em;
+    line-height: 2em;
+    color: #555;
+    font-size: 12px;
+}
+
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-content {
+  padding:0px;
+  background:#FFF;
+}
+
+.moodle-dialogue-confirm .confirmation-dialogue {text-align:center;}
+.moodle-dialogue-confirm .confirmation-dialogue input {text-align:center;}
+.moodle-dialogue-exception .moodle-exception-message {text-align:center}
+.moodle-dialogue-exception .moodle-exception-param label {font-weight:bold;}
+.moodle-dialogue-exception .param-stacktrace label {
+    background-color:#EEE;
+    border:1px solid #ccc;
+    border-bottom-width:0;
+}
+
+.moodle-dialogue-exception .param-stacktrace pre {
+    border:1px solid #ccc;
+    background-color:#fff;
+}
+
+.moodle-dialogue-exception .param-stacktrace .stacktrace-file {
+    color:navy
+    font-size:80%
+}
+.moodle-dialogue-exception .param-stacktrace .stacktrace-line {
+    color:#AA0000
+    font-size:80%
+}
+.moodle-dialogue-exception .param-stacktrace .stacktrace-call {
+    color:#333
+    font-size:90%
+    border-bottom:1px solid #eee
+}
+
+.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-content .moodle-dialogue-ft {
+    padding:0px;
+    margin: 0.7em 1em;
+    text-align: right;
+    background-color: #FFF;
+    font-size: 12px;
+}
+
+.moodle-dialogue-confirm .confirmation-message {margin:0.5em 1em;}
+.moodle-dialogue-confirm .confirmation-dialogue input {min-width:80px}
+.moodle-dialogue-exception .moodle-exception-message {margin:1em;}
+.moodle-dialogue-exception .moodle-exception-param {margin-bottom:0.5em;}
+.moodle-dialogue-exception .moodle-exception-param label {width:150px;}
+.moodle-dialogue-exception .param-stacktrace label {
+    display:block;
+    margin:0;
+    padding:4px 1em;
+}
+.moodle-dialogue-exception .param-stacktrace pre {
+    display:block;
+    height:200px;
+    overflow:auto;
+}
+
+.moodle-dialogue-exception .param-stacktrace .stacktrace-file {
+    display:inline-block
+    margin:4px 0
+}
+.moodle-dialogue-exception .param-stacktrace .stacktrace-line {
+    display:inline-block
+    width:50px
+    margin:4px 1em
+}
+.moodle-dialogue-exception .param-stacktrace .stacktrace-call {
+    padding-left:25px
+    margin-bottom:4px
+    padding-bottom:4px
+}
+
+
 /* Question Bank - Question Chooser "Close" button */
 #page-question-edit.dir-rtl a.container-close {right:auto;left:6px;}
 
+/**
+ * Chooser Dialogues (moodle-core-chooserdialogue)
+ *
+ * This CSS belong to the chooser dialogue which should work both with, and
+ * without javascript enabled
+ */
+/* Hide the dialog and it's title */
+.chooserdialoguebody,
+.choosertitle {
+    display:none;
+}
+.moodle-dialogue.chooserdialogue .moodle-dialogue-content .moodle-dialogue-ft {
+    margin: 0;
+}
+
 .chooserdialogue .moodle-dialogue-wrap .moodle-dialogue-bd {
-    font-size: 12px;
-    color: #555555;
-    overflow: auto;
     padding: 0px;
     background: #F2F2F2;
     border-bottom-left-radius: 10px;
index d71f000..20c7d86 100644 (file)
@@ -494,7 +494,7 @@ div.yui3-widget-bd {
     background: none;
 }
 
-div.yui3-widget-bd h1.helpheading {
+div.yui3-widget-bd h2.helpheading {
     font-size: 16px !important;
     font-weight: 800;
     margin-top: 5px;
index b333b1d..575d34c 100644 (file)
@@ -33,7 +33,8 @@ ul {
     color:inherit;
     font-size:inherit;
 }
-h1.helpheading {
+h1.helpheading,
+h2.helpheading {
     font-size: 1.6em;
 }
 /*extra line abve labels and remove padding right for no icon */
index 54d65f2..9439c4e 100644 (file)
@@ -377,8 +377,9 @@ if (!isset($hiddenfields['suspended'])) {
 
 echo "</table></div></div>";
 
-
+echo '<div id="region-content" class="block-region"><div class="region-content">';
 echo $OUTPUT->blocks_for_region('content');
+echo '</div></div>';
 
 // Print messaging link if allowed
 if (isloggedin() && has_capability('moodle/site:sendmessage', $context)