]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-10386 Refactored the grader report file (index.php), and extracted the grade_repo...
authornicolasconnault <nicolasconnault>
Thu, 12 Jul 2007 16:36:38 +0000 (16:36 +0000)
committernicolasconnault <nicolasconnault>
Thu, 12 Jul 2007 16:36:38 +0000 (16:36 +0000)
grade/report.php
grade/report/grader/grader_report.php [new file with mode: 0644]
grade/report/grader/index.php
lib/gradelib.php
lib/weblib.php

index 8a63da1b4c241e5448ddb5d57fd3cd46eb9d7b4f..c82967e8fabae48911caac3ea1f884aecce6e44e 100644 (file)
@@ -29,7 +29,6 @@
     $courseid = required_param('id');              // course id
     $report   = optional_param('report', 'user', PARAM_FILE);              // course id
     $edit     = optional_param('edit', -1, PARAM_BOOL); // sticky editting mode
-    $feedback = optional_param('feedback', -1, PARAM_BOOL); // sticky feedback mode
 
 /// Make sure they can even access this course
 
@@ -99,7 +98,7 @@
         $USER->gradeediting = 0;
     }
 
-    // params for the turn editting on and feedback buttons
+    // params for the turn editting on
     $options['id'] = $courseid;
     $options['report'] = $report;
 
