示例#1
0
 public function test_grade_edit_tree_column_range_get_item_cell()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     // Make some things we need.
     $scale = $this->getDataGenerator()->create_scale();
     $course = $this->getDataGenerator()->create_course();
     $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
     $modulecontext = context_module::instance($assign->id);
     // The generator returns a dummy object, lets get the real assign object.
     $assign = new assign($modulecontext, false, false);
     $cm = $assign->get_course_module();
     // Get range column.
     $column = grade_edit_tree_column::factory('range');
     $gradeitemparams = array('itemtype' => 'mod', 'itemmodule' => $cm->modname, 'iteminstance' => $cm->instance, 'courseid' => $cm->course, 'itemnumber' => 0);
     // Lets set the grade to something we know.
     $instance = $assign->get_instance();
     $instance->grade = 70;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     $this->assertEquals(GRADE_TYPE_VALUE, $gradeitem->gradetype);
     $this->assertEquals(null, $gradeitem->scaleid);
     $this->assertEquals(70.0, (double) $cell->text, "Grade text is 70", 0.01);
     // Now change it to a scale.
     $instance = $assign->get_instance();
     $instance->grade = -$scale->id;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     // Make the expected scale text.
     $scaleitems = null;
     $scaleitems = explode(',', $scale->scale);
     $scalestring = end($scaleitems) . ' (' . count($scaleitems) . ')';
     $this->assertEquals(GRADE_TYPE_SCALE, $gradeitem->gradetype);
     $this->assertEquals($scale->id, $gradeitem->scaleid);
     $this->assertEquals($scalestring, $cell->text, "Grade text matches scale");
     // Now change it to no grade.
     $instance = $assign->get_instance();
     $instance->grade = 0;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     $this->assertEquals(GRADE_TYPE_TEXT, $gradeitem->gradetype);
     $this->assertEquals(null, $gradeitem->scaleid);
     $this->assertEquals(' - ', $cell->text, 'Grade text matches empty value of " - "');
 }
 /**
  * Return things to the renderer.
  *
  * @return int the course module id
  */
 public function get_course_module_id()
 {
     return $this->assignment->get_course_module()->id;
 }
示例#3
0
 /**
  * Tests the is_available and get_description functions.
  */
 public function test_usage()
 {
     global $CFG, $DB;
     require_once $CFG->dirroot . '/mod/assign/locallib.php';
     $this->resetAfterTest();
     // Create course with completion turned on.
     $CFG->enablecompletion = true;
     $CFG->enableavailability = true;
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('enablecompletion' => 1));
     $user = $generator->create_user();
     $generator->enrol_user($user->id, $course->id);
     $this->setUser($user);
     // Create a Page with manual completion for basic checks.
     $page = $generator->get_plugin_generator('mod_page')->create_instance(array('course' => $course->id, 'name' => 'Page!', 'completion' => COMPLETION_TRACKING_MANUAL));
     // Create an assignment - we need to have something that can be graded
     // so as to test the PASS/FAIL states. Set it up to be completed based
     // on its grade item.
     $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Assign!', 'completion' => COMPLETION_TRACKING_AUTOMATIC));
     $DB->set_field('course_modules', 'completiongradeitemnumber', 0, array('id' => $assignrow->cmid));
     $assign = new assign(context_module::instance($assignrow->cmid), false, false);
     // Get basic details.
     $modinfo = get_fast_modinfo($course);
     $pagecm = $modinfo->get_cm($page->cmid);
     $assigncm = $assign->get_course_module();
     $info = new \core_availability\mock_info($course, $user->id);
     // COMPLETE state (false), positive and NOT.
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // INCOMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     // Mark page complete.
     $completion = new completion_info($course);
     $completion->update_state($pagecm, COMPLETION_COMPLETE);
     // COMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     // INCOMPLETE state (false).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // We are going to need the grade item so that we can get pass/fails.
     $gradeitem = $assign->get_grade_item();
     grade_object::set_properties($gradeitem, array('gradepass' => 50.0));
     $gradeitem->update();
     // With no grade, it should return true for INCOMPLETE and false for
     // the other three.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Check $information for COMPLETE_PASS and _FAIL as we haven't yet.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Change the grade to be complete and failed.
     self::set_grade($assignrow, $user->id, 40);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and failed~', $information);
     // Now change it to pass.
     self::set_grade($assignrow, $user->id, 60);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and passed~', $information);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Simulate deletion of an activity by using an invalid cmid. These
     // conditions always fail, regardless of NOT flag or INCOMPLETE.
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~(Missing activity).*is marked complete~', $information);
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
 }
