dirroot . '/grade/report/lib.php'); require_once($CFG->libdir.'/tablelib.php'); foreach (glob($CFG->dirroot . '/grade/report/visual/visualizations/visual_*.php') as $filename) { require_once($filename); } class grade_report_visual extends grade_report { /** * Capability to view hidden items. * TODO: Add a check for hidden items and grades. * @var bool $canviewhidden */ public $canviewhidden; public $nullgradesasmin = false; private static $visualizations = array(); /** * Grade objects of users in the course * @var array $grades */ public $grades = array(); private $visdata = array(); private $visid = 'grades_vs_students'; private $flashvars = array(); private $flashvarshtml; /** * The html of the report to output. * @var string $html */ public $html; /** * Constructor. Initialises grade_tree, sets up group, baseurl * and pbarurl. * @param int $courseid the coures id for the report * @param object $gpr grade plugin tracking object * @context string $context */ public function __construct($courseid, $gpr, $context, $visid=null) { global $CFG; parent::__construct($courseid, $gpr, $context, null); $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->course->id)); if(!is_null($visid)) { $this->visid = $visid; } /// Set up urls $this->baseurl = 'index.php?id=' . $this->courseid; $this->pbarurl = 'index.php?id=' . $this->courseid; /// Build grade tree $this->gtree = new grade_tree($this->courseid, false); $this->load_visualizations(); $this->set_up_flashvars(); /// Set up Groups if($visid && grade_report_visual::get_visualization($visid)->usegroups) { $this->setup_groups(); } } /// Added to keep grade_report happy public function process_data($data){} public function process_action($target, $action){} /** * Load all the visualization classes into $visualizations. * Looks in /visualizations and trys to make an instence of any * class that is in a file that starts with visual_ and extends * visualization directly. * @param bool $return if true return visualizations array, else store in $this->visualizations * @returns array array of clases that extend visualization */ private function load_visualizations($return=false) { global $CFG; if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations)) { $visualizations = array(); foreach (glob($CFG->dirroot . '/grade/report/visual/visualizations/visual_*.php') as $path) { $filename = substr(basename($path, '.php'), 7); if(class_exists($filename) && get_parent_class($class = new $filename) == 'visualization' ) { $visualizations[$filename] = $class; } } if($return) { return $visualizations; } else { grade_report_visual::$visualizations = $visualizations; } } else if($return) { return grade_report_visual::$visualizations; } } /** * Returns the current visualizations being used in the report * or if none are set, it returns the them as whould be loaded * by load_visualizations. * @returns array array of classes that extend visualization */ public function get_visualizations() { if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations)) { return grade_report_visual::load_visualizations(true); } else { return grade_report_visual::$visualizations; } } public function get_visualization($filename) { if(!isset(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations) || empty(grade_report_visual::$visualizations) || is_null(grade_report_visual::$visualizations[$filename])) { if(class_exists($filename) && get_parent_class($class = new $filename) == 'visualization' ) { return $class; } else { return null; } } else { return grade_report_visual::$visualizations[$filename]; } } /** * Based on load user function from grader report. * Pulls out the userids of the users to be used in the stats. * @return array array of user ids to use in stats */ public function load_users() { global $CFG, $DB; if(isset($DB) && !is_null($DB)) { $params = array(); list($usql, $gbr_params) = $DB->get_in_or_equal(explode(',', $this->gradebookroles)); $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber, u.username FROM {user} u JOIN {role_assignments} ra ON u.id = ra.userid $this->groupsql WHERE ra.roleid $usql $this->groupwheresql AND ra.contextid ".get_related_contexts_string($this->context); $params = array_merge($gbr_params, $this->groupwheresql_params); $this->users = $DB->get_records_sql($sql, $params); } else { $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber FROM {$CFG->prefix}user u 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); $this->users = get_records_sql($sql); } if (empty($this->users)) { $this->userselect = ''; $this->users = array(); $this->userselect_params = array(); } else { if(isset($DB) && !is_null($DB)) { list($usql, $params) = $DB->get_in_or_equal(array_keys($this->users)); $this->userselect = "AND g.userid $usql"; $this->userselect_params = $params; }else{ $this->userselect = 'AND g.userid in ('.implode(',', array_keys($this->users)).')'; } } return $this->users; } /** * Harvest the grades from the data base and build the finalgrades array. * Filters out hidden, locked and null grades based on users settings. * Partly based on grader reports load_final_grades function. */ public function harvest_data() { global $CFG, $DB; $params = array(); if(isset($DB) && !is_null($DB)) { $params = array_merge(array($this->courseid), $this->userselect_params); /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it! $sql = "SELECT g.* FROM {grade_items} gi, {grade_grades} g WHERE g.itemid = gi.id AND gi.courseid = ? {$this->userselect}"; $grades = $DB->get_records_sql($sql, $params); } else { /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it! $sql = "SELECT g.* FROM {$CFG->prefix}grade_items gi, {$CFG->prefix}grade_grades g WHERE g.itemid = gi.id AND gi.courseid = {$this->courseid} {$this->userselect}"; $grades = get_records_sql($sql); } $userids = array_keys($this->users); if ($grades) { foreach ($grades as $graderec) { if (in_array($graderec->userid, $userids) and array_key_exists($graderec->itemid, $this->gtree->items)) { // some items may not be present!! $this->grades[$graderec->itemid][$graderec->userid] = new grade_grade($graderec, false); $this->grades[$graderec->itemid][$graderec->userid]->grade_item =& $this->gtree->items[$graderec->itemid]; // db caching } } } if($this->nullgradesasmin) { /// prefil grades that do not exist yet foreach ($userids as $userid) { foreach ($this->gtree->items as $itemid=>$unused) { if (!isset($this->grades[$itemid][$userid])) { $this->grades[$itemid][$userid] = new grade_grade(); $this->grades[$itemid][$userid]->itemid = $itemid; $this->grades[$itemid][$userid]->userid = $userid; $this->grades[$itemid][$userid]->grade_item =& $this->gtree->items[$itemid]; // db caching $this->grades[$itemid][$userid]->finalgrade = $this->grades[$itemid][$userid]->grade_item->mingrade; } } } } /*$this->finalgrades = array(); /// Build finalgrades array and filliter out unwanted grades. foreach ($this->gtree->items as $id=>$item) { if(($item->gradetype == GRADE_TYPE_SCALE && ($this->get_pref('stats', 'showscaleitems') || is_null($this->get_pref('stats', 'showscaleitems')))) || ($item->gradetype == GRADE_TYPE_VALUE && ($this->get_pref('stats', 'showvalueitems') || is_null($this->get_pref('stats', 'showvalueitems'))))) { $this->finalgrades[$id] = array(); $i = 0; if(isset($this->grades[$id]) && !is_null($this->grades[$id])) { foreach ($this->grades[$id] as $grade) { if( (($grade->is_hidden() && ($this->get_pref('stats', 'usehidden') || is_null($this->get_pref('stats', 'usehidden')))) || !$grade->is_hidden()) && (($grade->is_locked() && ($this->get_pref('stats', 'uselocked') || is_null($this->get_pref('stats', 'uselocked')))) || !$grade->is_locked())) { if($this->get_pref('stats', 'incompleasmin') && is_null($grade->finalgrade)) { $this->finalgrades[$id][$i] = $item->grademin; $i++; } elseif(!is_null($grade->finalgrade)) { $this->finalgrades[$id][$i] = $grade->finalgrade; $i++; } } } } } }*/ } /** * TODO: have this make the data depending on what kind of visulsation * is needed rather then a singal visulasztion witch is currently hardcoded. */ public function report_data($all = false) { if($all) { $visuals = $this->get_visualizations(); foreach($visuals as $key=>$visual) { $this->visdata[$key] = $visual->report_data($this); } } else { $visual = $this->get_visualization($this->visid); $this->visdata[$this->visid] = $visual->report_data($this); } } private function set_up_flashvars() { global $USER, $SESSION, $CFG; $flashvars = array(); $flashvars['username'] = $USER->username; $flashvars['userid'] = $USER->id; $flashvars['courseid'] = $this->courseid; $flashvars['coursefullname'] = $this->course->fullname; $flashvars['courseshortname'] = $this->course->shortname; $flashvars['sessionid'] = session_id(); $flashvars['sessioncookie'] = $CFG->sessioncookie; $flashvars['sessiontest'] = $SESSION->session_test; $flashvars['dirroot'] = $CFG->dirroot; $flashvars['wwwroot'] = $CFG->wwwroot; $flashvars['visid'] = $this->visid; foreach($flashvars as $key=>$val) { $this->flashvarshtml .= $key. '=' . addslashes(urlencode(strip_tags($val))) . '&'; } $this->flashvarshtml = substr($this->flashvarshtml, 0, strlen($this->flashvarshtml) - 1); } /** *TODO: Have this call on flex.php to generate html for the report., *rather then having it hardcoded as it is now. */ public function adapt_html($printerversion = false, $return = false) { global $CFG; $flashvarshtml = $this->flashvarshtml; $visual = $this->get_visualization($this->visid); ob_start(); require($CFG->dirroot.'/grade/report/visual/flex.php'); $this->html = ob_get_clean(); if($return) { return $this->html; } else { echo $this->html; } } public function adapt_data($return = false) { if($return) { return $this->get_tab(true); } else { echo $this->get_tab(true); } } public function visualization_selector($return = false) { $visuals = $this->get_visualizations(); $visualmenu = array(); $vislabel = $this->get_lang_string('visualselector', 'gradereport_visual'); foreach($visuals as $key=>$visual) { $visualmenu[$key] = format_string($visual->name); } if(count($visualmenu) > 1) { $selectorhtml = popup_form($this->pbarurl . '&visid=', $visualmenu, 'selectvisual', $this->visid, '', '', '', true, 'self', $vislabel); } else { $selectorhtml = ''; } if($return) { return $selectorhtml; } else { echo $selectorhtml; } } public static function truncate($string, $max = 25, $end = '...') { if(strlen($string) <= $max) { return $string; } return substr_replace($string, $end, $max - strlen($end)); } /** * Returns the data for a visulazation in json format. * TODO: Use moodle's json encoding functions rather then phps. * @param boolean $return if true return a string, other wise echo the data. * @return string If return is set to true, returns a string of the data in json format. */ private function get_json($return = true) { if ($return) { return json_encode($this->visdata[$this->visid]); } else { echo json_encode($this->visdata[$this->visid]); } } /** * Returns the data for a visulasation in tab format. * @param boolean $return if true return a string, other wise echo the data. * @return string If return is set to true, returns a string of the data in tab format. */ private function get_tab($return = true) { if ($return) { return $this->tab_encode($this->visdata[$this->visid]); } else { echo $this->tab_encode($this->visdata[$this->visid]); } } /** * Encodes an array to a string using the tab format. *@param array $data the array to encode. *@return string a string encoded in tab format based on the given array. */ public static function tab_encode(array $data, $useindexes = false) { $outstring = ''; foreach($data as $key=>$row) { if(is_array($row)) { if($useindexes) { $outstring .= $key . "\t"; } foreach($row as $col) { $outstring .= $col . "\t"; } $outstring[strlen($outstring) - 1] = "\n"; } else { if($useindexes) { $outstring .= $key . "\t" . $row . "\n"; } else { $outstring .= $row . "\n"; } } } return $outstring; } } ?>