diff --git a/grade/report/grader/grader_report.php b/grade/report/grader/grader_report.php
new file mode 100644 (file)
index 0000000..2a5f0aa
--- /dev/null
@@ -0,0 +1,1136 @@
+<?php // $Id$
+/**
+ * File in which the grader_report class is defined.
+ * @package gradebook
+ */
+
+define('GRADER_REPORT_AGGREGATION_POSITION_LEFT', 0);
+define('GRADER_REPORT_AGGREGATION_POSITION_RIGHT', 1);
+define('GRADER_REPORT_AGGREGATION_VIEW_FULL', 0);
+define('GRADER_REPORT_AGGREGATION_VIEW_COMPACT', 1);
+define('GRADER_REPORT_GRADE_DISPLAY_TYPE_RAW', 0);
+define('GRADER_REPORT_GRADE_DISPLAY_TYPE_PERCENTAGE', 1);
+define('GRADER_REPORT_FEEDBACK_FORMAT_TEXT', 0);
+define('GRADER_REPORT_FEEDBACK_FORMAT_HTML', 1);
+
+require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/gradelib.php');
+require_once($CFG->dirroot.'/grade/report/lib.php');
+
+/**
+ * Class providing an API for the grader report building and displaying.
+ * @package gradebook
+ */
+class grade_report_grader {
+    /**
+     * The courseid.
+     * @var int $courseid
+     */
+    var $courseid;
+
+    /**
+     * The context.
+     * @var int $context
+     */
+    var $context;
+
+    /**
+     * The grade_tree object.
+     * @var object $gtree
+     */
+    var $gtree;
+
+    /**
+     * The final grades.
+     * @var array $finalgrades
+     */
+    var $finalgrades;
+
+    /**
+     * The grade items.
+     * @var array $items
+     */
+    var $items;
+
+    /**
+     * Array of errors for bulk grades updating.
+     * @var array $gradeserror
+     */
+    var $gradeserror = array();
+
+//// USER PREFERENCES
+
+    /**
+     * Number of users on a page.
+     * @var int $perpage
+     */
+    var $studentsperpage;
+
+    /**
+     * Number of digits after the decimal point.
+     * @var int $decimalspoints
+     */
+    var $decimalspoints;
+
+    /**
+     * Whether or not to display the grandtotals row.
+     * @var bool $showgrandtotals
+     */
+    var $showgrandtotals;
+
+    /**
+     * Whether or not to display group selector, total row and other group-related elements.
+     * @var bool $showgroups
+     */
+    var $showgroups;
+
+    /**
+     * The position of the Aggregation column in relation to the raw grade items.
+     * @var int $aggregation_position
+     */
+    var $aggregation_position;
+
+    /**
+     * Whether or not to display a row of scales/ranges for each grade_item.
+     * @var bool $showscales
+     */
+    var $showscales;
+
+    /**
+     * Whether or not to use quickgrading.
+     * @var bool $quickgrading
+     */
+    var $quickgrading;
+
+    /**
+     * Whether or not to use quickfeedback.
+     * @var bool $quickfeedback
+     */
+    var $quickfeedback;
+
+//// SQL-RELATED
+
+    /**
+     * The roles for this report.
+     * @var string $gradebookroles
+     */
+    var $gradebookroles;
+
+    /**
+     * base url for sorting by first/last name.
+     * @var string $baseurl
+     */
+    var $baseurl;
+
+    /**
+     * base url for paging.
+     * @var string $pbarurl
+     */
+    var $pbarurl;
+
+    /**
+     * Current page (for paging).
+     * @var int $page
+     */
+    var $page;
+
+    /**
+     * The id of the grade_item by which this report will be sorted.
+     * @var int $sortitemid
+     */
+    var $sortitemid;
+
+    /**
+     * Sortorder used in the SQL selections.
+     * @var int $sortorder
+     */
+    var $sortorder;
+
+    /**
+     * An SQL fragment affecting the search for users.
+     * @var string $userselect
+     */
+    var $userselect;
+
+//// GROUP VARIABLES (including SQL)
+
+    /**
+     * The current group being displayed.
+     * @var int $currentgroup
+     */
+    var $currentgroup;
+
+    /**
+     * A HTML select element used to select the current group.
+     * @var string $group_selector
+     */
+    var $group_selector;
+
+    /**
+     * An SQL fragment used to add linking information to the group tables.
+     * @var string $groupsql
+     */
+    var $groupsql;
+
+    /**
+     * An SQL constraint to append to the queries used by this object to build the report.
+     * @var string $groupwheresql
+     */
+    var $groupwheresql;
+
+
+
+    /**
+     * Constructor. Sets local copies of user preferences and initialises grade_tree.
+     * @param int $courseid
+     */
+    function grade_report_grader($courseid, $context, $page=null, $sortitemid=null) {
+        global $CFG;
+
+        $this->courseid = $courseid;
+        $this->context = $context;
+        $this->page = $page;
+        $this->sortitemid = $sortitemid;
+
+        // roles to be displayed in the gradebook
+        $this->gradebookroles = $CFG->gradebookroles;
+
+        // User preferences
+        $this->studentsperpage      = get_user_preferences('grade_report_studentsperpage',
+                                                            $CFG->grade_report_studentsperpage);
+        $this->decimalpoints        = get_user_preferences('grade_report_decimalpoints',
+                                                            $CFG->grade_report_decimalpoints);
+        $this->showgrandtotals      = get_user_preferences('grade_report_showgrandtotals',
+                                                            $CFG->grade_report_showgrandtotals);
+        $this->showgroups           = get_user_preferences('grade_report_showgroups',
+                                                            $CFG->grade_report_showgroups);
+        $this->aggregation_position = get_user_preferences('grade_report_aggregationposition',
+                                                            $CFG->grade_report_aggregationposition);
+        $this->showscales           = get_user_preferences('grade_report_showscales',
+                                                            $CFG->grade_report_showscales);
+        $this->quickgrading         = get_user_preferences('grade_report_quickgrading',
+                                                            $CFG->grade_report_quickgrading);
+        $this->quickfeedback        = get_user_preferences('grade_report_quickfeedback',
+                                                            $CFG->grade_report_quickfeedback);
+
+        // Grab the grade_tree for this course
+        $this->gtree = new grade_tree($this->courseid, true, false, $this->aggregation_position);
+
+        // base url for sorting by first/last name
+        $this->baseurl = 'report.php?id='.$this->courseid.'&amp;perpage='.$this->studentsperpage.'&amp;report=grader&amp;page='.$this->page;
+        //
+        $this->pbarurl = 'report.php?id='.$this->courseid.'&amp;perpage='.$this->studentsperpage.'&amp;report=grader&amp;';
+
+        if ($this->showgroups) {
+            $this->setup_groups();
+        }
+
+        $this->setup_sortitemid();
+    }
+
+    /**
+     * Uses set_user_preferences() to update the value of a user preference.
+     * Also updates the object's corresponding variable.
+     * @param string $pref_name The name of the preference.
+     * @param mixed $pref_value The value of the preference.
+     * @return bool Success or failure.
+     * TODO print visual feedback
+     */
+    function set_user_pref($pref_name, $pref_value) {
+        if ($result = set_user_preferences(array($pref_name => $pref_value))) {
+            $this->$pref_name = $pref_value;
+        }
+        return $result;
+    }
+
+    /**
+     * Processes the data sent by the form (grades and feedbacks).
+     * @var array $data
+     * @return bool Success or Failure (array of errors).
+     */
+    function process_data($data) {
+        // always initialize all arrays
+        $queue = array();
+
+        foreach ($data as $varname => $postedvalue) {
+            // this is a bit tricky - we have to first load all grades into memory,
+            // check if changed and only then start updating the final grades because
+            // columns might depend one on another - the result would be overriden calculated and category grades
+
+            $needsupdate = false;
+            $note = false; // TODO implement note??
+
+            // skip, not a grade nor feedback
+            $data_type = '';
+            if (strstr($varname, 'grade')) {
+                $data_type = 'grade';
+            } elseif (strstr($varname, 'feedback')) {
+                $data_type = 'feedback';
+            } else {
+                continue;
+            }
+
+            $gradeinfo = explode("_", $varname);
+
+            $userid = clean_param($gradeinfo[1], PARAM_INT);
+            $itemid = clean_param($gradeinfo[2], PARAM_INT);
+
+            if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$this->courseid))) { // we must verify course id here!
+                error('Incorrect grade item id');
+            }
+
+            // Pre-process grade
+            if ($data_type == 'grade') {
+
+                if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+                    if ($postedvalue == -1) { // -1 means no grade
+                        $finalgrade = null;
+                    } else {
+                        $finalgrade = (float)$postedvalue;
+                    }
+                } else {
+                    if ($postedvalue == '') { // empty string means no grade
+                        $finalgrade = null;
+                    } else {
+                        $finalgrade = format_grade($postedvalue);
+                    }
+                }
+
+                if (!is_null($finalgrade) and ($finalgrade < $grade_item->grademin or $finalgrade > $grade_item->grademax)) {
+                    $this->gradeserror[$grade_item->id][$userid] = 'outofrange'; //TODO: localize
+                    // another possiblity is to use bounded number instead
+                    continue;
+                }
+            }
+
+            // Get the grade object to compare old value with new value
+            if ($grade = grade_grades::fetch(array('userid'=>$userid, 'itemid'=>$grade_item->id))) {
+                if ($data_type == 'feedback') {
+                    $finalgrade = false;
+                    $text = $grade->load_text();
+                    if ($text != s($postedvalue)) {
+                        $feedback = s($postedvalue);
+                        $feedbackformat = GRADER_REPORT_FEEDBACK_FORMAT_TEXT;
+                        $needsupdate = true;
+                    }
+                } elseif ($data_type == 'grade') {
+                    $feedback = false;
+                    $feedbackformat = false;
+                    if (!is_null($grade->finalgrade)) {
+                        $grade->finalgrade = (float)$grade->finalgrade;
+                    }
+                    if ($grade->finalgrade === $finalgrade) {
+                        $needsupdate = true;
+                    }
+                }
+
+            }
+
+            // we must not update all grades, only changed ones - we do not want to mark everything as overriden
+            if ($needsupdate) {
+                $gradedata = new object();
+                $gradedata->grade_item     = $grade_item;
+                $gradedata->userid         = $userid;
+                $gradedata->note           = $note;
+                $gradedata->finalgrade     = $finalgrade;
+                $gradedata->feedback       = $feedback;
+                $gradedata->feedbackformat = $feedbackformat;
+
+                $queue[] = $gradedata;
+            }
+        }
+
+        // now we update the new final grade for each changed grade
+        foreach ($queue as $gradedata) {
+            $gradedata->grade_item->update_final_grade($gradedata->userid, $gradedata->finalgrade, 'gradebook',
+                                                       $gradedata->note, $gradedata->feedback, $gradedata->feedbackformat);
+        }
+
+        return true;
+    }
+
+    /**
+     * Sets up this object's group variables, mainly to restrict the selection of users to display.
+     */
+    function setup_groups() {
+        global $CFG;
+
+        /// find out current groups mode
+        $course = get_record('course', 'id', $this->courseid);
+        $groupmode = $course->groupmode;
+        ob_start();
+        $this->currentgroup = setup_and_print_groups($course, $groupmode, $this->baseurl);
+        $this->group_selector = ob_get_clean();
+
+        // update paging after group
+        $this->baseurl .= 'group='.$this->currentgroup.'&amp;';
+        $this->pbarurl .= 'group='.$this->currentgroup.'&amp;';
+
+        if ($this->currentgroup) {
+            $this->groupsql = " LEFT JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id ";
+            $this->groupwheresql = " AND gm.groupid = $this->currentgroup ";
+        }
+    }
+
+    /**
+     * Setting the sort order, this depends on last state
+     * all this should be in the new table class that we might need to use
+     * for displaying grades.
+     */
+    function setup_sortitemid() {
+        if ($this->sortitemid) {
+            if (!isset($SESSION->gradeuserreport->sort)) {
+                $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+            } else {
+                // this is the first sort, i.e. by last name
+                if (!isset($SESSION->gradeuserreport->sortitemid)) {
+                    $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                } else if ($SESSION->gradeuserreport->sortitemid == $this->sortitemid) {
+                    // same as last sort
+                    if ($SESSION->gradeuserreport->sort == 'ASC') {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'DESC';
+                    } else {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                    }
+                } else {
+                    $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                }
+            }
+            $SESSION->gradeuserreport->sortitemid = $this->sortitemid;
+        } else {
+            // not requesting sort, use last setting (for paging)
+
+            if (isset($SESSION->gradeuserreport->sortitemid)) {
+                $this->sortitemid = $SESSION->gradeuserreport->sortitemid;
+            }
+            if (isset($SESSION->gradeuserreport->sort)) {
+                $this->sortorder = $SESSION->gradeuserreport->sort;
+            } else {
+                $this->sortorder = 'ASC';
+            }
+        }
+    }
+
+    /**
+     * Processes a single action against a category, grade_item or grade.
+     * @param string $target Sortorder
+     * @param string $action Which action to take (edit, delete etc...)
+     * @return
+     * TODO Update this, it's quite old and needs a major makeover
+     */
+    function process_action($target, $action) {
+        $element = $this->gtree->locate_element($target);
+
+        switch ($action) {
+            case 'edit':
+                break;
+            case 'delete':
+                if ($confirm == 1) { // Perform the deletion
+                    //TODO: add proper delete support for grade items and categories
+                    //$element['object']->delete();
+                    // Print result message
+
+                } else { // Print confirmation dialog
+                    $eid = $element['eid'];
+                    $strdeletecheckfull = get_string('deletecheck', '', $element['object']->get_name());
+                    $linkyes = "category.php?target=$eid&amp;action=delete&amp;confirm=1$this->gtree->commonvars";
+                    $linkno = "category.php?$this->gtree->commonvars";
+                    notice_yesno($strdeletecheckfull, $linkyes, $linkno);
+                }
+                break;
+
+            case 'hide':
+            // TODO Implement calendar for selection of a date to hide element until
+                $element['object']->set_hidden(1);
+                $this->gtree = new grade_tree($this->courseid);
+                break;
+            case 'show':
+                $element['object']->set_hidden(0);
+                $this->gtree = new grade_tree($this->courseid);
+                break;
+            case 'lock':
+            // TODO Implement calendar for selection of a date to lock element after
+                if (!$element['object']->set_locked(1)) {
+                    debugging("Could not update the element's locked state!");
+                }
+                $this->gtree = new grade_tree($this->courseid);
+                break;
+            case 'unlock':
+                if (!$element['object']->set_locked(0)) {
+                    debugging("Could not update the element's locked state!");
+                }
+                $this->gtree = new grade_tree($this->courseid);
+                break;
+            default:
+                break;
+        }
+
+    }
+
+    /**
+     * pulls out the userids of the users to be display, and sort them
+     * the right outer join is needed because potentially, it is possible not
+     * to have the corresponding entry in grade_grades table for some users
+     * this is check for user roles because there could be some users with grades
+     * but not supposed to be displayed
+     */
+    function load_users() {
+        global $CFG;
+
+        if (is_numeric($this->sortitemid)) {
+            $sql = "SELECT u.id, u.firstname, u.lastname
+                    FROM {$CFG->prefix}grade_grades g RIGHT OUTER JOIN
+                         {$CFG->prefix}user u ON (u.id = g.userid AND g.itemid = $this->sortitemid)
+                         LEFT JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                         $this->groupsql
+                    WHERE ra.roleid in ($this->gradebookroles)
+                         $this->groupwheresql
+                    AND ra.contextid ".get_related_contexts_string($this->context)."
+                    ORDER BY g.finalgrade $this->sortorder";
+            $this->users = get_records_sql($sql, $this->studentsperpage * $this->page, $this->studentsperpage);
+        } else {
+            // default sort
+            // get users sorted by lastname
+            $this->users = get_role_users(@implode(',', $CFG->gradebookroles), $this->context, false,
+                                'u.id, u.firstname, u.lastname', 'u.'.$this->sortitemid .' '. $this->sortorder,
+                                false, $this->page * $this->studentsperpage, $this->studentsperpage, $this->currentgroup);
+            // need to cut users down by groups
+
+        }
+
+        if (empty($this->users)) {
+            $this->userselect = '';
+            $this->users = array();
+        } else {
+            $this->userselect = 'AND g.userid in ('.implode(',', array_keys($this->users)).')';
+        }
+
+        return $this->users;
+    }
+
+    /**
+     * Fetches and returns a count of all the users that will be shows on this page.
+     * @return int Count of users
+     */
+    function get_numusers() {
+        global $CFG;
+        $countsql = "SELECT COUNT(DISTINCT u.id)
+                    FROM {$CFG->prefix}grade_grades g RIGHT OUTER JOIN
+                         {$CFG->prefix}user u ON (u.id = g.userid AND g.itemid = $this->sortitemid)
+                         LEFT JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                         $this->groupsql
+                    WHERE ra.roleid in ($this->gradebookroles)
+                         $this->groupwheresql
+                    AND ra.contextid ".get_related_contexts_string($this->context);
+        return count_records_sql($countsql);
+    }
+
+    /**
+     * we supply the userids in this query, and get all the grades
+     * pulls out all the grades, this does not need to worry about paging
+     */
+    function load_final_grades() {
+        global $CFG;
+
+        $sql = "SELECT g.id, g.itemid, g.userid, g.finalgrade, g.hidden, g.locked, g.locktime, g.overridden, gt.feedback
+                FROM  {$CFG->prefix}grade_items gi,
+                      {$CFG->prefix}grade_grades g
+                LEFT JOIN {$CFG->prefix}grade_grades_text gt ON g.id = gt.gradeid
+                WHERE g.itemid = gi.id
+                AND gi.courseid = $this->courseid $this->userselect";
+
+        if ($grades = get_records_sql($sql)) {
+            foreach ($grades as $grade) {
+                $this->finalgrades[$grade->userid][$grade->itemid] = $grade;
+            }
+        }
+    }
+
+    /**
+     * Builds and returns a div with on/off toggles.
+     * @return string HTML code
+     */
+    function get_toggles_html() {
+        global $USER;
+        $html = '<div id="grade-report-toggles">';
+        if ($USER->gradeediting) {
+            $html .= $this->print_toggle('eyecons', true);
+            $html .= $this->print_toggle('locks', true);
+            $html .= $this->print_toggle('calculations', true);
+        }
+
+        $html .= $this->print_toggle('grandtotals', true);
+        $html .= $this->print_toggle('groups', true);
+        $html .= $this->print_toggle('scales', true);
+        $html .= '</div>';
+        return $html;
+    }
+
+    /**
+    * Shortcut function for printing the grader report toggles.
+    * @param string $type The type of toggle
+    * @param bool $return Whether to return the HTML string rather than printing it
+    * @return void
+    */
+    function print_toggle($type, $return=false) {
+        global $CFG;
+
+        $icons = array('eyecons' => 'hide',
+                       'calculations' => 'calc',
+                       'locks' => 'lock',
+                       'grandtotals' => 'sigma');
+
+        $pref_name = 'grade_report_show' . $type;
+        $show_pref = get_user_preferences($pref_name, $CFG->$pref_name);
+
+        $strshow = get_string('show' . $type, 'grades');
+        $strhide = get_string('hide' . $type, 'grades');
+
+        $show_hide = 'show';
+        $toggle_action = 1;
+
+        if ($show_pref) {
+            $show_hide = 'hide';
+            $toggle_action = 0;
+        }
+
+        if (array_key_exists($type, $icons)) {
+            $image_name = $icons[$type];
+        } else {
+            $image_name = $type;
+        }
+
+        $string = ${'str' . $show_hide};
+
+        $img = '<img src="'.$CFG->pixpath.'/t/'.$image_name.'.gif" class="iconsmall" alt="'
+                      .$string.'" title="'.$string.'" />'. "\n";
+
+        $retval = '<div class="gradertoggle">' . $img . '<a href="' . $this->baseurl . "&amp;toggle=$toggle_action&amp;toggle_type=$type\">"
+             . $string . '</a></div>';
+
+        if ($return) {
+            return $retval;
+        } else {
+            echo $retval;
+        }
+    }
+
+    /**
+     * Builds and returns the HTML code for the headers.
+     * @return string $headerhtml
+     */
+    function get_headerhtml() {
+        global $CFG, $USER;
+
+        $strsortasc  = get_string('sortasc', 'grades');
+        $strsortdesc = get_string('sortdesc', 'grades');
+        if ($this->sortitemid === 'lastname') {
+            if ($this->sortorder == 'ASC') {
+                $lastarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $lastarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $lastarrow = '';
+        }
+
+        if ($this->sortitemid === 'firstname') {
+            if ($this->sortorder == 'ASC') {
+                $firstarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $firstarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $firstarrow = '';
+        }
+        // Prepare Table Headers
+        $headerhtml = '';
+
+        $numrows = count($this->gtree->levels);
+
+        foreach ($this->gtree->levels as $key=>$row) {
+            if ($key == 0) {
+                // do not diplay course grade category
+                // continue;
+            }
+
+            $headerhtml .= '<tr class="heading">';
+
+            if ($key == $numrows - 1) {
+                $headerhtml .= '<th class="user"><a href="'.$this->baseurl.'&amp;sortitemid=firstname">Firstname</a> ' //TODO: localize
+                            . $firstarrow. '/ <a href="'.$this->baseurl.'&amp;sortitemid=lastname">Lastname </a>'. $lastarrow .'</th>';
+            } else {
+                $headerhtml .= '<td class="topleft">&nbsp;</td>';
+            }
+
+            foreach ($row as $element) {
+                $eid    = $element['eid'];
+                $object = $element['object'];
+                $type   = $element['type'];
+
+                if (!empty($element['colspan'])) {
+                    $colspan = 'colspan="'.$element['colspan'].'"';
+                } else {
+                    $colspan = '';
+                }
+
+                if (!empty($element['depth'])) {
+                    $catlevel = ' catlevel'.$element['depth'];
+                } else {
+                    $catlevel = '';
+                }
+
+
+                if ($type == 'filler' or $type == 'fillerfirst' or $type == 'fillerlast') {
+                    $headerhtml .= '<td class="'.$type.$catlevel.'" '.$colspan.'>&nbsp;</td>';
+                } else if ($type == 'category') {
+                    $headerhtml .= '<td class="category'.$catlevel.'" '.$colspan.'>'.$element['object']->get_name();
+
+                    // Print icons
+                    if ($USER->gradeediting) {
+                        $headerhtml .= $this->get_icons($element);
+                    }
+
+                    $headerhtml .= '</td>';
+                } else {
+                    if ($element['object']->id == $this->sortitemid) {
+                        if ($this->sortorder == 'ASC') {
+                            $arrow = print_arrow('up', $strsortasc, true);
+                        } else {
+                            $arrow = print_arrow('down', $strsortdesc, true);
+                        }
+                    } else {
+                        $arrow = '';
+                    }
+
+                    $dimmed = '';
+                    if ($element['object']->is_hidden()) {
+                        $dimmed = ' dimmed_text ';
+                    }
+
+                    if ($object->itemtype == 'mod') {
+                        $icon = '<img src="'.$CFG->modpixpath.'/'.$object->itemmodule.'/icon.gif" class="icon" alt="'
+                              .get_string('modulename', $object->itemmodule).'"/>';
+                    } else if ($object->itemtype == 'manual') {
+                        //TODO: add manual grading icon
+                        $icon = '<img src="'.$CFG->pixpath.'/t/edit.gif" class="icon" alt="'.get_string('manualgrade', 'grades')
+                              .'"/>';
+                    }
+
+
+                    $headerhtml .= '<th class="'.$type.$catlevel.$dimmed.'"><a href="'.$this->baseurl.'&amp;sortitemid='
+                              . $element['object']->id .'">'. $element['object']->get_name()
+                              . '</a>' . $arrow;
+
+                    $headerhtml .= $this->get_icons($element) . '</th>';
+
+                    $this->items[$element['object']->sortorder] =& $element['object'];
+                }
+
+            }
+
+            $headerhtml .= '</tr>';
+        }
+        return $headerhtml;
+    }
+
+    /**
+     * Builds and return the HTML rows of the table (grades headed by student).
+     * @return string HTML
+     */
+    function get_studentshtml() {
+        global $CFG, $USER;
+        $studentshtml = '';
+        $strfeedback = get_string("feedback");
+
+        foreach ($this->users as $userid => $user) {
+            // Student name and link
+            $studentshtml .= '<tr><th class="user"><a href="' . $CFG->wwwroot . '/user/view.php?id='
+                          . $user->id . '">' . fullname($user) . '</a></th>';
+            foreach ($this->items as $item) {
+
+                if (isset($this->finalgrades[$userid][$item->id])) {
+                    $gradeval = $this->finalgrades[$userid][$item->id]->finalgrade;
+                    $grade = new grade_grades($this->finalgrades[$userid][$item->id], false);
+                    $grade->feedback = $this->finalgrades[$userid][$item->id]->feedback;
+
+                } else {
+                    $gradeval = null;
+                    $grade = new grade_grades(array('userid' => $userid, 'itemid' => $item->id), false);
+                    $grade->feedback = '';
+                }
+
+                if ($grade->is_overridden()) {
+                    $studentshtml .= '<td class="overridden">';
+                } else {
+                    $studentshtml .= '<td>';
+                }
+
+                // emulate grade element
+                $grade->courseid = $this->courseid;
+                $grade->grade_item = $item; // this may speedup is_hidden() and other grade_grades methods
+                $element = array ('eid'=>'g'.$grade->id, 'object'=>$grade, 'type'=>'grade');
+
+                // Do not show any icons if no grade (no record in DB to match)
+                if (!empty($grade->id)) {
+                    $studentshtml .= $this->get_icons($element);
+                }
+
+                // if in editting mode, we need to print either a text box
+                // or a drop down (for scales)
+
+                // grades in item of type grade category or course are not directly editable
+                if ($USER->gradeediting) {
+                    // We need to retrieve each grade_grade object from DB in order to
+                    // know if they are hidden/locked
+
+                    if ($item->scaleid) {
+                        if ($scale = get_record('scale', 'id', $item->scaleid)) {
+                            $scales = explode(",", $scale->scale);
+                            // reindex because scale is off 1
+                            $i = 0;
+                            foreach ($scales as $scaleoption) {
+                                $i++;
+                                $scaleopt[$i] = $scaleoption;
+                            }
+
+                            if ($this->quickgrading) {
+                                $studentshtml .= choose_from_menu($scaleopt, 'grade_'.$userid.'_'.$item->id,
+                                                              $gradeval, get_string('nograde'), '', -1, true);
+                            } elseif ($scale = get_record('scale', 'id', $item->scaleid)) {
+                                $scales = explode(",", $scale->scale);
+
+                                // invalid grade if gradeval < 1
+                                if ((int) $gradeval < 1) {
+                                    $studentshtml .= '-';
+                                } else {
+                                    $studentshtml .= $scales[$gradeval-1];
+                                }
+                            } else {
+                                // no such scale, throw error?
+                            }
+                        }
+                    } else {
+                        if ($this->quickgrading) {
+                            $studentshtml .= '<input size="6" type="text" name="grade_'.$userid.'_'
+                                          .$item->id.'" value="'.get_grade_clean($gradeval).'"/>';
+                        } else {
+                            $studentshtml .= get_grade_clean($gradeval);
+                        }
+                    }
+
+
+                    // If quickfeedback is on, print an input element
+                    if ($this->quickfeedback) {
+                        if ($this->quickgrading) {
+                            $studentshtml .= '<br />';
+                        }
+                        $studentshtml .= '<input size="6" type="text" name="feedback_'.$userid.'_'.$item->id.'" value="'
+                                      . s($grade->feedback) . '"/>';
+                    }
+
+                    $studentshtml .= '<div class="grade_icons">' . $this->get_icons($element, array('edit')) . '</div>';
+                } else {
+                    // If feedback present, surround grade with feedback tooltip
+                    if (!empty($grade->feedback)) {
+                        $studentshtml .= '<span onmouseover="return overlib(\''.$grade->feedback.'\', CAPTION, \''
+                                . $strfeedback.'\');" onmouseout="return nd();">';
+                    }
+
+                    // finalgrades[$userid][$itemid] could be null because of the outer join
+                    // in this case it's different than a 0
+                    if ($item->scaleid) {
+                        if ($scale = get_record('scale', 'id', $item->scaleid)) {
+                            $scales = explode(",", $scale->scale);
+
+                            // invalid grade if gradeval < 1
+                            if ((int) $gradeval < 1) {
+                                $studentshtml .= '-';
+                            } else {
+                                $studentshtml .= $scales[$gradeval-1];
+                            }
+                        } else {
+                            // no such scale, throw error?
+                        }
+                    } else {
+                        if (is_null($gradeval)) {
+                            $studentshtml .= '-';
+                        } else {
+                            $studentshtml .=  get_grade_clean($gradeval);
+                        }
+                    }
+                    if (!empty($grade->feedback)) {
+                        $studentshtml .= '</span>';
+                    }
+                }
+
+                if (!empty($this->gradeserror[$item->id][$userid])) {
+                    $studentshtml .= $this->gradeserror[$item->id][$userid];
+                }
+
+                $studentshtml .=  '</td>' . "\n";
+            }
+            $studentshtml .= '</tr>';
+        }
+        return $studentshtml;
+    }
+
+    /**
+     * Builds and return the HTML rows of the table (grades headed by student).
+     * @return string HTML
+     */
+    function get_groupsumhtml() {
+        global $CFG;
+
+        $groupsumhtml = '';
+
+        if ($this->currentgroup && $this->showgroups) {
+
+        /** SQL for finding group sum */
+            $SQL = "SELECT g.itemid, SUM(g.finalgrade) as sum
+                FROM {$CFG->prefix}grade_items gi LEFT JOIN
+                     {$CFG->prefix}grade_grades g ON gi.id = g.itemid RIGHT OUTER JOIN
+                     {$CFG->prefix}user u ON u.id = g.userid LEFT JOIN
+                     {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                     $this->groupsql
+                WHERE gi.courseid = $this->courseid
+                     $this->groupwheresql
+                AND ra.roleid in ($this->gradebookroles)
+                AND ra.contextid ".get_related_contexts_string($this->context)."
+                GROUP BY g.itemid";
+
+            $groupsum = array();
+            $sums = get_records_sql($SQL);
+            foreach ($sums as $itemid => $csum) {
+                $groupsum[$itemid] = $csum;
+            }
+
+            $groupsumhtml = '<tr><th>Group total</th>';
+            foreach ($this->items as $item) {
+                if (!isset($groupsum[$item->id])) {
+                    $groupsumhtml .= '<td>-</td>';
+                } else {
+                    $sum = $groupsum[$item->id];
+                    $groupsumhtml .= '<td>'.get_grade_clean($sum->sum).'</td>';
+                }
+            }
+            $groupsumhtml .= '</tr>';
+        }
+        return $groupsumhtml;
+    }
+
+    function get_gradesumhtml() {
+        global $CFG;
+
+        $gradesumhtml = '';
+        if ($this->showgrandtotals) {
+
+        /** SQL for finding the SUM grades of all visible users ($CFG->gradebookroles) */
+
+            $SQL = "SELECT g.itemid, SUM(g.finalgrade) as sum
+                FROM {$CFG->prefix}grade_items gi LEFT JOIN
+                     {$CFG->prefix}grade_grades g ON gi.id = g.itemid RIGHT OUTER JOIN
+                     {$CFG->prefix}user u ON u.id = g.userid LEFT JOIN
+                     {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                WHERE gi.courseid = $this->courseid
+                AND ra.roleid in ($this->gradebookroles)
+                AND ra.contextid ".get_related_contexts_string($this->context)."
+                GROUP BY g.itemid";
+
+            $classsum = array();
+            $sums = get_records_sql($SQL);
+            foreach ($sums as $itemid => $csum) {
+                $classsum[$itemid] = $csum;
+            }
+
+            $gradesumhtml = '<tr><th>Total</th>';
+            foreach ($this->items as $item) {
+                if (!isset($classsum[$item->id])) {
+                    $gradesumhtml .= '<td>-</td>';
+                } else {
+                    $sum = $classsum[$item->id];
+                    $gradesumhtml .= '<td>'.get_grade_clean($sum->sum).'</td>';
+                }
+            }
+            $gradesumhtml .= '</tr>';
+        }
+        return $gradesumhtml;
+    }
+
+    function get_scalehtml() {
+        $scalehtml = '';
+        if ($this->showscales) {
+            $scalehtml = '<tr><td>'.get_string('range','grades').'</td>';
+            foreach ($this->items as $item) {
+                $scalehtml .= '<td>'. get_grade_clean($item->grademin).'-'. get_grade_clean($item->grademax).'</td>';
+            }
+            $scalehtml .= '</tr>';
+        }
+        return $scalehtml;
+    }
+
+    /**
+     * Given a grade_category, grade_item or grade_grade, this function
+     * figures out the state of the object and builds then returns a div
+     * with the icons needed for the grader report.
+     *
+     * @param object $object
+     * @param array $icons An array of icon names that this function is explicitly requested to print, regardless of settings
+     * @param bool $limit If true, use the $icons array as the only icons that will be printed. If false, use it to exclude these icons.
+     * @return string HTML
+     */
+    function get_icons($element, $icons=null, $limit=true) {
+        global $CFG;
+        global $USER;
+
+        // Load language strings
+        $stredit           = get_string("edit");
+        $streditcalculation= get_string("editcalculation", 'grades');
+        $strfeedback       = get_string("feedback");
+        $strmove           = get_string("move");
+        $strmoveup         = get_string("moveup");
+        $strmovedown       = get_string("movedown");
+        $strmovehere       = get_string("movehere");
+        $strcancel         = get_string("cancel");
+        $stredit           = get_string("edit");
+        $strdelete         = get_string("delete");
+        $strhide           = get_string("hide");
+        $strshow           = get_string("show");
+        $strlock           = get_string("lock", 'grades');
+        $strswitch_minus   = get_string("contract", 'grades');
+        $strswitch_plus    = get_string("expand", 'grades');
+        $strunlock         = get_string("unlock", 'grades');
+
+        // Prepare container div
+        $html = '<div class="grade_icons">';
+
+        // Prepare reference variables
+        $eid    = $element['eid'];
+        $object = $element['object'];
+        $type   = $element['type'];
+
+        // Add mock attributes in case the object is not of the right type
+        if ($type != 'grade') {
+            $object->feedback = '';
+        }
+
+        // Load user preferences
+        $aggregationview  = get_user_preferences('grade_report_aggregationview', $CFG->grade_report_aggregationview);
+        $showeyecons      = get_user_preferences('grade_report_showeyecons', $CFG->grade_report_showeyecons);
+        $showlocks        = get_user_preferences('grade_report_showlocks', $CFG->grade_report_showlocks);
+        $showcalculations = get_user_preferences('grade_report_showcalculations', $CFG->grade_report_showcalculations);
+
+        // Prepare image strings
+        $edit_category_icon = '<a href="report/grader/edit_category.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
+                            . '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'
+                            . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
+
+        $edit_item_icon = '<a href="report/grader/edit_item.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
+                        . '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'
+                        . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
+        $overlib = '';
+        if (!empty($object->feedback)) {
+            $overlib = 'onmouseover="return overlib(\''.$object->feedback.'\', CAPTION, \''
+                         . $strfeedback.'\');" onmouseout="return nd();"';
+        }
+
+        $edit_grade_icon = '<a href="report/grader/edit_grade.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
+                         . '<img ' . $overlib . ' src="'.$CFG->pixpath.'/t/edit.gif"'
+                         . 'class="iconsmall" alt="' . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
+
+
+        $edit_calculation_icon = '<a href="report/grader/edit_calculation.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
+                               . '<img src="'.$CFG->pixpath.'/t/calc.gif" class="iconsmall" alt="'
+                               . $streditcalculation.'" title="'.$streditcalculation.'" /></a>'. "\n";
+
+        // Prepare Hide/Show icon state
+        $hide_show = 'hide';
+        if ($object->is_hidden()) {
+            $hide_show = 'show';
+        }
+
+        $show_hide_icon = '<a href="report.php?report=grader&amp;target='.$eid
+                        . "&amp;action=$hide_show" . $this->gtree->commonvars . "\">\n"
+                        . '<img src="'.$CFG->pixpath.'/t/'.$hide_show.'.gif" class="iconsmall" alt="'
+                        . ${'str' . $hide_show}.'" title="'.${'str' . $hide_show}.'" /></a>'. "\n";
+
+        // Prepare lock/unlock string
+        $lock_unlock = 'lock';
+        if ($object->is_locked()) {
+            $lock_unlock = 'unlock';
+        }
+
+        // Print lock/unlock icon
+
+        $lock_unlock_icon = '<a href="report.php?report=grader&amp;target='.$eid
+                          . "&amp;action=$lock_unlock" . $this->gtree->commonvars . "\">\n"
+                          . '<img src="'.$CFG->pixpath.'/t/'.$lock_unlock.'.gif" class="iconsmall" alt="'
+                          . ${'str' . $lock_unlock}.'" title="'.${'str' . $lock_unlock}.'" /></a>'. "\n";
+
+        // Prepare expand/contract string
+        $expand_contract = 'switch_minus'; // Default: expanded
+        $state = get_user_preferences('grade_category_' . $object->id, GRADE_CATEGORY_EXPANDED);
+        if ($state == GRADE_CATEGORY_CONTRACTED) {
+            $expand_contract = 'switch_plus';
+        }
+
+        $contract_expand_icon = '<a href="report.php?report=grader&amp;target=' . $eid
+                              . "&amp;action=$expand_contract" . $this->gtree->commonvars . "\">\n"
+                              . '<img src="'.$CFG->pixpath.'/t/'.$expand_contract.'.gif" class="iconsmall" alt="'
+                              . ${'str' . $expand_contract}.'" title="'.${'str' . $expand_contract}.'" /></a>'. "\n";
+
+        // If an array of icon names is given, return only these in the order they are given
+        if (!empty($icons) && is_array($icons)) {
+            $new_html = '';
+
+            foreach ($icons as $icon_name) {
+                if ($icon_name == 'edit') {
+                    $icon_name .= "_$type";
+                }
+                if ($limit) {
+                    $new_html .= ${$icon_name . '_icon'};
+                } else {
+                    ${'show_' . $icon_name} = false;
+                }
+            }
+            if ($limit) {
+                return $new_html;
+            } else {
+                $html .= $new_html;
+            }
+        }
+
+        // Icons shown when edit mode is on
+        if ($USER->gradeediting) {
+            // Edit icon (except for grade_grades)
+            if ($type == 'category') {
+                $html .= $edit_category_icon;
+
+            } else if ($type == 'item' or $type == 'courseitem' or $type == 'categoryitem') {
+                $html .= $edit_item_icon;
+            }
+
+            // Calculation icon for items and categories
+            if ($showcalculations && $type != 'grade') {
+                $html .= $edit_calculation_icon;
+            }
+
+            if ($showeyecons) {
+                $html .= $show_hide_icon;
+            }
+
+            if ($showlocks) {
+                $html .= $lock_unlock_icon;
+            }
+
+            // If object is a category, display expand/contract icon
+            if (get_class($object) == 'grade_category' && $aggregationview == GRADER_REPORT_AGGREGATION_VIEW_COMPACT) {
+                $html .= $contract_expand_icon;
+            }
+        } else { // Editing mode is off
+        }
+
+        return $html . '</div>';
+    }
+}
+?>
index 295405d11d6233a91874cfd0351a76255d3471dc..cc773afd50098ef78d886cfe0fe6bc7682cdc63a 100644 (file)
 
 /// This creates and handles the whole grader report interface, sans header and footer
 
-require_once($CFG->libdir.'/tablelib.php');
-require_once($CFG->libdir.'/gradelib.php');
-require_once($CFG->dirroot.'/grade/report/lib.php');
+require_once($CFG->dirroot.'/grade/report/grader/grader_report.php');
 $gradeserror = array();
 
-/**
-* Shortcut function for printing the grader report toggles.
-* @param string $type The type of toggle
-* @param string $baseurl The base of the URL the toggles will link to
-* @param bool $return Whether to return the HTML string rather than printing it
-* @return void
-*/
-function grader_report_print_toggle($type, $baseurl, $return=false) {
-    global $CFG;
-
-    $icons = array('eyecons' => 'hide',
-                   'calculations' => 'calc',
-                   'locks' => 'lock',
-                   'grandtotals' => 'sigma');
-
-    $pref_name = 'grade_report_show' . $type;
-    $show_pref = get_user_preferences($pref_name, $CFG->$pref_name);
-
-    $strshow = get_string('show' . $type, 'grades');
-    $strhide = get_string('hide' . $type, 'grades');
-
-    $show_hide = 'show';
-    $toggle_action = 1;
-
-    if ($show_pref) {
-        $show_hide = 'hide';
-        $toggle_action = 0;
-    }
-
-    if (array_key_exists($type, $icons)) {
-        $image_name = $icons[$type];
-    } else {
-        $image_name = $type;
-    }
-
-    $string = ${'str' . $show_hide};
-
-    $img = '<img src="'.$CFG->pixpath.'/t/'.$image_name.'.gif" class="iconsmall" alt="'
-                  .$string.'" title="'.$string.'" />'. "\n";
-
-    $retval = '<div class="gradertoggle">' . $img . '<a href="' . $baseurl . "&amp;toggle=$toggle_action&amp;toggle_type=$type\">"
-         . $string . '</a></div>';
-
-    if ($return) {
-        return $retval;
-    } else {
-        echo $retval;
-    }
-}
-
-
-/// processing posted grades & feedback here
-
-if ($data = data_submitted() and confirm_sesskey()) {
-
-    // always initialize all arrays
-    $queue = array();
-
-    foreach ($data as $varname => $postedvalue) {
-        // this is a bit tricky - we have to first load all grades into memory,
-        // check if changed and only then start updating the final grades because
-        // columns might depend one on another - the result would be overriden calculated and category grades
-
-        $needsupdate = false;
-        $note = false; // TODO implement note??
-
-        // skip, not a grade nor feedback
-        $data_type = '';
-        if (strstr($varname, 'grade')) {
-            $data_type = 'grade';
-        } elseif (strstr($varname, 'feedback')) {
-            $data_type = 'feedback';
-        } else {
-            continue;
-        }
-
-        $gradeinfo = explode("_", $varname);
-
-        $userid = clean_param($gradeinfo[1], PARAM_INT);
-        $itemid = clean_param($gradeinfo[2], PARAM_INT);
-
-        if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$course->id))) { // we must verify course id here!
-            error('Incorrect grade item id');
-        }
-
-        // Pre-process grade
-        if ($data_type == 'grade') {
-
-            if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
-                if ($postedvalue == -1) { // -1 means no grade
-                    $finalgrade = null;
-                } else {
-                    $finalgrade = (float)$postedvalue;
-                }
-            } else {
-                if ($postedvalue == '') { // empty string means no grade
-                    $finalgrade = null;
-                } else {
-                    $finalgrade = format_grade($postedvalue);
-                }
-            }
-
-            if (!is_null($finalgrade) and ($finalgrade < $grade_item->grademin or $finalgrade > $grade_item->grademax)) {
-                $gradeserror[$grade_item->id][$userid] = 'outofrange'; //TODO: localize
-                // another possiblity is to use bounded number instead
-                continue;
-            }
-        }
-
-        // Get the grade object to compare old value with new value
-        if ($grade = grade_grades::fetch(array('userid'=>$userid, 'itemid'=>$grade_item->id))) {
-            if ($data_type == 'feedback') {
-                $finalgrade = false;
-                $text = $grade->load_text();
-                if ($text != s($postedvalue)) {
-                    $feedback = s($postedvalue);
-                    $feedbackformat = GRADER_REPORT_FEEDBACK_FORMAT_TEXT;
-                    $needsupdate = true;
-                }
-            } elseif ($data_type == 'grade') {
-                $feedback = false;
-                $feedbackformat = false;
-                if (!is_null($grade->finalgrade)) {
-                    $grade->finalgrade = (float)$grade->finalgrade;
-                }
-                if ($grade->finalgrade === $finalgrade) {
-                    $needsupdate = true;
-                }
-            }
-
-        }
-
-        // we must not update all grades, only changed ones - we do not want to mark everything as overriden
-        if ($needsupdate) {
-            $gradedata = new object();
-            $gradedata->grade_item     = $grade_item;
-            $gradedata->userid         = $userid;
-            $gradedata->note           = $note;
-            $gradedata->finalgrade     = $finalgrade;
-            $gradedata->feedback       = $feedback;
-            $gradedata->feedbackformat = $feedbackformat;
-
-            $queue[] = $gradedata;
-        }
-    }
-
-    // now we update the new final grade for each changed grade
-    foreach ($queue as $gradedata) {
-        $gradedata->grade_item->update_final_grade($gradedata->userid, $gradedata->finalgrade, 'gradebook',
-                                                   $gradedata->note, $gradedata->feedback, $gradedata->feedbackformat);
-    }
-}
-
-// get the params
-$courseid      = required_param('id', PARAM_INT);
-$context       = get_context_instance(CONTEXT_COURSE, $courseid);
+// get the params ($report, $courseid and $context are already set in grade/report.php)
 $page          = optional_param('page', 0, PARAM_INT);
 $sortitemid    = optional_param('sortitemid', 0, PARAM_ALPHANUM); // sort by which grade item