示例#4
0
    /**
     * Process an uploaded zip file
     *
     * @param assign $assignment - The assignment instance
     * @param assign_feedback_file $fileplugin - The file feedback plugin
     * @return string - The html response
     */
    public function import_zip_files($assignment, $fileplugin) {
        global $USER, $CFG, $PAGE, $DB;

        @set_time_limit(ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME);
        $packer = get_file_packer('application/zip');

        $feedbackfilesupdated = 0;
        $feedbackfilesadded = 0;
        $userswithnewfeedback = array();
        $contextid = $assignment->get_context()->id;

        $fs = get_file_storage();
        $files = $fs->get_directory_files($contextid,
                                          'assignfeedback_file',
                                          ASSIGNFEEDBACK_FILE_IMPORT_FILEAREA,
                                          $USER->id,
                                          '/import/');

        $currentgroup = groups_get_activity_group($assignment->get_course_module(), true);
        $allusers = $assignment->list_participants($currentgroup, false);
        $participants = array();
        foreach ($allusers as $user) {
            $participants[$assignment->get_uniqueid_for_user($user->id)] = $user;
        }

        foreach ($files as $unzippedfile) {
            // Set the timeout for unzipping each file.
            $user = null;
            $plugin = null;
            $filename = '';

            if ($this->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $user, $plugin, $filename)) {
                if ($this->is_file_modified($assignment, $user, $plugin, $filename, $unzippedfile)) {
                    $grade = $assignment->get_user_grade($user->id, true);

                    if ($oldfile = $fs->get_file($contextid,
                                                 'assignfeedback_file',
                                                 ASSIGNFEEDBACK_FILE_FILEAREA,
                                                 $grade->id,
                                                 '/',
                                                 $filename)) {
                        // Update existing feedback file.
                        $oldfile->replace_content_with($unzippedfile);
                        $feedbackfilesupdated++;
                    } else {
                        // Create a new feedback file.
                        $newfilerecord = new stdClass();
                        $newfilerecord->contextid = $contextid;
                        $newfilerecord->component = 'assignfeedback_file';
                        $newfilerecord->filearea = ASSIGNFEEDBACK_FILE_FILEAREA;
                        $newfilerecord->filename = $filename;
                        $newfilerecord->filepath = '/';
                        $newfilerecord->itemid = $grade->id;
                        $fs->create_file_from_storedfile($newfilerecord, $unzippedfile);
                        $feedbackfilesadded++;
                    }
                    $userswithnewfeedback[$user->id] = 1;

                    // Update the number of feedback files for this user.
                    $fileplugin->update_file_count($grade);

                    // Update the last modified time on the grade which will trigger student notifications.
                    $assignment->notify_grade_modified($grade);
                }
            }
        }

        require_once($CFG->dirroot . '/mod/assign/feedback/file/renderable.php');
        $importsummary = new assignfeedback_file_import_summary($assignment->get_course_module()->id,
                                                            count($userswithnewfeedback),
                                                            $feedbackfilesadded,
                                                            $feedbackfilesupdated);

        $assignrenderer = $assignment->get_renderer();
        $renderer = $PAGE->get_renderer('assignfeedback_file');

        $o = '';

        $o .= $assignrenderer->render(new assign_header($assignment->get_instance(),
                                                        $assignment->get_context(),
                                                        false,
                                                        $assignment->get_course_module()->id,
                                                        get_string('uploadzipsummary', 'assignfeedback_file')));

        $o .= $renderer->render($importsummary);

        $o .= $assignrenderer->render_footer();
        return $o;
    }
