[moodle] / contrib / plugins / grade / report / stats / lib.php Repository:

Annotation of /contrib/plugins/grade/report/stats/lib.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (view) (download)

1 : dservos 1.1 <?php
2 :    
3 :     /**
4 :     * File in which the grade_report_stats class is defined.
5 :     */
6 :    
7 :     require_once($CFG->dirroot . '/grade/report/lib.php');
8 :     require_once($CFG->libdir.'/tablelib.php');
9 :     require_once($CFG->dirroot . '/grade/report/stats/statistics/load.php');
10 :    
11 :     /**
12 :     * Class providing the API for the stats report, including harvesters,
13 :     * reports, and adaptor methods for turing grades in to statistics.
14 :     * @uses grade_report
15 :     * @package gradebook
16 :     */
17 :     class grade_report_stats extends grade_report {
18 :     /**
19 :     * Capability to view hidden items.
20 :     * TODO: Add a check for hidden items and grades.
21 :     * @var boolean $canviewhidden
22 :     */
23 :     private $canviewhidden;
24 :    
25 :     /**
26 :     * Categories to be displayed based on report setting.
27 :     * @var array $collapsed
28 :     */
29 :     private $collapsed;
30 :    
31 :     /**
32 :     * Grade objects of users in the course
33 :     * @var array $grades
34 :     */
35 :     private $grades;
36 :    
37 :     /**
38 :     * Array of users final grades affter filtered based on
39 :     * settings.
40 :     * @var array $finalgrades
41 :     */
42 :     private $finalgrades;
43 :    
44 :     /**
45 :     * The value returned from each statistic.
46 :     * @var array $reportedstats
47 :     */
48 :     private $reportedstats;
49 :    
50 :     /**
51 :     * The html of the report to output.
52 :     * @var string $html
53 :     */
54 :     public $html;
55 :    
56 :     /**
57 :     * The table class used to make the html of the report.
58 :     * @var object $table
59 :     */
60 :     private $table;
61 :    
62 :     /**
63 :     * Constructor. Initialises grade_tree, sets up group, baseurl
64 :     * and pbarurl.
65 :     * @param int $courseid the coures id for the report
66 :     * @param object $gpr grade plugin tracking object
67 :     * @context string $context
68 :     */
69 :     public function __construct($courseid, $gpr, $context) {
70 :     global $CFG;
71 :     parent::__construct($courseid, $gpr, $context, null);
72 :    
73 :     $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->course->id));
74 :    
75 :     /// Set categories to be displayed.
76 :     if($this->get_pref('stats', 'aggregationview') == GRADE_REPORT_PREFERENCE_DEFAULT || $this->get_pref('stats', 'aggregationview') == GRADE_REPORT_AGGREGATION_VIEW_FULL) {
77 :     $this->collapsed = array('aggregatesonly' => array(), 'gradesonly' => array());
78 :     } elseif($this->get_pref('stats', 'aggregationview') == GRADE_REPORT_AGGREGATION_VIEW_AGGREGATES_ONLY) {
79 :     $this->collapsed = array('aggregatesonly' => array());
80 :     } elseif($this->get_pref('stats', 'aggregationview') == GRADE_REPORT_AGGREGATION_VIEW_GRADES_ONLY) {
81 :     $this->collapsed = array('gradesonly' => array());
82 :     } else {
83 :     $this->collapsed = array('aggregatesonly' => array(), 'gradesonly' => array());
84 :     }
85 :    
86 :     /// Set up urls
87 :     $this->baseurl = 'index.php?id=' . $this->courseid;
88 :     $this->pbarurl = 'index.php?id=' . $this->courseid;
89 :    
90 :     /// Set the position of the aggregation categorie based on pref
91 :     $switch = $this->get_pref('stats', 'aggregationposition');
92 :     if ($switch == '' && isset($CFG->grade_aggregationposition)) {
93 :     $switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
94 :     }
95 :    
96 :     /// Build grade tree
97 :     $this->gtree = new grade_tree($this->courseid, false, $switch);
98 :    
99 :     /// Set up Groups
100 :     if ($this->get_pref('stats', 'showgroups') || is_null($this->get_pref('stats', 'showgroups'))) {
101 :     if(is_callable(array($this, 'setup_groups'))) {
102 :     $this->setup_groups();
103 :     } else {
104 :     $this->local_setup_groups();
105 :     }
106 :     }
107 :     }
108 :    
109 :     public function process_data($data){}
110 :     public function process_action($target, $action){}
111 :    
112 :     private function local_setup_groups() {
113 :     global $CFG;
114 :    
115 :     /// find out current groups mode
116 :     $this->group_selector = groups_print_course_menu($this->course, $this->pbarurl, true);
117 :     $this->currentgroup = groups_get_course_group($this->course);
118 :    
119 :     if ($this->currentgroup) {
120 :     $this->groupsql = " LEFT JOIN {groups_members} gm ON gm.userid = u.id ";
121 :     $this->groupwheresql = " AND gm.groupid = ? ";
122 :     $this->groupwheresql_params = array($this->currentgroup);
123 :     }
124 :     }
125 :    
126 :     /**
127 :     * Based on load user function from grader report.
128 :     * Pulls out the userids of the users to be used in the stats.
129 :     * @return array array of user ids to use in stats
130 :     */
131 :     public function load_users() {
132 :     global $CFG, $DB;
133 :    
134 :     if(isset($DB) && !is_null($DB)) {
135 :     $params = array();
136 :     list($usql, $gbr_params) = $DB->get_in_or_equal(explode(',', $this->gradebookroles));
137 :    
138 :     $sql = "SELECT u.id
139 :     FROM {user} u
140 :     JOIN {role_assignments} ra ON u.id = ra.userid
141 :     $this->groupsql
142 :     WHERE ra.roleid $usql
143 :     $this->groupwheresql
144 :     AND ra.contextid ".get_related_contexts_string($this->context);
145 :    
146 :     $params = array_merge($gbr_params, $this->groupwheresql_params);
147 :     $this->users = $DB->get_records_sql($sql, $params);
148 :     } else {
149 :     $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
150 :     FROM {$CFG->prefix}user u
151 :     JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
152 :     $this->groupsql
153 :     WHERE ra.roleid in ($this->gradebookroles)
154 :     $this->groupwheresql
155 :     AND ra.contextid ".get_related_contexts_string($this->context);
156 :    
157 :     $this->users = get_records_sql($sql);
158 :     }
159 :    
160 :     if (empty($this->users)) {
161 :     $this->userselect = '';
162 :     $this->users = array();
163 :     } else {
164 :     if(isset($DB) && !is_null($DB)) {
165 :     list($usql, $params) = $DB->get_in_or_equal(array_keys($this->users));
166 :     $this->userselect = "AND g.userid $usql";
167 :     $this->userselect_params = $params;
168 :     }else{
169 :     $this->userselect = 'AND g.userid in ('.implode(',', array_keys($this->users)).')';
170 :     }
171 :     }
172 :    
173 :     return $this->users;
174 :     }
175 :    
176 :     /**
177 :     * Encode an array of stat's data in to a stirng so it can
178 :     * be put in the get part of a url.
179 :     * @param arrray $array array of data to encode
180 :     * @param object $item grade_item to use to fromat stats
181 :     * @param object $stat stats object to use to format stats
182 :     * @return string encoded string
183 :     */
184 :     private function encode_array($array, $item, $stat) {
185 :     $string = '';
186 :    
187 :     /// Encode each elment by puting a delimiter and base64 encoding it.
188 :     foreach($array as $id=>$data) {
189 :     $string .= addslashes(grade_format_gradevalue($data, $item, true, $stat->displaytype, $stat->decimals)) . '"';
190 :     }
191 :     return strtr(base64_encode($string), '+/=', '-_,');
192 :     }
193 :    
194 :     /**
195 :     * Harvest the grades from the data base and build the finalgrades array.
196 :     * Filters out hidden, locked and null grades based on users settings.
197 :     * Partly based on grader reports load_final_grades function.
198 :     */
199 :     public function harvest_data() {
200 :     global $CFG, $DB;
201 :    
202 :     if(isset($DB) && !is_null($DB)) {
203 :     $params = array_merge(array($this->courseid), $this->userselect_params);
204 :    
205 :     /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
206 :     $sql = "SELECT g.*
207 :     FROM {grade_items} gi,
208 :     {grade_grades} g
209 :     WHERE g.itemid = gi.id AND gi.courseid = ? {$this->userselect}";
210 :    
211 :     $grades = $DB->get_records_sql($sql, $params);
212 :     } else {
213 :     /// please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
214 :     $sql = "SELECT g.*
215 :     FROM {$CFG->prefix}grade_items gi,
216 :     {$CFG->prefix}grade_grades g
217 :     WHERE g.itemid = gi.id AND gi.courseid = {$this->courseid} {$this->userselect}";
218 :    
219 :     $grades = get_records_sql($sql);
220 :     }
221 :    
222 :     $userids = array_keys($this->users);
223 :    
224 :     if ($grades) {
225 :     foreach ($grades as $graderec) {
226 :     if (in_array($graderec->userid, $userids) and array_key_exists($graderec->itemid, $this->gtree->items)) { // some items may not be present!!
227 :     $this->grades[$graderec->itemid][$graderec->userid] = new grade_grade($graderec, false);
228 :     $this->grades[$graderec->itemid][$graderec->userid]->grade_item =& $this->gtree->items[$graderec->itemid]; // db caching
229 :     }
230 :     }
231 :     }
232 :    
233 :     /// prefil grades that do not exist yet
234 :     foreach ($userids as $userid) {
235 :     foreach ($this->gtree->items as $itemid=>$unused) {
236 :     if (!isset($this->grades[$itemid][$userid])) {
237 :     $this->grades[$itemid][$userid] = new grade_grade();
238 :     $this->grades[$itemid][$userid]->itemid = $itemid;
239 :     $this->grades[$itemid][$userid]->userid = $userid;
240 :     $this->grades[$itemid][$userid]->grade_item =& $this->gtree->items[$itemid]; // db caching
241 :     }
242 :     }
243 :     }
244 :    
245 :     $this->finalgrades = array();
246 :    
247 :     /// Build finalgrades array and filliter out unwanted grades.
248 :     foreach ($this->gtree->items as $id=>$item) {
249 :     if(($item->gradetype == GRADE_TYPE_SCALE && ($this->get_pref('stats', 'showscaleitems') || is_null($this->get_pref('stats', 'showscaleitems'))))
250 :     || ($item->gradetype == GRADE_TYPE_VALUE && ($this->get_pref('stats', 'showvalueitems') || is_null($this->get_pref('stats', 'showvalueitems'))))) {
251 :     $this->finalgrades[$id] = array();
252 :     $i = 0;
253 :    
254 :     if(isset($this->grades[$id]) && !is_null($this->grades[$id])) {
255 :     foreach ($this->grades[$id] as $grade) {
256 :     if( (($grade->is_hidden() && ($this->get_pref('stats', 'usehidden') || is_null($this->get_pref('stats', 'usehidden')))) || !$grade->is_hidden())
257 :     && (($grade->is_locked() && ($this->get_pref('stats', 'uselocked') || is_null($this->get_pref('stats', 'uselocked')))) || !$grade->is_locked())) {
258 :     if($this->get_pref('stats', 'incompleasmin') && is_null($grade->finalgrade)) {
259 :     $this->finalgrades[$id][$i] = $item->grademin;
260 :     $i++;
261 :     } elseif(!is_null($grade->finalgrade)) {
262 :     $this->finalgrades[$id][$i] = $grade->finalgrade;
263 :     $i++;
264 :     }
265 :     }
266 :     }
267 :     }
268 :     }
269 :     }
270 :     }
271 :    
272 :     /**
273 :     * Runs grades for each item threw the report functions
274 :     * of each stats class in $stats and stores the values in
275 :     * reportedstats.
276 :     * TODO: Do not report on hidden items if the user can not see them.
277 :     */
278 :     public function report_data() {
279 :     global $stats;
280 :     $this->reportedstats = array();
281 :    
282 :     foreach($stats as $name=>$stat) {
283 :     if($this->get_pref('stats', $name) || is_null($this->get_pref('stats', $name))) {
284 :     $this->reportedstats[$name] = array();
285 :    
286 :     foreach($this->finalgrades as $itemid=>$item) {
287 :     sort($item);
288 :     if(count($item) > 0) {
289 :     $this->reportedstats[$name][$itemid] = $stat->report_data($item, $this->gtree->items[$itemid]);
290 :     } else {
291 :     $this->reportedstats[$name][$itemid] = null;
292 :     }
293 :     }
294 :     }
295 :     }
296 :     }
297 :    
298 :     /**
299 :     * Take the reported data and adapt it in to HTML to output.
300 :     * HTML is stored in html.
301 :     * TODO: Deal with tables growing to wide.
302 :     * TODO: Make it look nice.
303 :     */
304 :     public function adapt_data() {
305 :     global $stats;
306 :    
307 :     /// Set up table arrays
308 :     $tablecolumns = array('statistic');
309 :     $tableheaders = array($this->get_lang_string('statistic', 'gradereport_stats'));
310 :    
311 :     /// Set up range column and number of grades column
312 :     $ranges = array('<strong>' . $this->get_lang_string('range', 'gradereport_stats') . '</strong>');
313 :     $numgrades = array('<strong>' . $this->get_lang_string('num_grades', 'gradereport_stats') . '</strong>');
314 :    
315 :     /// Loop threw items and build arrays
316 :     foreach($this->finalgrades as $itemid=>$item) {
317 :     array_push($tablecolumns, $itemid);
318 :     array_push($tableheaders, $this->gtree->items[$itemid]->get_name());
319 :     array_push($ranges, '<strong>' . grade_format_gradevalue($this->gtree->items[$itemid]->grademin, $this->gtree->items[$itemid], true) . '-' . grade_format_gradevalue($this->gtree->items[$itemid]->grademax, $this->gtree->items[$itemid], true) . '<strong>' );
320 :     array_push($numgrades, count($item));
321 :     }
322 :    
323 :     /// Set up flexible table
324 :     $this->table = new flexible_table('grade-report-stats-' . $this->courseid);
325 :     $this->table->define_columns($tablecolumns);
326 :     $this->table->define_headers($tableheaders);
327 :     $this->table->define_baseurl($this->baseurl);
328 :     $this->table->collapsible(true);
329 :     $this->table->set_attribute('cellspacing', '1');
330 :     $this->table->set_attribute('id', 'stats-grade');
331 :     $this->table->set_attribute('class', 'grade-report-stats gradestable flexible');
332 :     $this->table->setup();
333 :    
334 :     /// If ranges are being shown add them to the table
335 :     if ($this->get_pref('stats', 'showranges')){
336 :     $this->table->add_data($ranges);
337 :     $this->table->add_separator();
338 :     }
339 :    
340 :     /// Loop threw all the reported data and format it in to cells
341 :     /// If stat retured an array of values display the elements or
342 :     /// make a link to a popup with the data in it.
343 :     foreach($this->reportedstats as $name=>$data) {
344 :     $row = array('<strong>' . $stats[$name]->name . '</strong>');
345 :    
346 :     foreach($data as $itemid=>$stat) {
347 :     if(!is_array($stat)) {
348 :     array_push($row, grade_format_gradevalue($stat, $this->gtree->items[$itemid], true, $stats[$name]->displaytype, $stats[$name]->decimals));
349 :     } else {
350 :     $statstring = "";
351 :    
352 :     for($i = 0; $i < 2; $i++) {
353 :     if($i >= count($stat)) {
354 :     break;
355 :     }
356 :     $statstring .= grade_format_gradevalue($stat[$i], $this->gtree->items[$itemid], true, $stats[$name]->displaytype, $stats[$name]->decimals) . ', ';
357 :     }
358 :    
359 :     if($i < count($stat)) {
360 :     $statstring = "<a href=\"#\" onClick=\"javascript:window.open('arrayview.php?data={$this->encode_array($stat, $this->gtree->items[$itemid], $stats[$name])}','{$this->get_lang_string('moredata', 'gradereport_stats')}','width=300,height=500,menubar=no,status=no,location=no,directories=no,toolbar=no,scrollbars=yes');\">". $statstring . '....</a>';
361 :     } else {
362 :     $statstring = substr($statstring, 0, strlen($statstring) - 2);
363 :     }
364 :     array_push($row, $statstring);
365 :     }
366 :     }
367 :     $this->table->add_data($row);
368 :     }
369 :    
370 :     /// If the number of grades is being shown add it to the table.
371 :     if ($this->get_pref('stats', 'shownumgrades')){
372 :     $this->table->add_separator();
373 :     $this->table->add_data($numgrades);
374 :     }
375 :    
376 :     /// Build html
377 :     ob_start();
378 :     if($this->currentgroup == 0) {
379 :     echo '<strong>Group:</strong> All participants';
380 :     } else {
381 :     echo '<strong>Group:</strong> ' . groups_get_group_name($this->currentgroup);
382 :     }
383 :     $this->table->print_html();
384 :     $this->html = ob_get_clean();
385 :     }
386 :    
387 :     /**
388 :     * Builds HTML for toggles on top of report.
389 :     * Based on grader report get_toggles_html
390 :     * @return string html code for toggles.
391 :     */
392 :     public function get_toggles_html() {
393 :     global $CFG, $USER;
394 :    
395 :     $html = '<div id="stats-report-toggles" style="vertical-align: text-top; text-align: center;">';
396 :     $html .= $this->print_toggle('numgrades', true);
397 :     $html .= $this->print_toggle('groups', true);
398 :     $html .= $this->print_toggle('ranges', true);
399 :     $html .= '</div>';
400 :    
401 :     return $html;
402 :     }
403 :    
404 :     /**
405 :     * Builds HTML for each individual toggle.
406 :     * Based on grader report print_toggle
407 :     * @param string $type The toggle type.
408 :     * @param bool $return Wheather ro return the HTML or print it.
409 :     */
410 :     private function print_toggle($type, $return=false) {
411 :     global $CFG;
412 :    
413 :     $icons = array('eyecons' => 't/hide.gif',
414 :     'numgrades' => 't/grades.gif',
415 :     'calculations' => 't/calc.gif',
416 :     'locks' => 't/lock.gif',
417 :     'averages' => 't/mean.gif',
418 :     'nooutcomes' => 't/outcomes.gif');
419 :    
420 :     $pref_name = 'grade_report_statsshow' . $type;
421 :    
422 :     if (array_key_exists($pref_name, $CFG)) {
423 :     $show_pref = get_user_preferences($pref_name, $CFG->$pref_name);
424 :     } else {
425 :     $show_pref = get_user_preferences($pref_name);
426 :     }
427 :    
428 :     $strshow = $this->get_lang_string('show' . $type, 'gradereport_stats');
429 :     $strhide = $this->get_lang_string('hide' . $type, 'gradereport_stats');
430 :    
431 :     $show_hide = 'show';
432 :     $toggle_action = 1;
433 :    
434 :     if ($show_pref) {
435 :     $show_hide = 'hide';
436 :     $toggle_action = 0;
437 :     }
438 :    
439 :     if (array_key_exists($type, $icons)) {
440 :     $image_name = $icons[$type];
441 :     } else {
442 :     $image_name = "t/$type.gif";
443 :     }
444 :    
445 :     $string = ${'str' . $show_hide};
446 :    
447 :     $img = '<img src="'.$CFG->pixpath.'/'.$image_name.'" class="iconsmall" alt="'
448 :     .$string.'" title="'.$string.'" />'. "\n";
449 :    
450 :     $retval = $img . '<a href="' . $this->baseurl . "&amp;toggle=$toggle_action&amp;toggle_type=$type\">"
451 :     . $string . '</a> ';
452 :    
453 :     if ($return) {
454 :     return $retval;
455 :     } else {
456 :     echo $retval;
457 :     }
458 :     }
459 :     }
460 :     ?>

Moodle CVS Admin
ViewVC Help
Powered by ViewVC 1.0.7