-$report        = optional_param('report', 0, PARAM_ALPHANUM);
 $action        = optional_param('action', 0, PARAM_ALPHA);
 $move          = optional_param('move', 0, PARAM_INT);
 $type          = optional_param('type', 0, PARAM_ALPHA);
 $target        = optional_param('target', 0, PARAM_ALPHANUM);
 $toggle        = optional_param('toggle', NULL, PARAM_INT);
 $toggle_type   = optional_param('toggle_type', 0, PARAM_ALPHANUM);
-
+$db->debug=true;
 // Handle toggle change request
-// TODO print visual feedback
 if (!is_null($toggle) && !empty($toggle_type)) {
     set_user_preferences(array('grade_report_show' . $toggle_type => $toggle));
 }
 
-// Get the user preferences
-$perpage              = get_user_preferences('grade_report_studentsperpage', $CFG->grade_report_studentsperpage); // number of users on a page
-$decimals             = get_user_preferences('grade_report_decimalpoints', $CFG->grade_report_decimalpoints); // decimals in grades
-$showgrandtotals      = get_user_preferences('grade_report_showgrandtotals', $CFG->grade_report_showgrandtotals);
-$showgroups           = get_user_preferences('grade_report_showgroups', $CFG->grade_report_showgroups);
-$aggregation_position = get_user_preferences('grade_report_aggregationposition', $CFG->grade_report_aggregationposition);
-$showscales           = get_user_preferences('grade_report_showscales', $CFG->grade_report_showscales);
-$quickgrading         = get_user_preferences('grade_report_quickgrading', $CFG->grade_report_quickgrading);
-$quickfeedback        = get_user_preferences('grade_report_quickfeedback', $CFG->grade_report_quickfeedback);
+// Initialise the grader report object
+$report = new grade_report_grader($courseid, $context, $page, $sortitemid);
 