示例#5
0
 /**
  * Tests for importing grades from an external source.
  */
 public function test_grade_import_commit()
 {
     global $USER, $DB, $CFG;
     $this->resetAfterTest();
     $importcode = get_new_importcode();
     $user1 = $this->getDataGenerator()->create_user();
     $user2 = $this->getDataGenerator()->create_user();
     $course = $this->getDataGenerator()->create_course();
     $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
     $itemname = $assign->name;
     $modulecontext = context_module::instance($assign->cmid);
     // The generator returns a dummy object, lets get the real assign object.
     $assign = new assign($modulecontext, false, false);
     $cm = $assign->get_course_module();
     // Enrol users in the course.
     $this->getDataGenerator()->enrol_user($user1->id, $course->id);
     $this->getDataGenerator()->enrol_user($user2->id, $course->id);
     // Enter a new grade into an existing grade item.
     $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod'));
     // Keep this value around for a test further down.
     $originalgrade = 55;
     $this->import_grades(array('importcode' => $importcode, 'itemid' => $gradeitem->id, 'userid' => $user1->id, 'finalgrade' => $originalgrade));
     $status = grade_import_commit($course->id, $importcode, false, false);
     $this->assertTrue($status);
     // Get imported grade_grade.
     $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id));
     $this->assertEquals($originalgrade, $gradegrade->finalgrade);
     // Overriden field will be a timestamp and will evaluate out to true.
     $this->assertTrue($gradegrade->is_overridden());
     // Create a new grade item and import into that.
     $importcode = get_new_importcode();
     $record = new stdClass();
     $record->itemname = 'New grade item';
     $record->importcode = $importcode;
     $record->importer = $USER->id;
     $insertid = $DB->insert_record('grade_import_newitem', $record);
     $finalgrade = 75;
     $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'finalgrade' => $finalgrade, 'newgradeitem' => $insertid));
     $status = grade_import_commit($course->id, $importcode, false, false);
     $this->assertTrue($status);
     // Check that we have a new grade_item.
     $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'manual'));
     $this->assertEquals($record->itemname, $gradeitem->itemname);
     // Grades were imported.
     $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id));
     $this->assertEquals($finalgrade, $gradegrade->finalgrade);
     // As this is a new item the grade has not been overridden.
     $this->assertFalse($gradegrade->is_overridden());
     // Import feedback only.
     $importcode = get_new_importcode();
     $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod'));
     $originalfeedback = 'feedback can be useful';
     $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id, 'feedback' => $originalfeedback, 'importonlyfeedback' => true));
     $status = grade_import_commit($course->id, $importcode, true, false);
     $this->assertTrue($status);
     $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id));
     // The final grade should be the same as the first record further up. We are only altering the feedback.
     $this->assertEquals($originalgrade, $gradegrade->finalgrade);
     $this->assertTrue($gradegrade->is_overridden());
     // Import grades only.
     $importcode = get_new_importcode();
     $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod'));
     $finalgrade = 60;
     $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id, 'finalgrade' => $finalgrade, 'feedback' => 'feedback can still be useful'));
     $status = grade_import_commit($course->id, $importcode, false, false);
     $this->assertTrue($status);
     $gradegrade = grade_grade::fetch(array('itemid' => $gradeitem->id, 'userid' => $user1->id));
     $this->assertEquals($finalgrade, $gradegrade->finalgrade);
     // The final feedback should not have changed.
     $this->assertEquals($originalfeedback, $gradegrade->feedback);
     $this->assertTrue($gradegrade->is_overridden());
     // Check that printing of import status is correct.
     $importcode = get_new_importcode();
     $gradeitem = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod'));
     $this->import_grades(array('importcode' => $importcode, 'userid' => $user1->id, 'itemid' => $gradeitem->id));
     $url = $CFG->wwwroot . '/grade/index.php';
     $expectedresponse = "++ Grade import success ++\n<div class=\"continuebutton\"><form method=\"get\" action=\"{$url}\"><div><input type=\"submit\" value=\"Continue\" /><input type=\"hidden\" name=\"id\" value=\"{$course->id}\" /></div></form></div>";
     ob_start();
     $status = grade_import_commit($course->id, $importcode);
     $output = ob_get_contents();
     ob_end_clean();
     $this->assertTrue($status);
     $this->assertEquals($expectedresponse, $output);
 }
