MDL-55026 quiz_overview: Convert chart to the new library
authorFrederic Massart <fred@moodle.com>
Mon, 27 Jun 2016 07:13:53 +0000 (15:13 +0800)
committerDan Poltawski <dan@moodle.com>
Mon, 25 Jul 2016 09:43:01 +0000 (10:43 +0100)
Part of MDL-54987 epic.

mod/quiz/renderer.php
mod/quiz/report/overview/overviewgraph.php
mod/quiz/report/overview/report.php
mod/quiz/report/overview/tests/report_test.php

index cddf863..526f2f5 100644 (file)
@@ -1233,6 +1233,17 @@ class mod_quiz_renderer extends plugin_renderer_base {
         return html_writer::link($url, $summary);
     }
 
+    /**
+     * Outputs a chart.
+     *
+     * @param \core\chart_base $chart The chart.
+     * @param string $title The title to display above the graph.
+     * @return string HTML fragment for the graph.
+     */
+    public function chart(\core\chart_base $chart, $title) {
+        return $this->heading($title, 3) . html_writer::tag('div', $this->render($chart), array('class' => 'graph'));
+    }
+
     /**
      * Output a graph, or a message saying that GD is required.
      * @param moodle_url $url the URL of the graph.
index 9202369..3538464 100644 (file)
  * @package   quiz_overview
  * @copyright 2008 Jamie Pratt
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @deprecated since Moodle 3.2
  */
 
 
 require_once(__DIR__ . '/../../../../config.php');
-require_once($CFG->libdir . '/graphlib.php');
-require_once($CFG->dirroot . '/mod/quiz/locallib.php');
-require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
+require_once($CFG->libdir . '/filelib.php');
 