-// Override perpage if set in URL
-if ($perpageurl = optional_param('perpage', 0, PARAM_INT)) {
-    $perpage = $perpageurl;
-}
-
-// Prepare language strings
-$strsortasc  = get_string('sortasc', 'grades');
-$strsortdesc = get_string('sortdesc', 'grades');
-$strfeedback = get_string("feedback");
-
-// base url for sorting by first/last name
-$baseurl = 'report.php?id='.$courseid.'&amp;perpage='.$perpage.'&amp;report=grader&amp;page='.$page;
-// base url for paging
-$pbarurl = 'report.php?id='.$courseid.'&amp;perpage='.$perpage.'&amp;report=grader&amp;';
-
-/// setting up groups
-$groupsql = '';
-$groupwheresql = '';
-$group_selector = null;
-$currentgroup = null;
-
-if ($showgroups) {
-    /// find out current groups mode
-    $course = get_record('course', 'id', $courseid);
-    $groupmode = $course->groupmode;
-    ob_start();
-    $currentgroup = setup_and_print_groups($course, $groupmode, $baseurl);
-    $group_selector = ob_get_clean();
-
-    // update paging after group
-    $baseurl .= 'group='.$currentgroup.'&amp;';
-    $pbarurl .= 'group='.$currentgroup.'&amp;';
-
-    if ($currentgroup) {
-        $groupsql = " LEFT JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id ";
-        $groupwheresql = " AND gm.groupid = $currentgroup ";
-    }
+/// processing posted grades & feedback here
+if ($data = data_submitted() and confirm_sesskey()) {
+    $report->process_data($data);
 }
 
-// Grab the grade_tree for this course
-$gtree = new grade_tree($courseid, true, false, $aggregation_position);
-
-// setting the sort order, this depends on last state
-// all this should be in the new table class that we might need to use
-// for displaying grades
-
-// already in not requesting sort, i.e. normal paging
-
-if ($sortitemid) {
-    if (!isset($SESSION->gradeuserreport->sort)) {
-        $sortorder = $SESSION->gradeuserreport->sort = 'ASC';
-    } else {
-        // this is the first sort, i.e. by last name
-        if (!isset($SESSION->gradeuserreport->sortitemid)) {
-            $sortorder = $SESSION->gradeuserreport->sort = 'ASC';
-        } else if ($SESSION->gradeuserreport->sortitemid == $sortitemid) {
-            // same as last sort
-            if ($SESSION->gradeuserreport->sort == 'ASC') {
-                $sortorder = $SESSION->gradeuserreport->sort = 'DESC';
-            } else {
-                $sortorder = $SESSION->gradeuserreport->sort = 'ASC';
-            }
-        } else {
-            $sortorder = $SESSION->gradeuserreport->sort = 'ASC';
-        }
-    }
-    $SESSION->gradeuserreport->sortitemid = $sortitemid;
-} else {
-    // not requesting sort, use last setting (for paging)
-
-    if (isset($SESSION->gradeuserreport->sortitemid)) {
-        $sortitemid = $SESSION->gradeuserreport->sortitemid;
-    }
-    if (isset($SESSION->gradeuserreport->sort)) {
-        $sortorder = $SESSION->gradeuserreport->sort;
-    } else {
-        $sortorder = 'ASC';
-    }
+// Override perpage if set in URL
+if ($perpageurl = optional_param('perpage', 0, PARAM_INT)) {
+    $report->studentsperpage = $perpageurl;
 }
 
-/// end of setting sort order code
-
 // Perform actions on categories, items and grades
 if (!empty($target) && !empty($action) && confirm_sesskey()) {
-
-    $element = $gtree->locate_element($target);
-
-    switch ($action) {
-        case 'edit':
-            break;
-        case 'delete':
-            if ($confirm == 1) { // Perform the deletion
-                //TODO: add proper delete support for grade items and categories
-                //$element['object']->delete();
-                // Print result message
-
-            } else { // Print confirmation dialog
-                $eid = $element['eid'];
-                $strdeletecheckfull = get_string('deletecheck', '', $element['object']->get_name());
-                $linkyes = "category.php?target=$eid&amp;action=delete&amp;confirm=1$gtree->commonvars";
-                $linkno = "category.php?$gtree->commonvars";
-                notice_yesno($strdeletecheckfull, $linkyes, $linkno);
-            }
-            break;
-
-        case 'hide':
-        // TODO Implement calendar for selection of a date to hide element until
-            $element['object']->set_hidden(1);
-            $gtree = new grade_tree($courseid);
-            break;
-        case 'show':
-            $element['object']->set_hidden(0);
-            $gtree = new grade_tree($courseid);
-            break;
-        case 'lock':
-        // TODO Implement calendar for selection of a date to lock element after
-            if (!$element['object']->set_locked(1)) {
-                debugging("Could not update the element's locked state!");
-            }
-            $gtree = new grade_tree($courseid);
-            break;
-        case 'unlock':
-            if (!$element['object']->set_locked(0)) {
-                debugging("Could not update the element's locked state!");
-            }
-            $gtree = new grade_tree($courseid);
-            break;
-        default:
-            break;
-    }
+    $report->process_action($target, $action);
 }
 
 // first make sure we have all final grades
 // TODO: check that no grade_item has needsupdate set
 grade_regrade_final_grades($courseid);
 
-// roles to be displaye in the gradebook
-$gradebookroles = $CFG->gradebookroles;
-
-/*
-* pulls out the userids of the users to be display, and sort them
-* the right outer join is needed because potentially, it is possible not
-* to have the corresponding entry in grade_grades table for some users
-* this is check for user roles because there could be some users with grades
-* but not supposed to be displayed
-*/
-if (is_numeric($sortitemid)) {
-    $sql = "SELECT u.id, u.firstname, u.lastname
-            FROM {$CFG->prefix}grade_grades g RIGHT OUTER JOIN
-                 {$CFG->prefix}user u ON (u.id = g.userid AND g.itemid = $sortitemid)
-                 LEFT JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
-                 $groupsql
-            WHERE ra.roleid in ($gradebookroles)
-                 $groupwheresql
-            AND ra.contextid ".get_related_contexts_string($context)."
-            ORDER BY g.finalgrade $sortorder";
-    $users = get_records_sql($sql, $perpage * $page, $perpage);
-} else {
-    // default sort
-    // get users sorted by lastname
-    $users = get_role_users(@implode(',', $CFG->gradebookroles), $context, false, 'u.id, u.firstname, u.lastname', 'u.'.$sortitemid .' '. $sortorder, false, $page * $perpage, $perpage, $currentgroup);
-    // need to cut users down by groups
-
-}
-
-/// count total records for paging
-
-$countsql = "SELECT COUNT(DISTINCT u.id)
-            FROM {$CFG->prefix}grade_grades g RIGHT OUTER JOIN
-                 {$CFG->prefix}user u ON (u.id = g.userid AND g.itemid = $sortitemid)
-                 LEFT JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
-                 $groupsql
-            WHERE ra.roleid in ($gradebookroles)
-                 $groupwheresql
-            AND ra.contextid ".get_related_contexts_string($context);
-$numusers = count_records_sql($countsql);
-
-// print_object($users); // debug
-
-if (empty($users)) {
-    $userselect = '';
-    $users = array();
-} else {
-    $userselect = 'AND g.userid in ('.implode(',', array_keys($users)).')';
-}
-
-
-// phase 2 sql, we supply the userids in this query, and get all the grades
-// pulls out all the grades, this does not need to worry about paging
-$sql = "SELECT g.id, g.itemid, g.userid, g.finalgrade, g.hidden, g.locked, g.locktime, g.overridden, gt.feedback
-        FROM  {$CFG->prefix}grade_items gi,
-              {$CFG->prefix}grade_grades g
-        LEFT JOIN {$CFG->prefix}grade_grades_text gt ON g.id = gt.gradeid
-        WHERE g.itemid = gi.id
-        AND gi.courseid = $courseid $userselect";
-
-///print_object($grades); //debug
-
-$finalgrades = array();
-// needs to be formatted into an array for easy retrival
-
-if ($grades = get_records_sql($sql)) {
-    foreach ($grades as $grade) {
-        $finalgrades[$grade->userid][$grade->itemid] = $grade;
-    }
-}
-
-/// With the users in an sorted array and grades fetched, we can not print the main html table
+$report->load_users();
+$numusers = $report->get_numusers();
+$report->load_final_grades();
 
-// 1. Fetch all top-level categories for this course, with all children preloaded, sorted by sortorder
-
-    // Fetch array of students enroled in this course
-if (!$context = get_context_instance(CONTEXT_COURSE, $gtree->courseid)) {
+if (!$context = get_context_instance(CONTEXT_COURSE, $report->gtree->courseid)) {
     return false;
 }
-//$users = get_role_users(@implode(',', $CFG->gradebookroles), $context);
-
-if ($sortitemid === 'lastname') {
-    if ($sortorder == 'ASC') {
-        $lastarrow = print_arrow('up', $strsortasc, true);
-    } else {
-        $lastarrow = print_arrow('down', $strsortdesc, true);
-    }
-} else {
-    $lastarrow = '';
-}
-
-if ($sortitemid === 'firstname') {
-    if ($sortorder == 'ASC') {
-        $firstarrow = print_arrow('up', $strsortasc, true);
-    } else {
-        $firstarrow = print_arrow('down', $strsortdesc, true);
-    }
-} else {
-    $firstarrow = '';
-}
-
-/********* BEGIN OUTPUT *********/
 
 print_heading('Grader Report');
 
@@ -434,333 +56,18 @@ print_heading('Grader Report');
 $currenttab = 'graderreport';
 include('tabs.php');
 
-// Group selection drop-down
-echo $group_selector;
-
-// Show/hide toggles
-echo '<div id="grade-report-toggles">';
-if ($USER->gradeediting) {
-    grader_report_print_toggle('eyecons', $baseurl);
-    grader_report_print_toggle('locks', $baseurl);
-    grader_report_print_toggle('calculations', $baseurl);
-}
-
-grader_report_print_toggle('grandtotals', $baseurl);
-grader_report_print_toggle('groups', $baseurl);
-grader_report_print_toggle('scales', $baseurl);
-echo '</div>';
-
-// Paging bar
-print_paging_bar($numusers, $page, $perpage, $pbarurl);
-
-$items = array();
-
-// Prepare Table Headers
-$headerhtml = '';
-
-$numrows = count($gtree->levels);
-
-foreach ($gtree->levels as $key=>$row) {
-    if ($key == 0) {
-        // do not diplay course grade category
-        // continue;
-    }
-
-    $headerhtml .= '<tr class="heading">';
-
-    if ($key == $numrows - 1) {
-        $headerhtml .= '<th class="user"><a href="'.$baseurl.'&amp;sortitemid=firstname">Firstname</a> ' //TODO: localize
-                    . $firstarrow. '/ <a href="'.$baseurl.'&amp;sortitemid=lastname">Lastname </a>'. $lastarrow .'</th>';
-    } else {
-        $headerhtml .= '<td class="topleft">&nbsp;</td>';
-    }
-
-    foreach ($row as $element) {
-        $eid    = $element['eid'];
-        $object = $element['object'];
-        $type   = $element['type'];
-
-        if (!empty($element['colspan'])) {
-            $colspan = 'colspan="'.$element['colspan'].'"';
-        } else {
-            $colspan = '';
-        }
-
-        if (!empty($element['depth'])) {
-            $catlevel = ' catlevel'.$element['depth'];
-        } else {
-            $catlevel = '';
-        }
-
-
-        if ($type == 'filler' or $type == 'fillerfirst' or $type == 'fillerlast') {
-            $headerhtml .= '<td class="'.$type.$catlevel.'" '.$colspan.'>&nbsp;</td>';
-        } else if ($type == 'category') {
-            $headerhtml .= '<td class="category'.$catlevel.'" '.$colspan.'>'.$element['object']->get_name();
-
-            // Print icons
-            if ($USER->gradeediting) {
-                $headerhtml .= grade_get_icons($element, $gtree);
-            }
-
-            $headerhtml .= '</td>';
-        } else {
-            if ($element['object']->id == $sortitemid) {
-                if ($sortorder == 'ASC') {
-                    $arrow = print_arrow('up', $strsortasc, true);
-                } else {
-                    $arrow = print_arrow('down', $strsortdesc, true);
-                }
-            } else {
-                $arrow = '';
-            }
-
-            $dimmed = '';
-            if ($element['object']->is_hidden()) {
-                $dimmed = ' dimmed_text ';
-            }
-
-            if ($object->itemtype == 'mod') {
-                $icon = '<img src="'.$CFG->modpixpath.'/'.$object->itemmodule.'/icon.gif" class="icon" alt="'
-                      .get_string('modulename', $object->itemmodule).'"/>';
-            } else if ($object->itemtype == 'manual') {
-                //TODO: add manual grading icon
-                $icon = '<img src="'.$CFG->pixpath.'/t/edit.gif" class="icon" alt="'.get_string('manualgrade', 'grades')
-                      .'"/>';
-            }
-
-
-            $headerhtml .= '<th class="'.$type.$catlevel.$dimmed.'"><a href="'.$baseurl.'&amp;sortitemid='
-                      . $element['object']->id .'">'. $element['object']->get_name()
-                      . '</a>' . $arrow;
-
-            $headerhtml .= grade_get_icons($element, $gtree) . '</th>';
-
-            $items[$element['object']->sortorder] =& $element['object'];
-        }
-
-    }
-
-    $headerhtml .= '</tr>';
-}
-
-// Prepare Table Rows
-$studentshtml = '';
-
-foreach ($users as $userid => $user) {
-    // Student name and link
-    $studentshtml .= '<tr><th class="user"><a href="' . $CFG->wwwroot . '/user/view.php?id='
-                  . $user->id . '">' . fullname($user) . '</a></th>';
-    foreach ($items as $item) {
-
-        if (isset($finalgrades[$userid][$item->id])) {
-            $gradeval = $finalgrades[$userid][$item->id]->finalgrade;
-            $grade = new grade_grades($finalgrades[$userid][$item->id], false);
-            $grade->feedback = $finalgrades[$userid][$item->id]->feedback;
-
-        } else {
-            $gradeval = null;
-            $grade = new grade_grades(array('userid' => $userid, 'itemid' => $item->id), false);
-            $grade->feedback = '';
-        }
-
-        if ($grade->is_overridden()) {
-            $studentshtml .= '<td class="overridden">';
-        } else {
-            $studentshtml .= '<td>';
-        }
-
-        // Do not show any icons if no grade (no record in DB to match)
-        if (!empty($grade->id)) {
-            // emulate grade element
-            $grade->courseid = $course->id;
-            $grade->grade_item = $item; // this may speedup is_hidden() and other grade_grades methods
-            $element = array ('eid'=>'g'.$grade->id, 'object'=>$grade, 'type'=>'grade');
-            $studentshtml .= grade_get_icons($element, $gtree);
-        }
-
-
-        // if in editting mode, we need to print either a text box
-        // or a drop down (for scales)
-
-        // grades in item of type grade category or course are not directly editable
-        if ($USER->gradeediting) {
-            // We need to retrieve each grade_grade object from DB in order to
-            // know if they are hidden/locked
-
-            if ($item->scaleid) {
-                if ($scale = get_record('scale', 'id', $item->scaleid)) {
-                    $scales = explode(",", $scale->scale);
-                    // reindex because scale is off 1
-                    $i = 0;
-                    foreach ($scales as $scaleoption) {
-                        $i++;
-                        $scaleopt[$i] = $scaleoption;
-                    }
-
-                    if ($quickgrading) {
-                        $studentshtml .= choose_from_menu($scaleopt, 'grade_'.$userid.'_'.$item->id,
-                                                      $gradeval, get_string('nograde'), '', -1, true);
-                    } elseif ($scale = get_record('scale', 'id', $item->scaleid)) {
-                        $scales = explode(",", $scale->scale);
-
-                        // invalid grade if gradeval < 1
-                        if ((int) $gradeval < 1) {
-                            $studentshtml .= '-';
-                        } else {
-                            $studentshtml .= $scales[$gradeval-1];
-                        }
-                    } else {
-                        // no such scale, throw error?
-                    }
-                }
-            } else {
-                if ($quickgrading) {
-                    $studentshtml .= '<input size="6" type="text" name="grade_'.$userid.'_'.$item->id.'" value="'.get_grade_clean($gradeval).'"/>';
-                } else {
-                    $studentshtml .= get_grade_clean($gradeval);
-                }
-            }
-
-
-            // If quickfeedback is on, print an input element
-            if ($quickfeedback) {
-                $studentshtml .= '<input size="6" type="text" name="feedback_'.$userid.'_'.$item->id.'" value="'. s($grade->feedback) . '"/>';
-            }
-
-            $studentshtml .= '<div class="grade_icons">' . grade_get_icons($element, $gtree, array('edit')) . '</div>';
-        } else {
-            // If feedback present, surround grade with feedback tooltip
-            if (!empty($grade->feedback)) {
-                $studentshtml .= '<span onmouseover="return overlib(\''.$grade->feedback.'\', CAPTION, \''
-                        . $strfeedback.'\');" onmouseout="return nd();">';
-            }
-
-            // finalgrades[$userid][$itemid] could be null because of the outer join
-            // in this case it's different than a 0
-            if ($item->scaleid) {
-                if ($scale = get_record('scale', 'id', $item->scaleid)) {
-                    $scales = explode(",", $scale->scale);
-
-                    // invalid grade if gradeval < 1
-                    if ((int) $gradeval < 1) {
-                        $studentshtml .= '-';
-                    } else {
-                        $studentshtml .= $scales[$gradeval-1];
-                    }
-                } else {
-                    // no such scale, throw error?
-                }
-            } else {
-                if (is_null($gradeval)) {
-                    $studentshtml .= '-';
-                } else {
-                    $studentshtml .=  get_grade_clean($gradeval);
-                }
-            }
-            if (!empty($grade->feedback)) {
-                $studentshtml .= '</span>';
-            }
-        }
-
-        if (!empty($gradeserror[$item->id][$userid])) {
-            $studentshtml .= $gradeserror[$item->id][$userid];
-        }
-
-        $studentshtml .=  '</td>' . "\n";
-    }
-    $studentshtml .= '</tr>';
-}
-
-// if user preference to display group sum
-$groupsumhtml = '';
-
-if ($currentgroup && $showgroups) {
-
-/** SQL for finding group sum */
-    $SQL = "SELECT g.itemid, SUM(g.finalgrade) as sum
-        FROM {$CFG->prefix}grade_items gi LEFT JOIN
-             {$CFG->prefix}grade_grades g ON gi.id = g.itemid RIGHT OUTER JOIN
-             {$CFG->prefix}user u ON u.id = g.userid LEFT JOIN
-             {$CFG->prefix}role_assignments ra ON u.id = ra.userid
-             $groupsql
-        WHERE gi.courseid = $courseid
-             $groupwheresql
-        AND ra.roleid in ($gradebookroles)
-        AND ra.contextid ".get_related_contexts_string($context)."
-        GROUP BY g.itemid";
-
-    $groupsum = array();
-    $sums = get_records_sql($SQL);
-    foreach ($sums as $itemid => $csum) {
-        $groupsum[$itemid] = $csum;
-    }
-
-    $groupsumhtml = '<tr><th>Group total</th>';
-    foreach ($items as $item) {
-        if (!isset($groupsum[$item->id])) {
-            $groupsumhtml .= '<td>-</td>';
-        } else {
-            $sum = $groupsum[$item->id];
-            $groupsumhtml .= '<td>'.get_grade_clean($sum->sum).'</td>';
-        }
-    }
-    $groupsumhtml .= '</tr>';
-}
-
-// Grand totals
-$gradesumhtml = '';
-if ($showgrandtotals) {
-
-/** SQL for finding the SUM grades of all visible users ($CFG->gradebookroles) */
-
-    $SQL = "SELECT g.itemid, SUM(g.finalgrade) as sum
-        FROM {$CFG->prefix}grade_items gi LEFT JOIN
-             {$CFG->prefix}grade_grades g ON gi.id = g.itemid RIGHT OUTER JOIN
-             {$CFG->prefix}user u ON u.id = g.userid LEFT JOIN
-             {$CFG->prefix}role_assignments ra ON u.id = ra.userid
-        WHERE gi.courseid = $courseid
-        AND ra.roleid in ($gradebookroles)
-        AND ra.contextid ".get_related_contexts_string($context)."
-        GROUP BY g.itemid";
-
-    $classsum = array();
-    $sums = get_records_sql($SQL);
-    foreach ($sums as $itemid => $csum) {
-        $classsum[$itemid] = $csum;
-    }
-
-    $gradesumhtml = '<tr><th>Total</th>';
-    foreach ($items as $item) {
-        if (!isset($classsum[$item->id])) {
-            $gradesumhtml .= '<td>-</td>';
-        } else {
-            $sum = $classsum[$item->id];
-            $gradesumhtml .= '<td>'.get_grade_clean($sum->sum).'</td>';
-        }
-    }
-    $gradesumhtml .= '</tr>';
-}
-
-// finding the ranges of each gradeitem
-$scalehtml = '';
-if ($showscales) {
-    $scalehtml = '<tr><td>'.get_string('range','grades').'</td>';
-    foreach ($items as $item) {
-        $scalehtml .= '<td>'. get_grade_clean($item->grademin).'-'. get_grade_clean($item->grademax).'</td>';
-    }
-    $scalehtml .= '</tr>';
-}
-
-echo "<br/>";
-
-$reporthtml = "<table class=\"boxaligncenter\">$headerhtml";
-$reporthtml .= $scalehtml;
-$reporthtml .= $studentshtml;
-$reporthtml .= $groupsumhtml;
-$reporthtml .= $gradesumhtml;
+echo $report->group_selector;
+echo $report->get_toggles_html();
+print_paging_bar($numusers, $report->page, $report->studentsperpage, $report->pbarurl);
+echo '<br />';
+
+$reporthtml = '<table class="boxaligncenter">';
+$reporthtml .= $report->get_headerhtml();
+$reporthtml .= $report->get_scalehtml();
+$reporthtml .= $report->get_studentshtml();
+$reporthtml .= $report->get_groupsumhtml();
+$reporthtml .= $report->get_gradesumhtml();
 $reporthtml .= "</table>";
-
 // print submit button
 if ($USER->gradeediting) {
     echo '<form action="report.php" method="post">';
@@ -773,13 +80,13 @@ if ($USER->gradeediting) {
 echo $reporthtml;
 
 // print submit button
-if ($USER->gradeediting && ($quickfeedback || $quickgrading)) {
+if ($USER->gradeediting && ($report->quickfeedback || $report->quickgrading)) {
     echo '<div class="submit"><input type="submit" value="'.get_string('update').'" /></div>';
     echo '</div></form>';
 }
 
 // prints paging bar at bottom for large pages
-if ($perpage >= 20) {
-    print_paging_bar($numusers, $page, $perpage, $pbarurl);
+if ($report->studentsperpage >= 20) {
+    print_paging_bar($numusers, $report->page, $report->studentsperpage, $report->pbarurl);
 }
 ?>
index 7a2b18a0bef220a39f7a0ac8bda15ab1dd62d294..da703aa05334324d18d7ca728eece7b74ba0b9f0 100644 (file)
@@ -64,16 +64,6 @@ define('GRADE_HISTORY_INSERT', 1);
 define('GRADE_HISTORY_UPDATE', 2);
 define('GRADE_HISTORY_DELETE', 3);
 
-// Set up constants for report preferences
-define('GRADER_REPORT_AGGREGATION_POSITION_LEFT', 0);
-define('GRADER_REPORT_AGGREGATION_POSITION_RIGHT', 1);
-define('GRADER_REPORT_AGGREGATION_VIEW_FULL', 0);
-define('GRADER_REPORT_AGGREGATION_VIEW_COMPACT', 1);
-define('GRADER_REPORT_GRADE_DISPLAY_TYPE_RAW', 0);
-define('GRADER_REPORT_GRADE_DISPLAY_TYPE_PERCENTAGE', 1);
-define('GRADER_REPORT_FEEDBACK_FORMAT_TEXT', 0);
-define('GRADER_REPORT_FEEDBACK_FORMAT_HTML', 1);
-
 
 require_once($CFG->libdir . '/grade/grade_category.php');
 require_once($CFG->libdir . '/grade/grade_item.php');
@@ -704,170 +694,4 @@ function grade_oldgradebook_upgrade($courseid) {
     }
 }
 
-/**
- * Given a grade_category, grade_item or grade_grade, this function
- * figures out the state of the object and builds then returns a div
- * with the icons needed for the grader report.
- *
- * @param object $object
- * @param object $tree (A complete grade_tree object)
- * @param array $icons An array of icon names that this function is explicitly requested to print, regardless of settings
- * @param bool $limit If true, use the $icons array as the only icons that will be printed. If false, use it to exclude these icons.
- * @return string HTML
- */
-function grade_get_icons($element, $tree, $icons=null, $limit=true) {
-    global $CFG;
-    global $USER;
-
-
-    // Load language strings
-    $stredit           = get_string("edit");
-    $streditcalculation= get_string("editcalculation", 'grades');
-    $strfeedback       = get_string("feedback");
-    $strmove           = get_string("move");
-    $strmoveup         = get_string("moveup");
-    $strmovedown       = get_string("movedown");
-    $strmovehere       = get_string("movehere");
-    $strcancel         = get_string("cancel");
-    $stredit           = get_string("edit");
-    $strdelete         = get_string("delete");
-    $strhide           = get_string("hide");
-    $strshow           = get_string("show");
-    $strlock           = get_string("lock", 'grades');
-    $strswitch_minus   = get_string("contract", 'grades');
-    $strswitch_plus    = get_string("expand", 'grades');
-    $strunlock         = get_string("unlock", 'grades');
-
-    // Prepare container div
-    $html = '<div class="grade_icons">';
-
-    // Prepare reference variables
-    $eid    = $element['eid'];
-    $object = $element['object'];
-    $type   = $element['type'];
-
-    // Add mock attributes in case the object is not of the right type
-    if ($type != 'grade') {
-        $object->feedback = '';
-    }
-
-    // Load user preferences
-    $aggregationview  = get_user_preferences('grade_report_aggregationview', $CFG->grade_report_aggregationview);
-    $showeyecons      = get_user_preferences('grade_report_showeyecons', $CFG->grade_report_showeyecons);
-    $showlocks        = get_user_preferences('grade_report_showlocks', $CFG->grade_report_showlocks);
-    $showcalculations = get_user_preferences('grade_report_showcalculations', $CFG->grade_report_showcalculations);
-
-    // Prepare image strings
-    $edit_category_icon = '<a href="report/grader/edit_category.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
-                        . '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'
-                        . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
-
-    $edit_item_icon = '<a href="report/grader/edit_item.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
-                    . '<img src="'.$CFG->pixpath.'/t/edit.gif" class="iconsmall" alt="'
-                    . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
-    $overlib = '';
-    if (!empty($object->feedback)) {
-        $overlib = 'onmouseover="return overlib(\''.$object->feedback.'\', CAPTION, \''
-                     . $strfeedback.'\');" onmouseout="return nd();"';
-    }
-
-    $edit_grade_icon = '<a href="report/grader/edit_grade.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
-                     . '<img ' . $overlib . ' src="'.$CFG->pixpath.'/t/edit.gif"'
-                     . 'class="iconsmall" alt="' . $stredit.'" title="'.$stredit.'" /></a>'. "\n";
-
-
-    $edit_calculation_icon = '<a href="report/grader/edit_calculation.php?courseid='.$object->courseid.'&amp;id='.$object->id.'">'
-                           . '<img src="'.$CFG->pixpath.'/t/calc.gif" class="iconsmall" alt="'
-                           . $streditcalculation.'" title="'.$streditcalculation.'" /></a>'. "\n";
-
-    // Prepare Hide/Show icon state
-    $hide_show = 'hide';
-    if ($object->is_hidden()) {
-        $hide_show = 'show';
-    }
-
-    $show_hide_icon = '<a href="report.php?report=grader&amp;target='.$eid
-                    . "&amp;action=$hide_show$tree->commonvars\">\n"
-                    . '<img src="'.$CFG->pixpath.'/t/'.$hide_show.'.gif" class="iconsmall" alt="'
-                    . ${'str' . $hide_show}.'" title="'.${'str' . $hide_show}.'" /></a>'. "\n";
-
-    // Prepare lock/unlock string
-    $lock_unlock = 'lock';
-    if ($object->is_locked()) {
-        $lock_unlock = 'unlock';
-    }
-
-    // Print lock/unlock icon
-
-    $lock_unlock_icon = '<a href="report.php?report=grader&amp;target='.$eid
-                      . "&amp;action=$lock_unlock$tree->commonvars\">\n"
-                      . '<img src="'.$CFG->pixpath.'/t/'.$lock_unlock.'.gif" class="iconsmall" alt="'
-                      . ${'str' . $lock_unlock}.'" title="'.${'str' . $lock_unlock}.'" /></a>'. "\n";
-
-    // Prepare expand/contract string
-    $expand_contract = 'switch_minus'; // Default: expanded
-    $state = get_user_preferences('grade_category_' . $object->id, GRADE_CATEGORY_EXPANDED);
-    if ($state == GRADE_CATEGORY_CONTRACTED) {
-        $expand_contract = 'switch_plus';
-    }
-
-    $contract_expand_icon = '<a href="report.php?report=grader&amp;target=' . $eid
-                          . "&amp;action=$expand_contract$tree->commonvars\">\n"
-                          . '<img src="'.$CFG->pixpath.'/t/'.$expand_contract.'.gif" class="iconsmall" alt="'
-                          . ${'str' . $expand_contract}.'" title="'.${'str' . $expand_contract}.'" /></a>'. "\n";
-
-    // If an array of icon names is given, return only these in the order they are given
-    if (!empty($icons) && is_array($icons)) {
-        $new_html = '';
-
-        foreach ($icons as $icon_name) {
-            if ($icon_name == 'edit') {
-                $icon_name .= "_$type";
-            }
-            if ($limit) {
-                $new_html .= ${$icon_name . '_icon'};
-            } else {
-                ${'show_' . $icon_name} = false;
-            }
-        }
-        if ($limit) {
-            return $new_html;
-        } else {
-            $html .= $new_html;
-        }
-    }
-
-    // Icons shown when edit mode is on
-    if ($USER->gradeediting) {
-        // Edit icon (except for grade_grades)
-        if ($type == 'category') {
-            $html .= $edit_category_icon;
-
-        } else if ($type == 'item' or $type == 'courseitem' or $type == 'categoryitem') {
-            $html .= $edit_item_icon;
-        }
-
-        // Calculation icon for items and categories
-        if ($showcalculations && $type != 'grade') {
-            $html .= $edit_calculation_icon;
-        }
-
-        if ($showeyecons) {
-            $html .= $show_hide_icon;
-        }
-
-        if ($showlocks) {
-            $html .= $lock_unlock_icon;
-        }
-
-        // If object is a category, display expand/contract icon
-        if (get_class($object) == 'grade_category' && $aggregationview == GRADER_REPORT_AGGREGATION_VIEW_COMPACT) {
-            $html .= $contract_expand_icon;
-        }
-    } else { // Editing mode is off
-    }
-
-    return $html . '</div>';
-}
-
 ?>
index a21a35ee864c21282715879595430534f2b71ead..b4f1af7c13749bdf64d324529e2ced2dd30a4192 100644 (file)
@@ -3748,7 +3748,7 @@ has_capability('moodle/course:viewhiddenuserfields', $context)) {
     if (has_capability('moodle/notes:manage', $context) || has_capability('moodle/notes:view', $context)) {
         $output .= '<a href="'.$CFG->wwwroot.'/notes/index.php?course=' . $course->id. '&amp;user='.$user->id.'">'.get_string('notes','notes').'</a><br />';
     }
-    
+
     if (has_capability('moodle/site:viewreports', $context)) {
         $timemidnight = usergetmidnight(time());
         $output .= '<a href="'. $CFG->wwwroot .'/course/user.php?id='. $course->id .'&amp;user='. $user->id .'">'. $string->activity .'</a><br />';
@@ -6291,7 +6291,7 @@ function print_location_comment($file, $line, $return = false)
 }
 
 
-/** 
+/**
  * Returns an image of an up or down arrow, used for column sorting. To avoid unnecessary DB accesses, please
  * provide this function with the language strings for sortasc and sortdesc.
  * If no sort string is associated with the direction, an arrow with no alt text will be printed/returned.
@@ -6299,17 +6299,17 @@ function print_location_comment($file, $line, $return = false)
  * @param string $strsort The language string used for the alt attribute of this image
  * @param bool $return Whether to print directly or return the html string
  * @return string HTML for the image
- * 
+ *
  * TODO See if this isn't already defined somewhere. If not, move this to weblib
  */
 function print_arrow($direction='up', $strsort=null, $return=false) {
     global $CFG;
-    
+
     if (!in_array($direction, array('up', 'down', 'right', 'left'))) {
         return null;
     }
-    
-    $return = null; 
+
+    $return = null;
 
     switch ($direction) {
         case 'up':