示例#6
0
 /**
  * Process an uploaded zip file
  *
  * @param assign $assignment - The assignment instance
  * @param assign_feedback_file $fileplugin - The file feedback plugin
  * @return string - The html response
  */
 public function import_zip_files($assignment, $fileplugin)
 {
     global $CFG, $PAGE, $DB;
     core_php_time_limit::raise(ASSIGNFEEDBACK_FILE_MAXFILEUNZIPTIME);
     $packer = get_file_packer('application/zip');
     $feedbackfilesupdated = 0;
     $feedbackfilesadded = 0;
     $userswithnewfeedback = array();
     $contextid = $assignment->get_context()->id;
     $fs = get_file_storage();
     $files = $this->get_import_files($contextid);
     $currentgroup = groups_get_activity_group($assignment->get_course_module(), true);
     $allusers = $assignment->list_participants($currentgroup, false);
     $participants = array();
     foreach ($allusers as $user) {
         $participants[$assignment->get_uniqueid_for_user($user->id)] = $user;
     }
     foreach ($files as $unzippedfile) {
         // Set the timeout for unzipping each file.
         $user = null;
         $plugin = null;
         $filename = '';
         if ($this->is_valid_filename_for_import($assignment, $unzippedfile, $participants, $user, $plugin, $filename)) {
             if ($this->is_file_modified($assignment, $user, $plugin, $filename, $unzippedfile)) {
                 $grade = $assignment->get_user_grade($user->id, true);
                 // In 3.1 the default download structure of the submission files changed so that each student had their own
                 // separate folder, the files were not renamed and the folder structure was kept. It is possible that
                 // a user downloaded the submission files in 3.0 (or earlier) and edited the zip to add feedback or
                 // changed the behavior back to the previous format, the following code means that we will still support the
                 // old file structure. For more information please see - MDL-52489 / MDL-56022.
                 $path = pathinfo($filename);
                 if ($path['dirname'] == '.') {
                     // Student submissions are not in separate folders.
                     $basename = $filename;
                     $dirname = "/";
                     $dirnamewslash = "/";
                 } else {
                     $basename = $path['basename'];
                     $dirname = $path['dirname'];
                     $dirnamewslash = $dirname . "/";
                 }
                 if ($oldfile = $fs->get_file($contextid, 'assignfeedback_file', ASSIGNFEEDBACK_FILE_FILEAREA, $grade->id, $dirname, $basename)) {
                     // Update existing feedback file.
                     $oldfile->replace_file_with($unzippedfile);
                     $feedbackfilesupdated++;
                 } else {
                     // Create a new feedback file.
                     $newfilerecord = new stdClass();
                     $newfilerecord->contextid = $contextid;
                     $newfilerecord->component = 'assignfeedback_file';
                     $newfilerecord->filearea = ASSIGNFEEDBACK_FILE_FILEAREA;
                     $newfilerecord->filename = $basename;
                     $newfilerecord->filepath = $dirnamewslash;
                     $newfilerecord->itemid = $grade->id;
                     $fs->create_file_from_storedfile($newfilerecord, $unzippedfile);
                     $feedbackfilesadded++;
                 }
                 $userswithnewfeedback[$user->id] = 1;
                 // Update the number of feedback files for this user.
                 $fileplugin->update_file_count($grade);
                 // Update the last modified time on the grade which will trigger student notifications.
                 $assignment->notify_grade_modified($grade);
             }
         }
     }
     require_once $CFG->dirroot . '/mod/assign/feedback/file/renderable.php';
     $importsummary = new assignfeedback_file_import_summary($assignment->get_course_module()->id, count($userswithnewfeedback), $feedbackfilesadded, $feedbackfilesupdated);
     $assignrenderer = $assignment->get_renderer();
     $renderer = $PAGE->get_renderer('assignfeedback_file');
     $o = '';
     $o .= $assignrenderer->render(new assign_header($assignment->get_instance(), $assignment->get_context(), false, $assignment->get_course_module()->id, get_string('uploadzipsummary', 'assignfeedback_file')));
     $o .= $renderer->render($importsummary);
     $o .= $assignrenderer->render_footer();
     return $o;
 }
 /**
  * Makes the grading interface for the pop up. Robbed from /mod/assign/locallib.php
  * line 1583ish - view_single_grade_page().
  *
  * @param array $params From $_GET
  * @param object $coursemodule The coursemodule object that the user has been authenticated
  * against
  * @param bool $data
  * @throws coding_exception
  * @global $PAGE
  * @global stdClass $CFG
  * @global moodle_database $DB
  * @global $OUTPUT
  * @global stdClass $USER
  * @return string
  */
 public function grading_popup($params, $coursemodule, $data = false)
 {
     global $PAGE, $CFG, $DB;
     $modulecontext = context_module::instance($coursemodule->id);
     $course = $DB->get_record('course', array('id' => $coursemodule->course));
     $coursecontext = context_course::instance($course->id);
     $assign = new assign($modulecontext, $coursemodule, $course);
     /* @var mod_assign_renderer $renderer */
     $renderer = $PAGE->get_renderer('mod_assign');
     $output = '';
     // Include grade form.
     require_once $CFG->dirroot . '/mod/assign/gradeform.php';
     // Need submit permission to submit an assignment.
     require_capability('mod/assign:grade', $modulecontext);
     /* Pinched from private method assign::get_grading_userid_list() */
     $filter = get_user_preferences('assign_filter', '');
     $table = new assign_grading_table($assign, 0, $filter, 0, false);
     $useridlist = $table->get_column_data('userid');
     $userid = $params['userid'];
     $rownum = 0;
     foreach ($useridlist as $key => $useridinlist) {
         if ($useridinlist == $userid) {
             $rownum = $key;
             reset($useridlist);
             // Just in case.
             break;
         }
     }
     $last = false;
     if ($rownum == count($useridlist) - 1) {
         $last = true;
     }
     $user = $DB->get_record('user', array('id' => $userid));
     if ($user) {
         $output .= $renderer->render(new assign_user_summary($user, $course->id, has_capability('moodle/site:viewfullnames', $coursecontext)));
     }
     $submission = $DB->get_record('assign_submission', array('assignment' => $assign->get_instance()->id, 'userid' => $userid));
     // Get the current grade. Pinched from assign::get_user_grade().
     $grade = $DB->get_record('assign_grades', array('assignment' => $assign->get_instance()->id, 'userid' => $userid));
     // Pinched from assign::is_graded().
     $isgraded = !empty($grade) && $grade->grade !== null && $grade->grade >= 0;
     if ($assign->can_view_submission($userid)) {
         $gradelocked = $grade && $grade->locked || $assign->grading_disabled($userid);
         $widget = new assign_submission_status($assign->get_instance()->allowsubmissionsfromdate, $assign->get_instance()->alwaysshowdescription, $submission, $assign->is_any_submission_plugin_enabled(), $gradelocked, $isgraded, $assign->get_instance()->duedate, $assign->get_submission_plugins(), $assign->get_return_action(), $assign->get_return_params(), $assign->get_course_module()->id, assign_submission_status::GRADER_VIEW, false, false);
         $output .= $renderer->render($widget);
     }
     if ($grade) {
         $data = new stdClass();
         if ($grade->grade !== null && $grade->grade >= 0) {
             $data->grade = format_float($grade->grade, 2);
         }
     } else {
         $data = new stdClass();
         $data->grade = '';
     }
     // Now show the grading form.
     $customdata = array('useridlist' => $useridlist, 'rownum' => $rownum, 'last' => $last);
     $mform = new mod_assign_grade_form(block_ajax_marking_form_url($params), array($assign, $data, $customdata), 'post', '', array('class' => 'gradeform'));
     $output .= $renderer->render(new assign_form('gradingform', $mform));
     $assign->add_to_log('view grading form', get_string('viewgradingformforstudent', 'assign', array('id' => $user->id, 'fullname' => fullname($user))));
     return $output;
 }