-$quizid = required_param('id', PARAM_INT);
-$groupid = optional_param('groupid', 0, PARAM_INT);
-
-$quiz = $DB->get_record('quiz', array('id' => $quizid));
-$course = $DB->get_record('course', array('id' => $quiz->course));
-$cm = get_coursemodule_from_instance('quiz', $quizid);
-
-require_login($course, false, $cm);
-$modcontext = context_module::instance($cm->id);
-require_capability('mod/quiz:viewreports', $modcontext);
-
-if ($groupid && $groupmode = groups_get_activity_groupmode($cm)) {
-    // Groups are being used.
-    $groups = groups_get_activity_allowed_groups($cm);
-    if (!array_key_exists($groupid, $groups)) {
-        print_error('errorinvalidgroup', 'group', null, $groupid);
-    }
-    $group = $groups[$groupid];
-    $groupusers = get_users_by_capability($modcontext,
-            array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'),
-            '', '', '', '', $group->id, '', false);
-    if (!$groupusers) {
-        print_error('nostudentsingroup');
-    }
-    $groupusers = array_keys($groupusers);
-} else {
-    $groupusers = array();
-}
-
-$line = new graph(800, 600);
-$line->parameter['title'] = '';
-$line->parameter['y_label_left'] = get_string('participants');
-$line->parameter['x_label'] = get_string('grade');
-$line->parameter['y_label_angle'] = 90;
-$line->parameter['x_label_angle'] = 0;
-$line->parameter['x_axis_angle'] = 60;
-
-// The following two lines seem to silence notice warnings from graphlib.php.
-$line->y_tick_labels = null;
-$line->offset_relation = null;
-
-// We will make size > 1 to get an overlap effect when showing groups.
-$line->parameter['bar_size'] = 1;
-// Don't forget to increase spacing so that graph doesn't become one big block of colour.
-$line->parameter['bar_spacing'] = 10;
-
-// Pick a sensible number of bands depending on quiz maximum grade.
-$bands = $quiz->grade;
-while ($bands > 20 || $bands <= 10) {
-    if ($bands > 50) {
-        $bands /= 5;
-    } else if ($bands > 20) {
-        $bands /= 2;
-    }
-    if ($bands < 4) {
-        $bands *= 5;
-    } else if ($bands <= 10) {
-        $bands *= 2;
-    }
-}
-
-// See MDL-34589. Using doubles as array keys causes problems in PHP 5.4,
-// hence the explicit cast to int.
-$bands = (int) ceil($bands);
-$bandwidth = $quiz->grade / $bands;
-$bandlabels = array();
-for ($i = 1; $i <= $bands; $i++) {
-    $bandlabels[] = quiz_format_grade($quiz, ($i - 1) * $bandwidth) . ' - ' .
-            quiz_format_grade($quiz, $i * $bandwidth);
-}
-$line->x_data = $bandlabels;
-
-$line->y_format['allusers'] = array(
-    'colour' => 'red',
-    'bar' => 'fill',
-    'shadow_offset' => 1,
-    'legend' => get_string('allparticipants')
-);
-$line->y_data['allusers'] = quiz_report_grade_bands($bandwidth, $bands, $quizid, $groupusers);
-
-$line->y_order = array('allusers');
-
-$ymax = max($line->y_data['allusers']);
-$line->parameter['y_min_left'] = 0;
-$line->parameter['y_max_left'] = $ymax;
-$line->parameter['y_decimal_left'] = 0;
-
-// Pick a sensible number of gridlines depending on max value on graph.
-$gridlines = $ymax;
-while ($gridlines >= 10) {
-    if ($gridlines >= 50) {
-        $gridlines /= 5;
-    } else {
-        $gridlines /= 2;
-    }
-}
-
-$line->parameter['y_axis_gridlines'] = $gridlines + 1;
-$line->draw();
+debugging('This way of generating the chart is deprecated, refer to quiz_overview_report::display().', DEBUG_DEVELOPER);
+send_file_not_found();
index af8cacf..f14a5d1 100644 (file)
@@ -232,24 +232,25 @@ class quiz_overview_report extends quiz_attempts_report {
 
         if (!$table->is_downloading() && $options->usercanseegrades) {
             $output = $PAGE->get_renderer('mod_quiz');
+            list($bands, $bandwidth) = self::get_bands_count_and_width($quiz);
+            $labels = self::get_bands_labels($bands, $bandwidth, $quiz);
+
             if ($currentgroup && $groupstudents) {
                 list($usql, $params) = $DB->get_in_or_equal($groupstudents);
                 $params[] = $quiz->id;
-                if ($DB->record_exists_select('quiz_grades', "userid $usql AND quiz = ?",
-                        $params)) {
-                    $imageurl = new moodle_url('/mod/quiz/report/overview/overviewgraph.php',
-                            array('id' => $quiz->id, 'groupid' => $currentgroup));
-                    $graphname = get_string('overviewreportgraphgroup', 'quiz_overview',
-                            groups_get_group_name($currentgroup));
-                    echo $output->graph($imageurl, $graphname);
+                if ($DB->record_exists_select('quiz_grades', "userid $usql AND quiz = ?", $params)) {
+                    $data = quiz_report_grade_bands($bandwidth, $bands, $quiz->id, $groupstudents);
+                    $chart = self::get_chart($labels, $data);
+                    $graphname = get_string('overviewreportgraphgroup', 'quiz_overview', groups_get_group_name($currentgroup));
+                    echo $output->chart($chart, $graphname);
                 }
             }
 
             if ($DB->record_exists('quiz_grades', array('quiz'=> $quiz->id))) {
-                $imageurl = new moodle_url('/mod/quiz/report/overview/overviewgraph.php',
-                        array('id' => $quiz->id));
+                $data = quiz_report_grade_bands($bandwidth, $bands, $quiz->id, []);
+                $chart = self::get_chart($labels, $data);
                 $graphname = get_string('overviewreportgraph', 'quiz_overview');
-                echo $output->graph($imageurl, $graphname);
+                echo $output->chart($chart, $graphname);
             }
         }
         return true;
@@ -566,4 +567,70 @@ class quiz_overview_report extends quiz_attempts_report {
         quiz_update_all_final_grades($quiz);
         quiz_update_grades($quiz);
     }
+
+    /**
+     * Get the bands configuration for the quiz.
+     *
+     * This returns the configuration for having between 11 and 20 bars in
+     * a chart based on the maximum grade to be given on a quiz. The width of
+     * a band is the number of grade points it encapsulates.
+     *
+     * @param object $quiz The quiz object.
+     * @return array Contains the number of bands, and their width.
+     */
+    public static function get_bands_count_and_width($quiz) {
+        $bands = $quiz->grade;
+        while ($bands > 20 || $bands <= 10) {
+            if ($bands > 50) {
+                $bands /= 5;
+            } else if ($bands > 20) {
+                $bands /= 2;
+            }
+            if ($bands < 4) {
+                $bands *= 5;
+            } else if ($bands <= 10) {
+                $bands *= 2;
+            }
+        }
+        // See MDL-34589. Using doubles as array keys causes problems in PHP 5.4, hence the explicit cast to int.
+        $bands = (int) ceil($bands);
+        return [$bands, $quiz->grade / $bands];
+    }
+
+    /**
+     * Get the bands labels.
+     *
+     * @param int $bands The number of bands.
+     * @param int $bandwidth The band width.
+     * @param object $quiz The quiz object.
+     * @return string[] The labels.
+     */
+    public static function get_bands_labels($bands, $bandwidth, $quiz) {
+        $bandlabels = [];
+        for ($i = 1; $i <= $bands; $i++) {
+            $bandlabels[] = quiz_format_grade($quiz, ($i - 1) * $bandwidth) . ' - ' . quiz_format_grade($quiz, $i * $bandwidth);
+        }
+        return $bandlabels;
+    }
+
+    /**
+     * Get a chart.
+     *
+     * @param string[] $labels Chart labels.
+     * @param int[] $data The data.
+     * @return \core\chart_base
+     */
+    protected static function get_chart($labels, $data) {
+        $chart = new \core\chart_bar();
+        $chart->set_labels($labels);
+        $chart->get_xaxis(0, true)->set_label(get_string('grade'));
+
+        $yaxis = $chart->get_yaxis(0, true);
+        $yaxis->set_label(get_string('participants'));
+        $yaxis->set_stepsize(max(1, round(max($data) / 10)));
+
+        $series = new \core\chart_series(get_string('participants'), $data);
+        $chart->add_series($series);
+        return $chart;
+    }
 }
index 094faa6..f583b30 100644 (file)
@@ -126,4 +126,32 @@ class quiz_overview_report_testcase extends advanced_testcase {
         $this->assertArrayHasKey($student3->id . '#0', $table->rawdata);
         $this->assertEquals(0, $table->rawdata[$student3->id . '#0']->gradedattempt);
     }
+
+    /**
+     * Bands provider.
+     * @return array
+     */
+    public function get_bands_count_and_width_provider() {
+        return [
+            [10, [20, .5]],
+            [20, [20, 1]],
+            [30, [15, 2]],
+            // TODO MDL-55068 Handle bands better when grade is 50.
+            // [50, [10, 5]],
+            [100, [20, 5]],
+            [200, [20, 10]],
+        ];
+    }
+
+    /**
+     * Test bands.
+     * @dataProvider get_bands_count_and_width_provider
+     */
+    public function test_get_bands_count_and_width($grade, $expected) {
+        $this->resetAfterTest(true);
+        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
+        $quiz = $quizgenerator->create_instance(['course' => SITEID, 'grade' => $grade]);
+        $this->assertEquals($expected, quiz_overview_report::get_bands_count_and_width($quiz));
+    }
+
 }