Merge branch 'MDL-47681-master' of git://github.com/FMCorz/moodle
authorDan Poltawski <dan@moodle.com>
Thu, 16 Oct 2014 14:14:20 +0000 (15:14 +0100)
committerDan Poltawski <dan@moodle.com>
Thu, 16 Oct 2014 14:14:20 +0000 (15:14 +0100)
40 files changed:
availability/classes/tree.php
grade/report/grader/lib.php
grade/report/singleview/classes/event/grade_report_viewed.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/filterable_items.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/grade.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/screen.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/select.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/selectable_items.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/tablelike.php [new file with mode: 0644]
grade/report/singleview/classes/local/screen/user.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/attribute_format.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/be_checked.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/be_disabled.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/bulk_insert.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/checkbox_attribute.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/dropdown_attribute.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/element.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/empty_element.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/exclude.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/feedback.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/finalgrade.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/grade_attribute_format.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/override.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/range.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/tabbable.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/text_attribute.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/unique_name.php [new file with mode: 0644]
grade/report/singleview/classes/local/ui/unique_value.php [new file with mode: 0644]
grade/report/singleview/db/access.php [new file with mode: 0755]
grade/report/singleview/index.php [new file with mode: 0755]
grade/report/singleview/js/singleview.js [new file with mode: 0644]
grade/report/singleview/lang/en/gradereport_singleview.php [new file with mode: 0755]
grade/report/singleview/lib.php [new file with mode: 0755]
grade/report/singleview/styles.css [new file with mode: 0644]
grade/report/singleview/tests/behat/singleview.feature [new file with mode: 0644]
grade/report/singleview/version.php [new file with mode: 0755]
lang/en/grades.php
lib/classes/plugin_manager.php
mod/scorm/locallib.php
report/participation/index.php

index 658ed5f..e6383ed 100644 (file)
@@ -198,7 +198,7 @@ class tree extends tree_node {
 
         // For unit tests, also allow the mock plugin type (even though it
         // isn't configured in the code as a proper plugin).
-        if (defined('PHPUNIT_TEST')) {
+        if (PHPUNIT_TEST) {
             $enabled['mock'] = true;
         }
 
index 32577b8..26b4933 100644 (file)
@@ -671,15 +671,24 @@ class grade_report_grader extends grade_report {
 
             $userrow->cells[] = $usercell;
 
+            $userreportcell = new html_table_cell();
+            $userreportcell->attributes['class'] = 'userreport';
+            $userreportcell->header = true;
             if (has_capability('gradereport/'.$CFG->grade_profilereport.':view', $this->context)) {
-                $userreportcell = new html_table_cell();
-                $userreportcell->attributes['class'] = 'userreport';
-                $userreportcell->header = true;
                 $a = new stdClass();
                 $a->user = $fullname;
                 $strgradesforuser = get_string('gradesforuser', 'grades', $a);
                 $url = new moodle_url('/grade/report/'.$CFG->grade_profilereport.'/index.php', array('userid' => $user->id, 'id' => $this->course->id));
-                $userreportcell->text = $OUTPUT->action_icon($url, new pix_icon('t/grades', $strgradesforuser));
+                $userreportcell->text .= $OUTPUT->action_icon($url, new pix_icon('t/grades', $strgradesforuser));
+            }
+
+            if (has_capability('gradereport/singleview:view', $this->context)) {
+                $url = new moodle_url('/grade/report/singleview/index.php', array('id' => $this->course->id, 'itemid' => $user->id, 'item' => 'user'));
+                $singleview = $OUTPUT->action_icon($url, new pix_icon('t/editstring', get_string('singleview', 'grades', $fullname)));
+                $userreportcell->text .= $singleview;
+            }
+
+            if ($userreportcell->text) {
                 $userrow->cells[] = $userreportcell;
             }
 
@@ -817,8 +826,17 @@ class grade_report_grader extends grade_report {
                         $itemcell->attributes['class'] .= ' dimmed_text';
                     }
 
+                    $singleview = '';
+                    if (has_capability('gradereport/singleview:view', $this->context)) {
+                        $url = new moodle_url('/grade/report/singleview/index.php', array(
+                            'id' => $this->course->id,
+                            'item' => 'grade',
+                            'itemid' => $element['object']->id));
+                        $singleview = $OUTPUT->action_icon($url, new pix_icon('t/editstring', get_string('singleview', 'grades', $element['object']->itemname)));
+                    }
+
                     $itemcell->colspan = $colspan;
-                    $itemcell->text = shorten_text($headerlink) . $arrow;
+                    $itemcell->text = shorten_text($headerlink) . $arrow . $singleview;
                     $itemcell->header = true;
                     $itemcell->scope = 'col';
 
diff --git a/grade/report/singleview/classes/event/grade_report_viewed.php b/grade/report/singleview/classes/event/grade_report_viewed.php
new file mode 100644 (file)
index 0000000..b35c4cb
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Single view report viewed event.
+ *
+ * @package    gradereport_singleview
+ * @copyright  2014 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * User report viewed event class.
+ *
+ * @package    gradereport_singleview
+ * @since      Moodle 2.8
+ * @copyright  2014 Damyon Wiese
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class grade_report_viewed extends \core\event\grade_report_viewed {
+
+    /**
+     * Returns localised general event name.
+     *
+     * @return string
+     */
+    public static function get_name() {
+        return get_string('eventgradereportviewed', 'gradereport_singleview');
+    }
+
+    /**
+     * Custom validation.
+     *
+     * Throw \coding_exception notice in case of any problems.
+     */
+    protected function validate_data() {
+        parent::validate_data();
+
+        if (!isset($this->relateduserid)) {
+            throw new \coding_exception('The \'relateduserid\' value must be set.');
+        }
+    }
+}
diff --git a/grade/report/singleview/classes/local/screen/filterable_items.php b/grade/report/singleview/classes/local/screen/filterable_items.php
new file mode 100644 (file)
index 0000000..b266cf9
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook interface for a filterable class.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * The gradebook interface for a filterable class.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface filterable_items {
+
+    /**
+     * Return true/false if this item should be filtered.
+     * @param mixed $item (user or grade_item)
+     * @return bool
+     */
+    public static function filter($item);
+}
diff --git a/grade/report/singleview/classes/local/screen/grade.php b/grade/report/singleview/classes/local/screen/grade.php
new file mode 100644 (file)
index 0000000..0cb0321
--- /dev/null
@@ -0,0 +1,334 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The screen with a list of users.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+use gradereport_singleview\local\ui\range;
+use gradereport_singleview\local\ui\bulk_insert;
+use grade_grade;
+use grade_item;
+use moodle_url;
+use pix_icon;
+use html_writer;
+use gradereport_singleview;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * The screen with a list of users.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class grade extends tablelike implements selectable_items, filterable_items {
+
+    /** @var int $totalitemcount Used for paging */
+    private $totalitemcount = 0;
+
+    /** @var bool $requiresextra True if this is a manual grade item */
+    private $requiresextra = false;
+
+    /** @var bool $requirepaging True if there are more users than our limit. */
+    private $requirespaging = true;
+
+    /**
+     * True if $CFG->grade_overridecat is true
+     *
+     * @return bool
+     */
+    public static function allowcategories() {
+        return get_config('moodle', 'grade_overridecat');
+    }
+
+    /**
+     * Filter the list excluding category items (if required)?
+     * @param grade_item $item The grade item.
+     */
+    public static function filter($item) {
+        return get_config('moodle', 'grade_overridecat') ||
+                !($item->is_course_item() || $item->is_category_item());
+    }
+
+    /**
+     * Get the description of this page
+     * @return string
+     */
+    public function description() {
+        return get_string('users');
+    }
+
+    /**
+     * Convert this list of items into an options list
+     *
+     * @return array
+     */
+    public function options() {
+        $options = array();
+        foreach ($this->items as $userid => $user) {
+            $options[$userid] = fullname($user);
+        }
+
+        return $options;
+    }
+
+    /**
+     * Return the type of the things in this list.
+     * @return string
+     */
+    public function item_type() {
+        return 'user';
+    }
+
+    /**
+     * Get the original settings for this item
+     * @return array
+     */
+    public function original_definition() {
+        $def = array('finalgrade', 'feedback');
+
+        if ($this->requiresextra) {
+            $def[] = 'override';
+        }
+
+        $def[] = 'exclude';
+
+        return $def;
+    }
+
+    /**
+     * Init this page
+     *
+     * @param bool $selfitemisempty True if we have not selected a user.
+     */
+    public function init($selfitemisempty = false) {
+        $roleids = explode(',', get_config('moodle', 'gradebookroles'));
+
+        $this->items = get_role_users(
+            $roleids, $this->context, false, '',
+            'u.lastname, u.firstname', null, $this->groupid);
+
+        $this->totalitemcount = count_role_users($roleids, $this->context);
+
+        if ($selfitemisempty) {
+            return;
+        }
+
+        $params = array(
+            'id' => $this->itemid,
+            'courseid' => $this->courseid
+        );
+
+        $this->item = grade_item::fetch($params);
+        if (!self::filter($this->item)) {
+            $this->items = array();
+            $this->set_init_error(get_string('gradeitemcannotbeoverridden', 'gradereport_singleview'));
+        }
+
+        $this->requiresextra = !$this->item->is_manual_item();
+
+        $this->setup_structure();
+
+        $this->set_definition($this->original_definition());
+        $this->set_headers($this->original_headers());
+    }
+
+    /**
+     * Get the table headers
+     *
+     * @return array
+     */
+    public function original_headers() {
+        return array(
+            '', // For filter icon.
+            '', // For user picture.
+            get_string('firstname') . ' (' . get_string('alternatename') . ') ' . get_string('lastname'),
+            get_string('range', 'grades'),
+            get_string('grade', 'grades'),
+            get_string('feedback', 'grades'),
+            $this->make_toggle_links('override'),
+            $this->make_toggle_links('exclude')
+        );
+    }
+
+    /**
+     * Format a row in the table
+     *
+     * @param user $item
+     * @return string
+     */
+    public function format_line($item) {
+        global $OUTPUT;
+
+        $grade = $this->fetch_grade_or_default($this->item, $item->id);
+
+        $lockicon = '';
+
+        $lockedgrade = $lockedgradeitem = 0;
+        if (!empty($grade->locked)) {
+            $lockedgrade = 1;
+        }
+        if (!empty($grade->grade_item->locked)) {
+            $lockedgradeitem = 1;
+        }
+        // Check both grade and grade item.
+        if ( $lockedgrade || $lockedgradeitem ) {
+            $lockicon = $OUTPUT->pix_icon('t/locked', 'grade is locked') . ' ';
+        }
+
+        if (!empty($item->alternatename)) {
+            $fullname = $lockicon . $item->alternatename . ' (' . $item->firstname . ') ' . $item->lastname;
+        } else {
+            $fullname = $lockicon . fullname($item);
+        }
+
+        $item->imagealt = $fullname;
+        $url = new moodle_url("/user/view.php", array('id' => $item->id, 'course' => $this->courseid));
+        $iconstring = get_string('filtergrades', 'gradereport_singleview', $fullname);
+        $grade->label = $fullname;
+
+        $line = array(
+            $OUTPUT->action_icon($this->format_link('user', $item->id), new pix_icon('t/editstring', $iconstring)),
+            $OUTPUT->user_picture($item),
+            html_writer::link($url, $fullname),
+            $this->item_range()
+        );
+
+        return $this->format_definition($line, $grade);
+    }
+
+    /**
+     * Get the range ui element for this grade_item
+     *
+     * @return element;
+     */
+    public function item_range() {
+        if (empty($this->range)) {
+            $this->range = new range($this->item);
+        }
+
+        return $this->range;
+    }
+
+    /**
+     * Does this page require paging?
+     *
+     * @return bool
+     */
+    public function supports_paging() {
+        return $this->requirespaging;
+    }
+
+    /**
+     * Get the pager for this page.
+     *
+     * @return string
+     */
+    public function pager() {
+        global $OUTPUT;
+
+        return $OUTPUT->paging_bar(
+            $this->totalitemcount, $this->page, $this->perpage,
+            new moodle_url('/grade/report/singleview/index.php', array(
+                'perpage' => $this->perpage,
+                'id' => $this->courseid,
+                'groupid' => $this->groupid,
+                'itemid' => $this->itemid,
+                'item' => 'grade'
+            ))
+        );
+    }
+
+    /**
+     * Get the heading for this page.
+     *
+     * @return string
+     */
+    public function heading() {
+        return $this->item->get_name();
+    }
+
+    /**
+     * Process the data from the form.
+     *
+     * @param array $data
+     * @return array of warnings
+     */
+    public function process($data) {
+        $bulk = new bulk_insert($this->item);
+        // Bulk insert messages the data to be passed in
+        // ie: for all grades of empty grades apply the specified value.
+        if ($bulk->is_applied($data)) {
+            $filter = $bulk->get_type($data);
+            $insertvalue = $bulk->get_insert_value($data);
+            // Appropriately massage data that may not exist.
+            if ($this->supports_paging()) {
+                $gradeitem = grade_item::fetch(array(
+                    'courseid' => $this->courseid,
+                    'id' => $this->item->id
+                ));
+
+                $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : '';
+
+                foreach ($this->items as $itemid => $item) {
+                    $field = "finalgrade_{$gradeitem->id}_{$itemid}";
+                    if (isset($data->$field)) {
+                        continue;
+                    }
+
+                    $grade = grade_grade::fetch(array(
+                        'itemid' => $gradeitem->id,
+                        'userid' => $itemid
+                    ));
+
+                    $data->$field = empty($grade) ? $null : $grade->finalgrade;
+                    $data->{"old$field"} = $data->$field;
+                }
+            }
+
+            foreach ($data as $varname => $value) {
+                if (!preg_match('/^finalgrade_(\d+)_/', $varname, $matches)) {
+                    continue;
+                }
+
+                $gradeitem = grade_item::fetch(array(
+                    'courseid' => $this->courseid,
+                    'id' => $matches[1]
+                ));
+
+                $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE);
+
+                $empties = (trim($value) === '' or ($isscale and $value == -1));
+
+                if ($filter == 'all' or $empties) {
+                    $data->$varname = ($isscale and empty($insertvalue)) ?
+                        -1 : $insertvalue;
+                }
+            }
+        }
+
+        return parent::process($data);
+    }
+
+}
diff --git a/grade/report/singleview/classes/local/screen/screen.php b/grade/report/singleview/classes/local/screen/screen.php
new file mode 100644 (file)
index 0000000..fd4fa6d
--- /dev/null
@@ -0,0 +1,346 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Abstract class used as a base for the 3 screens.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+use context_course;
+use moodle_url;
+use html_writer;
+use grade_structure;
+use grade_grade;
+use grade_item;
+use stdClass;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Abstract class used as a base for the 3 screens.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class screen {
+
+    /** @var int $courseid The id of the course */
+    protected $courseid;
+
+    /** @var int $itemid Either a user id or a grade_item id */
+    protected $itemid;
+
+    /** @var int $groupid The currently set groupid (if set) */
+    protected $groupid;
+
+    /** @var course_context $context The course context */
+    protected $context;
+
+    /** @var int $page The page number */
+    protected $page;
+
+    /** @var int $perpage Results per page */
+    protected $perpage;
+
+    /** @var array $items List of items on the page, they could be users or grade_items */
+    protected $items;
+
+    /**
+     * Constructor
+     *
+     * @param int $courseid The course id
+     * @param int $itemid The item id
+     * @param int $groupid The group id
+     */
+    public function __construct($courseid, $itemid, $groupid = null) {
+        global $DB;
+
+        $this->courseid = $courseid;
+        $this->itemid = $itemid;
+        $this->groupid = $groupid;
+
+        $this->context = context_course::instance($this->courseid);
+        $this->course = $DB->get_record('course', array('id' => $courseid));
+
+        $this->page = optional_param('page', 0, PARAM_INT);
+        $this->perpage = optional_param('perpage', 100, PARAM_INT);
+        if ($this->perpage > 100) {
+            $this->perpage = 100;
+        }
+
+        $this->init(empty($itemid));
+    }
+
+    /**
+     * Cache the grade_structure class
+     */
+    public function setup_structure() {
+        $this->structure = new grade_structure();
+        $this->structure->modinfo = get_fast_modinfo($this->course);
+    }
+
+    /**
+     * Create a nice link from a thing (user or grade_item).
+     *
+     * @param string $screen
+     * @param int $itemid
+     * @param bool $display Should we wrap this in an anchor ?
+     * @return string The link
+     */
+    public function format_link($screen, $itemid, $display = null) {
+        $url = new moodle_url('/grade/report/singleview/index.php', array(
+            'id' => $this->courseid,
+            'item' => $screen,
+            'itemid' => $itemid,
+            'group' => $this->groupid,
+        ));
+
+        if ($display) {
+            return html_writer::link($url, $display);
+        } else {
+            return $url;
+        }
+    }
+
+    /**
+     * Get the grade_grade
+     *
+     * @param grade_item $item The grade_item
+     * @param int $userid The user id
+     * @return grade_grade
+     */
+    public function fetch_grade_or_default($item, $userid) {
+        $grade = grade_grade::fetch(array(
+            'itemid' => $item->id, 'userid' => $userid
+        ));
+
+        if (!$grade) {
+            $default = new stdClass;
+
+            $default->userid = $userid;
+            $default->itemid = $item->id;
+            $default->feedback = '';
+
+            $grade = new grade_grade($default, false);
+        }
+
+        $grade->grade_item = $item;
+
+        return $grade;
+    }
+
+    /**
+     * Make the HTML element that toggles all the checkboxes on or off.
+     *
+     * @param string $key A unique key for this control - inserted in the classes.
+     * @return string
+     */
+    public function make_toggle($key) {
+        $attrs = array('href' => '#');
+
+        $all = html_writer::tag('a', get_string('all'), $attrs + array(
+            'class' => 'include all ' . $key
+        ));
+
+        $none = html_writer::tag('a', get_string('none'), $attrs + array(
+            'class' => 'include none ' . $key
+        ));
+
+        return html_writer::tag('span', "$all / $none", array(
+            'class' => 'inclusion_links'
+        ));
+    }
+
+    /**
+     * Make a toggle link with some text before it.
+     *
+     * @param string $key A unique key for this control - inserted in the classes.
+     * @return string
+     */
+    public function make_toggle_links($key) {
+        return get_string($key, 'gradereport_singleview') . ' ' .
+            $this->make_toggle($key);
+    }
+
+    /**
+     * Get the default heading for the screen.
+     *
+     * @return string
+     */
+    public function heading() {
+        return get_string('pluginname', 'gradereport_singleview');
+    }
+
+    /**
+     * Override this to init the screen.
+     *
+     * @param boolean $selfitemisempty True if no item has been selected yet.
+     */
+    public abstract function init($selfitemisempty = false);
+
+    /**
+     * Get the type of items in the list.
+     *
+     * @return string
+     */
+    public abstract function item_type();
+
+    /**
+     * Get the entire screen as a string.
+     *
+     * @return string
+     */
+    public abstract function html();
+
+    /**
+     * Does this screen support paging?
+     *
+     * @return bool
+     */
+    public function supports_paging() {
+        return true;
+    }
+
+    /**
+     * Default pager
+     *
+     * @return string
+     */
+    public function pager() {
+        return '';
+    }
+
+    /**
+     * Initialise the js for this screen.
+     */
+    public function js() {
+        global $PAGE;
+
+        $module = array(
+            'name' => 'gradereport_singleview',
+            'fullpath' => '/grade/report/singleview/js/singleview.js',
+            'requires' => array('base', 'dom', 'event', 'event-simulate', 'io-base')
+        );
+
+        $PAGE->requires->js_init_call('M.gradereport_singleview.init', array(), false, $module);
+    }
+
+    /**
+     * Process the data from a form submission.
+     *
+     * @param array $data
+     * @return array of warnings
+     */
+    public function process($data) {
+        $warnings = array();
+
+        $fields = $this->definition();
+
+        foreach ($data as $varname => $throw) {
+            if (preg_match("/(\w+)_(\d+)_(\d+)/", $varname, $matches)) {
+                $itemid = $matches[2];
+                $userid = $matches[3];
+            } else {
+                continue;
+            }
+
+            $gradeitem = grade_item::fetch(array(
+                'id' => $itemid, 'courseid' => $this->courseid
+            ));
+
+            if (preg_match('/^old[oe]{1}/', $varname)) {
+                $elementname = preg_replace('/^old/', '', $varname);
+                if (!isset($data->$elementname)) {
+                    $data->$elementname = false;
+                }
+            }
+
+            if (!in_array($matches[1], $fields)) {
+                continue;
+            }
+
+            if (!$gradeitem) {
+                continue;
+            }
+
+            $grade = $this->fetch_grade_or_default($gradeitem, $userid);
+
+            $classname = '\\gradereport_singleview\\local\\ui\\' . $matches[1];
+            $element = new $classname($grade);
+
+            $name = $element->get_name();
+            $oldname = "old$name";
+
+            $posted = $data->$name;
+
+            $format = $element->determine_format();
+
+            if ($format->is_textbox() and trim($data->$name) === '') {
+                $data->$name = null;
+            }
+
+            // Same value; skip.
+            if (isset($data->$oldname) && $data->$oldname == $posted) {
+                continue;
+            }
+
+            $msg = $element->set($posted);
+
+            // Optional type.
+            if (!empty($msg)) {
+                $warnings[] = $msg;
+            }
+        }
+
+        // Some post-processing.
+        $eventdata = new stdClass;
+        $eventdata->warnings = $warnings;
+        $eventdata->post_data = $data;
+        $eventdata->instance = $this;
+
+        return $eventdata->warnings;
+    }
+
+    /**
+     * By default there are no options.
+     * @return array
+     */
+    public function options() {
+        return array();
+    }
+
+    /**
+     * Should we show the group selector?
+     * @return bool
+     */
+    public function display_group_selector() {
+        return true;
+    }
+
+    /**
+     * Should we show the next prev selector?
+     * @return bool
+     */
+    public function supports_next_prev() {
+        return true;
+    }
+}
diff --git a/grade/report/singleview/classes/local/screen/select.php b/grade/report/singleview/classes/local/screen/select.php
new file mode 100644 (file)
index 0000000..4554043
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook simple view - initial view to select your search options
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+use gradereport_singleview;
+use moodle_url;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * The gradebook simple view - initial view to select your search options
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class select extends screen {
+
+    /**
+     * Initialise this screen
+     *
+     * @param bool $selfitemisempty Has an item been selected (will be false)
+     */
+    public function init($selfitemisempty = false) {
+        global $DB;
+
+        $roleids = explode(',', get_config('moodle', 'gradebookroles'));
+
+        $this->items = get_role_users(
+            $roleids, $this->context, false, '',
+            'u.id, u.lastname, u.firstname', null, $this->groupid,
+            $this->perpage * $this->page, $this->perpage
+        );
+        $this->item = $DB->get_record('course', array('id' => $this->courseid));
+    }
+
+    /**
+     * Get the type of items on this screen, not valid so return false.
+     *
+     * @return bool
+     */
+    public function item_type() {
+        return false;
+    }
+
+    /**
+     * Return the HTML for the page.
+     *
+     * @return string
+     */
+    public function html() {
+        global $OUTPUT;
+
+        $html = '';
+
+        $types = gradereport_singleview::valid_screens();
+
+        foreach ($types as $type) {
+            $classname = "gradereport_singleview\\local\\screen\\${type}";
+
+            $screen = new $classname($this->courseid, null, $this->groupid);
+
+            if (!$screen instanceof selectable_items) {
+                continue;
+            }
+
+            $options = $screen->options();
+
+            if (empty($options)) {
+                continue;
+            }
+
+            $params = array(
+                'id' => $this->courseid,
+                'item' => $screen->item_type(),
+                'group' => $this->groupid
+            );
+
+            $url = new moodle_url('/grade/report/singleview/index.php', $params);
+            $html .= $OUTPUT->heading($screen->description());
+
+            $html .= $OUTPUT->single_select($url, 'itemid', $options);
+        }
+
+        if (empty($html)) {
+            $OUTPUT->notification(get_string('noscreens', 'gradereport_singleview'));
+        }
+
+        return $html;
+    }
+
+    /**
+     * Should we show the next prev selector?
+     * @return bool
+     */
+    public function supports_next_prev() {
+        return false;
+    }
+}
diff --git a/grade/report/singleview/classes/local/screen/selectable_items.php b/grade/report/singleview/classes/local/screen/selectable_items.php
new file mode 100644 (file)
index 0000000..84967fc
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Interface for a list of selectable things.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Interface for a list of selectable things.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface selectable_items {
+    /**
+     * Get the description of this list
+     * @return string
+     */
+    public function description();
+
+    /**
+     * Get the list of options to show.
+     * @return array
+     */
+    public function options();
+
+    /**
+     * Get type of things in the list (gradeitem or user)
+     * @return string
+     */
+    public function item_type();
+}
diff --git a/grade/report/singleview/classes/local/screen/tablelike.php b/grade/report/singleview/classes/local/screen/tablelike.php
new file mode 100644 (file)
index 0000000..775f145
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook simple view - base class for the table
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+use html_table;
+use html_writer;
+use stdClass;
+use grade_item;
+use grade_grade;
+use gradereport_singleview\local\ui\bulk_insert;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * The gradebook simple view - base class for the table
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class tablelike extends screen {
+
+    /** @var array $headers A list of table headers */
+    protected $headers = array();
+
+    /** @var array $initerrors A list of errors that mean we should not show the table */
+    protected $initerrors = array();
+
+    /** @var array $definition Describes the columns in the table */
+    protected $definition = array();
+
+    /**
+     * Format a row of the table
+     *
+     * @param mixed $item
+     * @return string
+     */
+    public abstract function format_line($item);
+
+    /**
+     * Get the table headers
+     *
+     * @return array
+     */
+    public function headers() {
+        return $this->headers;
+    }
+
+    /**
+     * Set the table headers
+     *
+     * @param array $overwrite New headers
+     * @return tablelike This
+     */
+    public function set_headers($overwrite) {
+        $this->headers = $overwrite;
+        return $this;
+    }
+
+    /**
+     * Get the list of errors
+     *
+     * @return array
+     */
+    public function init_errors() {
+        return $this->initerrors;
+    }
+
+    /**
+     * Set an error detected while building the page.
+     *
+     * @param string $mesg
+     */
+    public function set_init_error($mesg) {
+        $this->initerrors[] = $mesg;
+    }
+
+    /**
+     * Get the table definition
+     *
+     * @return array The definition.
+     */
+    public function definition() {
+        return $this->definition;
+    }
+
+    /**
+     * Set the table definition
+     *
+     * @param array $overwrite New definition
+     * @return tablelike This
+     */
+    public function set_definition($overwrite) {
+        $this->definition = $overwrite;
+        return $this;
+    }
+
+    /**
+     * Get the tabindex for the table in the page.
+     *
+     * @return int
+     */
+    public function get_tabindex() {
+        return (count($this->definition()) * $this->total) + $this->index;
+    }
+
+    /**
+     * Get a element to generate the HTML for this table row
+     * @param array $line This is a list of lines in the table (modified)
+     * @param grade_grade $grade The grade.
+     * @return string
+     */
+    public function format_definition($line, $grade) {
+        foreach ($this->definition() as $i => $field) {
+            // Table tab index.
+            $tab = ($i * $this->total) + $this->index;
+            $classname = '\\gradereport_singleview\\local\\ui\\' . $field;
+            $html = new $classname($grade, $tab);
+
+            if ($field == 'finalgrade' and !empty($this->structure)) {
+                $html .= $this->structure->get_grade_analysis_icon($grade);
+            }
+
+            $line[] = $html;
+        }
+        return $line;
+    }
+
+    /**
+     * Get the HTML for the whole table
+     * @return string
+     */
+    public function html() {
+        global $OUTPUT;
+
+        if (!empty($this->initerrors)) {
+            $warnings = '';
+            foreach ($this->initerrors as $mesg) {
+                $warnings .= $OUTPUT->notification($mesg);
+            }
+            return $warnings;
+        }
+        $table = new html_table();
+
+        $table->head = $this->headers();
+
+        // To be used for extra formatting.
+        $this->index = 0;
+        $this->total = count($this->items);
+
+        foreach ($this->items as $item) {
+            if ($this->index >= ($this->perpage * $this->page) &&
+                $this->index < ($this->perpage * ($this->page + 1))) {
+                $table->data[] = $this->format_line($item);
+            }
+            $this->index++;
+        }
+
+        $underlying = get_class($this);
+
+        $data = new stdClass;
+        $data->table = $table;
+        $data->instance = $this;
+
+        $buttonattr = array('class' => 'singleview_buttons submit');
+        $buttonhtml = implode(' ', $this->buttons());
+
+        $buttons = html_writer::tag('div', $buttonhtml, $buttonattr);
+
+        return html_writer::tag('form',
+            $buttons . html_writer::table($table) . $this->bulk_insert() . $buttons,
+            array('method' => 'POST')
+        );
+    }
+
+    /**
+     * Get the HTML for the bulk insert form
+     *
+     * @return string
+     */
+    public function bulk_insert() {
+        return html_writer::tag(
+            'div',
+            (new bulk_insert($this->item))->html(),
+            array('class' => 'singleview_bulk')
+        );
+    }
+
+    /**
+     * Get the buttons for saving changes.
+     *
+     * @return array
+     */
+    public function buttons() {
+        $save = html_writer::empty_tag('input', array(
+            'type' => 'submit',
+            'value' => get_string('update'),
+            'tabindex' => $this->get_tabindex(),
+        ));
+
+        return array($save);
+    }
+}
diff --git a/grade/report/singleview/classes/local/screen/user.php b/grade/report/singleview/classes/local/screen/user.php
new file mode 100644 (file)
index 0000000..cdd56d9
--- /dev/null
@@ -0,0 +1,335 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The user screen.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\screen;
+
+use grade_seq;
+use gradereport_singleview;
+use moodle_url;
+use pix_icon;
+use html_writer;
+use gradereport_singleview\local\ui\range;
+use gradereport_singleview\local\ui\bulk_insert;
+use grade_item;
+use grade_grade;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * The user screen.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class user extends tablelike implements selectable_items {
+
+    /** @var array $categories A cache for grade_item categories */
+    private $categories = array();
+
+    /** @var int $requirespaging Do we have more items than the paging limit? */
+    private $requirespaging = true;
+
+    /**
+     * Get the description for the screen.
+     *
+     * @return string
+     */
+    public function description() {
+        return get_string('gradeitems', 'grades');
+    }
+
+    /**
+     * Convert the list of items to a list of options.
+     *
+     * @return array
+     */
+    public function options() {
+        $result = array();
+        foreach ($this->items as $itemid => $item) {
+            $result[$itemid] = $item->get_name();
+        }
+        return $result;
+    }
+
+    /**
+     * Get the type of items on this screen.
+     *
+     * @return string
+     */
+    public function item_type() {
+        return 'grade';
+    }
+
+    /**
+     * Should we show the group selector on this screen?
+     *
+     * @return bool
+     */
+    public function display_group_selector() {
+        return false;
+    }
+
+    /**
+     * Init the screen
+     *
+     * @param bool $selfitemisempty Have we selected an item yet?
+     */
+    public function init($selfitemisempty = false) {
+        global $DB;
+
+        if (!$selfitemisempty) {
+            $this->item = $DB->get_record('user', array('id' => $this->itemid));
+        }
+
+        $params = array('courseid' => $this->courseid);
+
+        $seq = new grade_seq($this->courseid, true);
+        foreach ($seq->items as $key => $item) {
+            if (isset($item->itemmodule)) {
+                list($courseid, $cmid) = get_course_and_cm_from_instance($item->iteminstance, $item->itemmodule);
+                $seq->items[$key]->cmid = $cmid->id;
+            }
+        }
+
+        $this->items = array();
+        foreach ($seq->items as $itemid => $item) {
+            if (grade::filter($item)) {
+                $this->items[$itemid] = $item;
+            }
+        }
+
+        $this->requirespaging = count($this->items) > $this->perpage;
+
+        unset($seq);
+
+        $this->setup_structure();
+
+        $this->definition = array(
+            'finalgrade', 'feedback', 'override', 'exclude'
+        );
+        $this->set_headers($this->original_headers());
+    }
+
+    /**
+     * Get the list of headers for the table.
+     *
+     * @return array List of headers
+     */
+    public function original_headers() {
+        return array(
+            '', // For filter icon.
+            '', // For activity icon.
+            get_string('assessmentname', 'gradereport_singleview'),
+            get_string('gradecategory', 'grades'),
+            get_string('range', 'grades'),
+            get_string('grade', 'grades'),
+            get_string('feedback', 'grades'),
+            $this->make_toggle_links('override'),
+            $this->make_toggle_links('exclude')
+        );
+    }
+
+    /**
+     * Format each row of the table.
+     *
+     * @param grade_item $item
+     * @return string
+     */
+    public function format_line($item) {
+        global $OUTPUT;
+
+        $grade = $this->fetch_grade_or_default($item, $this->item->id);
+        $lockicon = '';
+
+        $lockeditem = $lockeditemgrade = 0;
+        if (!empty($grade->locked)) {
+            $lockeditem = 1;
+        }
+        if (!empty($grade->grade_item->locked)) {
+            $lockeditemgrade = 1;
+        }
+        // Check both grade and grade item.
+        if ($lockeditem || $lockeditemgrade) {
+             $lockicon = $OUTPUT->pix_icon('t/locked', 'grade is locked');
+        }
+
+        $realmodid = '';
+        if (isset($item->cmid)) {
+            $realmodid = $item->cmid;
+        }
+        $url = new moodle_url('/mod/' . $item->itemmodule . '/view.php', array('id' => $realmodid));
+        $iconstring = get_string('filtergrades', 'gradereport_singleview', $item->get_name());
+        $grade->label = $item->get_name();
+
+        $line = array(
+            $OUTPUT->action_icon($this->format_link('grade', $item->id), new pix_icon('t/editstring', $iconstring)),
+            $this->format_icon($item) . $lockicon,
+            html_writer::link($url, $item->get_name()),
+            $this->category($item),
+            (new range($item))
+        );
+        return $this->format_definition($line, $grade);
+    }
+
+    /**
+     * Helper to get the icon for an item.
+     *
+     * @param grade_item $item
+     * @return string
+     */
+    private function format_icon($item) {
+        $element = array('type' => 'item', 'object' => $item);
+        return $this->structure->get_element_icon($element);
+    }
+
+    /**
+     * Helper to get the category for an item.
+     *
+     * @param grade_item $item
+     * @return grade_category
+     */
+    private function category($item) {
+        global $DB;
+
+        if (empty($item->categoryid)) {
+
+            if ($item->itemtype == 'course') {
+                return $this->course->fullname;
+            }
+
+            $params = array('id' => $item->iteminstance);
+            $elem = $DB->get_record('grade_categories', $params);
+
+            return $elem->fullname;
+        }
+
+        if (!isset($this->categories[$item->categoryid])) {
+            $category = $item->get_parent_category();
+
+            $this->categories[$category->id] = $category;
+        }
+
+        return $this->categories[$item->categoryid]->get_name();
+    }
+
+    /**
+     * Get the heading for the page.
+     *
+     * @return string
+     */
+    public function heading() {
+        return fullname($this->item);
+    }
+
+    /**
+     * Default pager
+     *
+     * @return string
+     */
+    public function pager() {
+        global $OUTPUT;
+
+        if (!$this->supports_paging()) {
+            return '';
+        }
+
+        return $OUTPUT->paging_bar(
+            count($this->items), $this->page, $this->perpage,
+            new moodle_url('/grade/report/singleview/index.php', array(
+                'perpage' => $this->perpage,
+                'id' => $this->courseid,
+                'groupid' => $this->groupid,
+                'itemid' => $this->itemid,
+                'item' => 'user'
+            ))
+        );
+    }
+
+    /**
+     * Does this page require paging?
+     *
+     * @return bool
+     */
+    public function supports_paging() {
+        return $this->requirespaging;
+    }
+
+
+    /**
+     * Process the data from the form.
+     *
+     * @param array $data
+     * @return array of warnings
+     */
+    public function process($data) {
+        $bulk = new bulk_insert($this->item);
+        // Bulk insert messages the data to be passed in
+        // ie: for all grades of empty grades apply the specified value.
+        if ($bulk->is_applied($data)) {
+            $filter = $bulk->get_type($data);
+            $insertvalue = $bulk->get_insert_value($data);
+            // Appropriately massage data that may not exist.
+
+            $userid = $this->item->id;
+            foreach ($this->items as $gradeitemid => $gradeitem) {
+                $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : '';
+                $field = "finalgrade_{$gradeitem->id}_{$gradeitemid}";
+                if (isset($data->$field)) {
+                    continue;
+                }
+
+                $grade = grade_grade::fetch(array(
+                    'itemid' => $gradeitem->id,
+                    'userid' => $userid
+                ));
+
+                $data->$field = empty($grade) ? $null : $grade->finalgrade;
+                $data->{"old$field"} = $data->$field;
+            }
+
+            foreach ($data as $varname => $value) {
+                if (!preg_match('/^finalgrade_(\d+)_/', $varname, $matches)) {
+                    continue;
+                }
+
+                $gradeitem = grade_item::fetch(array(
+                    'courseid' => $this->courseid,
+                    'id' => $matches[1]
+                ));
+
+                $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE);
+
+                $empties = (trim($value) === '' or ($isscale and $value == -1));
+
+                if ($filter == 'all' or $empties) {
+                    $data->$varname = ($isscale and empty($insertvalue)) ?
+                        -1 : $insertvalue;
+                }
+            }
+        }
+
+        return parent::process($data);
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/attribute_format.php b/grade/report/singleview/classes/local/ui/attribute_format.php
new file mode 100644 (file)
index 0000000..bbf96e2
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class that builds an element tree that can be converted to a string
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Class that builds an element tree that can be converted to a string
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class attribute_format {
+
+    /**
+     * Used to convert this class to an "element" which can be converted to a string.
+     * @return element
+     */
+    abstract public function determine_format();
+
+    /**
+     * Convert this to an element and then to a string
+     * @return string
+     */
+    public function __toString() {
+        return $this->determine_format()->html();
+    }
+}
+
diff --git a/grade/report/singleview/classes/local/ui/be_checked.php b/grade/report/singleview/classes/local/ui/be_checked.php
new file mode 100644 (file)
index 0000000..03b1bb7
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Is this thing checked?
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Is this thing checked?
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface be_checked {
+    /**
+     * Return true if this is checked.
+     * @return bool
+     */
+    public function is_checked();
+}
diff --git a/grade/report/singleview/classes/local/ui/be_disabled.php b/grade/report/singleview/classes/local/ui/be_disabled.php
new file mode 100644 (file)
index 0000000..28790f3
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * be_disabled interface.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Simple interface implemented to add behaviour that an element can be checked to see
+ * if it should be disabled.
+ */
+interface be_disabled {
+    /**
+     * Am I disabled ?
+     *
+     * @return bool
+     */
+    public function is_disabled();
+}
diff --git a/grade/report/singleview/classes/local/ui/bulk_insert.php b/grade/report/singleview/classes/local/ui/bulk_insert.php
new file mode 100644 (file)
index 0000000..57d45c4
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Checkbox element used for bulk inserting values in the gradebook.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+use html_writer;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Checkbox element used for bulk inserting values in the gradebook.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class bulk_insert extends element {
+
+    /**
+     * Constructor
+     *
+     * @param mixed $item The grade item or user.
+     */
+    public function __construct($item) {
+        $this->name = 'bulk_' . $item->id;
+        $this->applyname = $this->name_for('apply');
+        $this->selectname = $this->name_for('type');
+        $this->insertname = $this->name_for('value');
+    }
+
+    /**
+     * Is this checkbox checked?
+     *
+     * @param array $data The form data
+     * @return bool
+     */
+    public function is_applied($data) {
+        return isset($data->{$this->applyname});
+    }
+
+    /**
+     * Get the type of this input (user or grade)
+     *
+     * @param array $data The form data
+     * @return string
+     */
+    public function get_type($data) {
+        return $data->{$this->selectname};
+    }
+
+    /**
+     * Get the value from either the user or grade.
+     *
+     * @param array $data The form data
+     * @return string
+     */
+    public function get_insert_value($data) {
+        return $data->{$this->insertname};
+    }
+
+    /**
+     * Generate the html for this form element.
+     *
+     * @return string HTML
+     */
+    public function html() {
+        $insertgrade = get_string('bulkinsertgrade', 'gradereport_singleview');
+        $insertappliesto = get_string('bulkappliesto', 'gradereport_singleview');
+
+        $apply = html_writer::checkbox($this->applyname, 1, false, $insertgrade);
+        $insertoptions = array(
+            'all' => get_string('all_grades', 'gradereport_singleview'),
+            'blanks' => get_string('blanks', 'gradereport_singleview')
+        );
+
+        $select = html_writer::select(
+            $insertoptions, $this->selectname, 'blanks', false
+        );
+
+        $label = html_writer::tag('label', $insertappliesto);
+        $text = new text_attribute($this->insertname, "0", 'bulk');
+        return implode(' ', array($apply, $text->html(), $label, $select));
+    }
+
+    /**
+     * This form element has 3 elements with different suffixes.
+     * Generate the name with the suffix.
+     *
+     * @param string $extend The suffix.
+     * @return string
+     */
+    private function name_for($extend) {
+        return "{$this->name}_$extend";
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/checkbox_attribute.php b/grade/report/singleview/classes/local/ui/checkbox_attribute.php
new file mode 100644 (file)
index 0000000..a16b081
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * A checkbox ui element.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace gradereport_singleview\local\ui;
+
+use html_writer;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * A checkbox ui element.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class checkbox_attribute extends element {
+
+    /** @var bool $ischecked Is it checked? */
+    private $ischecked;
+
+    /** @var int $tabindex The tab index for this form element. */
+    private $tabindex;
+
+    /**
+     * Constructor
+     *
+     * @param string $name The element name
+     * @param string $label The label for the form element
+     * @param bool $ischecked Is this thing on?
+     * @param int $tabindex The tab index for the form element.
+     * @param int $locked Is this element locked either 0 or a time.
+     */
+    public function __construct($name, $label, $ischecked = false, $tabindex = null, $locked=0) {
+        $this->ischecked = $ischecked;
+        $this->tabindex = $tabindex;
+        $this->locked = $locked;
+        parent::__construct($name, 1, $label);
+    }
+
+    /**
+     * Nasty function allowing checkbox logic to escape the class.
+     * @return bool
+     */
+    public function is_checkbox() {
+        return true;
+    }
+
+    /**
+     * Generate the HTML
+     *
+     * @return string
+     */
+    public function html() {
+
+        $attributes = array(
+            'type' => 'checkbox',
+            'name' => $this->name,
+            'value' => 1,
+            'id' => $this->name
+        );
+
+        // UCSB fixed user should not be able to override locked grade.
+        if ( $this->locked) {
+            $attributes['disabled'] = 'DISABLED';
+        }
+
+        $hidden = array(
+            'type' => 'hidden',
+            'name' => 'old' . $this->name
+        );
+
+        if (!empty($this->tabindex)) {
+            $attributes['tabindex'] = $this->tabindex;
+        }
+
+        if ($this->ischecked) {
+            $attributes['checked'] = 'CHECKED';
+            $hidden['value'] = 1;
+        }
+
+        $type = "override";
+        if (preg_match("/^exclude/", $this->name)) {
+            $type = "exclude";
+        }
+
+        return (
+            html_writer::tag('label',
+                             get_string($type . 'for', 'gradereport_singleview', $this->label),
+                             array('for' => $this->name, 'class' => 'accesshide')) .
+            html_writer::empty_tag('input', $attributes) .
+            html_writer::empty_tag('input', $hidden)
+        );
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/dropdown_attribute.php b/grade/report/singleview/classes/local/ui/dropdown_attribute.php
new file mode 100644 (file)
index 0000000..af70f02
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Drop down list (select list) element
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Drop down list (select list) element
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class dropdown_attribute extends element {
+
+    /** @var string $selected Who is selected ? */
+    private $selected;
+
+    /** @var array $options List of options ? */
+    private $options;
+
+    /** @var bool $isdisabled Is this input disabled. */
+    private $isdisabled;
+
+    /**
+     * Constructor
+     *
+     * @param string $name The first bit of the name of this input.
+     * @param array $options The options list for this select.
+     * @param string $label The form label for this input.
+     * @param string $selected The name of the selected item in this input.
+     * @param bool $isdisabled Are we disabled?
+     * @param int $tabindex The tab index for this field
+     */
+    public function __construct($name, $options, $label, $selected = '', $isdisabled = false, $tabindex = null) {
+        $this->selected = $selected;
+        $this->options = $options;
+        $this->tabindex = $tabindex;
+        $this->isdisabled = $isdisabled;
+        parent::__construct($name, $selected, $label);
+    }
+
+    /**
+     * Nasty function spreading dropdown logic around.
+     *
+     * @return bool
+     */
+    public function is_dropdown() {
+        return true;
+    }
+
+    /**
+     * Render this element as html.
+     *
+     * @return string
+     */
+    public function html() {
+        $old = array(
+            'type' => 'hidden',
+            'name' => 'old' . $this->name,
+            'value' => $this->selected
+        );
+
+        $attributes = array();
+        if (!empty($this->tabindex)) {
+            $attributes['tabindex'] = $this->tabindex;
+        }
+
+        if (!empty($this->isdisabled)) {
+            $attributes['disabled'] = 'DISABLED';
+        }
+
+        $select = html_writer::select(
+            $this->options, $this->name, $this->selected, false, $attributes
+        );
+
+        return ($select . html_writer::empty_tag('input', $old));
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/element.php b/grade/report/singleview/classes/local/ui/element.php
new file mode 100644 (file)
index 0000000..22b901b
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * UI Element for an excluded grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * UI Element for an excluded grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class element {
+
+    /** @var string $name The first bit of the name for this input. */
+    public $name;
+
+    /** @var string $value The value for this input. */
+    public $value;
+
+    /** @var string $label The form label for this input. */
+    public $label;
+
+    /**
+     * Constructor
+     *
+     * @param string $name The first bit of the name for this input
+     * @param string $value The value for this input
+     * @param string $label The label for this form field
+     */
+    public function __construct($name, $value, $label) {
+        $this->name = $name;
+        $this->value = $value;
+        $this->label = $label;
+    }
+
+    /**
+     * Nasty function used for spreading checkbox logic all around
+     * @return bool
+     */
+    public function is_checkbox() {
+        return false;
+    }
+
+    /**
+     * Nasty function used for spreading textbox logic all around
+     * @return bool
+     */
+    public function is_textbox() {
+        return false;
+    }
+
+    /**
+     * Nasty function used for spreading dropdown logic all around
+     * @return bool
+     */
+    public function is_dropdown() {
+        return false;
+    }
+
+    /**
+     * Return the HTML
+     * @return string
+     */
+    abstract public function html();
+}
diff --git a/grade/report/singleview/classes/local/ui/empty_element.php b/grade/report/singleview/classes/local/ui/empty_element.php
new file mode 100644 (file)
index 0000000..32ff3ce
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Element that just generates some text.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Element that just generates some text.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class empty_element extends element {
+
+    /**
+     * Constructor
+     *
+     * @param string $msg The text
+     */
+    public function __construct($msg = null) {
+        if (is_null($msg)) {
+            $this->text = '&nbsp;';
+        } else {
+            $this->text = $msg;
+        }
+    }
+
+    /**
+     * Generate the html (simple case)
+     *
+     * @return string HTML
+     */
+    public function html() {
+        return $this->text;
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/exclude.php b/grade/report/singleview/classes/local/ui/exclude.php
new file mode 100644 (file)
index 0000000..03e4f6e
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class that represents the exclude checkbox on a grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Class that represents the exclude checkbox on a grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class exclude extends grade_attribute_format implements be_checked {
+
+    /** @var string $name The name of the input */
+    public $name = 'exclude';
+
+    /**
+     * Is it checked?
+     *
+     * @return bool
+     */
+    public function is_checked() {
+        return $this->grade->is_excluded();
+    }
+
+    /**
+     * Generate the element used to render the UI
+     *
+     * @return element
+     */
+    public function determine_format() {
+        return new checkbox_attribute(
+            $this->get_name(),
+            $this->get_label(),
+            $this->is_checked()
+        );
+    }
+
+    /**
+     * Get the label for the form input
+     *
+     * @return string
+     */
+    public function get_label() {
+        if (!isset($this->grade->label)) {
+            $this->grade->label = '';
+        }
+        return $this->grade->label;
+    }
+
+    /**
+     * Set the value that was changed in the form.
+     *
+     * @param string $value The value to set.
+     * @return mixed string|bool An error message or false.
+     */
+    public function set($value) {
+        if (empty($this->grade->id)) {
+            if (empty($value)) {
+                return false;
+            }
+
+            $gradeitem = $this->grade->grade_item;
+
+            // Fill in arbitrary grade to be excluded.
+            $gradeitem->update_final_grade(
+                $this->grade->userid, null, 'singleview', null, FORMAT_MOODLE
+            );
+
+            $gradeparams = array(
+                'userid' => $this->grade->userid,
+                'itemid' => $this->grade->itemid
+            );
+
+            $this->grade = grade_grade::fetch($gradeparams);
+            $this->grade->grade_item = $gradeitem;
+        }
+
+        $state = $value == 0 ? false : true;
+
+        $this->grade->set_excluded($state);
+
+        $this->grade->grade_item->get_parent_category()->force_regrading();
+        return false;
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/feedback.php b/grade/report/singleview/classes/local/ui/feedback.php
new file mode 100644 (file)
index 0000000..a41e0f2
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class used to render a feedback input box.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Class used to render a feedback input box.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class feedback extends grade_attribute_format implements unique_value, be_disabled {
+
+    /** @var string $name Name of this input */
+    public $name = 'feedback';
+
+    /**
+     * Get the value for this input.
+     *
+     * @return string The value
+     */
+    public function get_value() {
+        return $this->grade->feedback ? $this->grade->feedback : '';
+    }
+
+    /**
+     * Get the string to use in the label for this input.
+     *
+     * @return string The label text
+     */
+    public function get_label() {
+        if (!isset($this->grade->label)) {
+            $this->grade->label = '';
+        }
+        return $this->grade->label;
+    }
+
+    /**
+     * Determine if this input should be disabled based on the other settings.
+     *
+     * @return boolean Should this input be disabled when the page loads.
+     */
+    public function is_disabled() {
+        $locked = 0;
+        $gradeitemlocked = 0;
+        $overridden = 0;
+        /* Disable editing if grade item or grade score is locked
+        * if any of these items are set,  then we will disable editing
+        * at some point, we might want to show the reason for the lock
+        * this code could be simplified, but its more readable for steve's little mind
+        */
+        if (!empty($this->grade->locked)) {
+            $locked = 1;
+        }
+        if (!empty($this->grade->grade_item->locked)) {
+            $gradeitemlocked = 1;
+        }
+        if ($this->grade->grade_item->is_overridable_item() and !$this->grade->is_overridden()) {
+            $overridden = 1;
+        }
+        return ($locked || $gradeitemlocked || $overridden);
+    }
+
+    /**
+     * Create a text_attribute for this ui element.
+     *
+     * @return text_attribute
+     */
+    public function determine_format() {
+        return new text_attribute(
+            $this->get_name(),
+            $this->get_value(),
+            $this->get_label(),
+            $this->is_disabled(),
+            $this->get_tabindex()
+        );
+    }
+
+    /**
+     * Update the value for this input.
+     *
+     * @param string $value The new feedback value.
+     * @return string Any error message
+     */
+    public function set($value) {
+        $finalgrade = false;
+        $trimmed = trim($value);
+        if (empty($trimmed)) {
+            $feedback = null;
+        } else {
+            $feedback = $value;
+        }
+
+        $this->grade->grade_item->update_final_grade(
+            $this->grade->userid, $finalgrade, 'singleview',
+            $feedback, FORMAT_MOODLE
+        );
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/finalgrade.php b/grade/report/singleview/classes/local/ui/finalgrade.php
new file mode 100644 (file)
index 0000000..03b7bf0
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * UI element representing the finalgrade column.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * UI element representing the finalgrade column.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class finalgrade extends grade_attribute_format implements unique_value, be_disabled {
+
+    /** @var string $name Name of this input */
+    public $name = 'finalgrade';
+
+    /**
+     * Get the value for this input.
+     *
+     * @return string The value based on the grade_grade.
+     */
+    public function get_value() {
+        $this->label = $this->grade->grade_item->itemname;
+        // Manual item raw grade support.
+        $val = $this->grade->grade_item->is_manual_item() && (!is_null($this->grade->rawgrade)) ?
+            $this->grade->rawgrade : $this->grade->finalgrade;
+
+        if ($this->grade->grade_item->scaleid) {
+            return $val ? (int)$val : -1;
+        } else {
+            return $val ? format_float($val, $this->grade->grade_item->get_decimals()) : '';
+        }
+    }
+
+    /**
+     * Get the label for this input.
+     *
+     * @return string The label for this form input.
+     */
+    public function get_label() {
+        if (!isset($this->grade->label)) {
+            $this->grade->label = '';
+        }
+        return $this->grade->label;
+    }
+
+    /**
+     * Is this input field disabled.
+     *
+     * @return bool Set disabled on this input or not.
+     */
+    public function is_disabled() {
+        $locked = 0;
+        $gradeitemlocked = 0;
+        $overridden = 0;
+
+        // Disable editing if grade item or grade score is locked
+        // if any of these items are set,  then we will disable editing
+        // at some point, we might want to show the reason for the lock
+        // this code could be simplified, but its more readable for steve's little mind.
+
+        if (!empty($this->grade->locked)) {
+            $locked = 1;
+        }
+        if (!empty($this->grade->grade_item->locked)) {
+            $gradeitemlocked = 1;
+        }
+        if ($this->grade->grade_item->is_overridable_item() and !$this->grade->is_overridden()) {
+            $overridden = 1;
+        }
+        return ($locked || $gradeitemlocked || $overridden);
+    }
+
+    /**
+     * Create the element for this column.
+     *
+     * @return element
+     */
+    public function determine_format() {
+        if ($this->grade->grade_item->load_scale()) {
+            $scale = $this->grade->grade_item->load_scale();
+
+            $options = array(-1 => get_string('nograde'));
+
+            foreach ($scale->scale_items as $i => $name) {
+                $options[$i + 1] = $name;
+            }
+
+            return new dropdown_attribute(
+                $this->get_name(),
+                $options,
+                $this->get_value(),
+                $this->get_label(),
+                $this->is_disabled(),
+                $this->get_tabindex()
+            );
+        } else {
+            return new text_attribute(
+                $this->get_name(),
+                $this->get_value(),
+                $this->get_label(),
+                $this->is_disabled(),
+                $this->get_tabindex()
+            );
+        }
+    }
+
+    /**
+     * Save the altered value for this field.
+     *
+     * @param string $value The new value.
+     * @return string Any error string
+     */
+    public function set($value) {
+        global $DB;
+
+        $userid = $this->grade->userid;
+        $gradeitem = $this->grade->grade_item;
+
+        $feedback = false;
+        $feedbackformat = false;
+        if ($gradeitem->gradetype == GRADE_TYPE_SCALE) {
+            if ($value == -1) {
+                $finalgrade = null;
+            } else {
+                $finalgrade = $value;
+            }
+        } else {
+            $finalgrade = unformat_float($value);
+        }
+
+        $errorstr = '';
+        if ($finalgrade) {
+            $bounded = $gradeitem->bounded_grade($finalgrade);
+            if ($bounded > $finalgrade) {
+                $errorstr = 'lessthanmin';
+            } else if ($bounded < $finalgrade) {
+                $errorstr = 'morethanmax';
+            }
+        }
+
+        if ($errorstr) {
+            $user = $DB->get_record('user', array('id' => $userid), 'id, firstname, alternatename, lastname');
+            $gradestr = new stdClass;
+            if (!empty($user->alternatename)) {
+                $gradestr->username = $user->alternatename . ' (' . $user->firstname . ') ' . $user->lastname;
+            } else {
+                $gradestr->username = $user->firstname . ' ' . $user->lastname;
+            }
+            $gradestr->itemname = $this->grade->grade_item->get_name();
+            $errorstr = get_string($errorstr, 'grades', $gradestr);
+        }
+
+        $gradeitem->update_final_grade($userid, $finalgrade, 'singleview', $feedback, FORMAT_MOODLE);
+        return $errorstr;
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/grade_attribute_format.php b/grade/report/singleview/classes/local/ui/grade_attribute_format.php
new file mode 100644 (file)
index 0000000..dcaebcd
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Abstract class for a form element representing something about a grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Abstract class for a form element representing something about a grade_grade.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class grade_attribute_format extends attribute_format implements unique_name, tabbable {
+
+    /** @var string $name The first part of the name attribute of the form input */
+    public $name;
+
+    /** @var string $label The label of the input */
+    public $label;
+
+    /** @var grade_grade $grade The grade_grade of the input */
+    public $grade;
+
+    /** @var int $tabindex The tabindex of the input */
+    public $tabindex;
+
+    /**
+     * Constructor
+     *
+     * @param grade_grade $grade The grade_grade we are editing.
+     * @param int $tabindex The tabindex for the input.
+     */
+    public function __construct($grade = 0, $tabindex = 1) {
+
+        $this->grade = $grade;
+        $this->tabindex = $tabindex;
+    }
+
+    /**
+     * Get a unique name for this form input
+     *
+     * @return string The form input name attribute.
+     */
+    public function get_name() {
+        return "{$this->name}_{$this->grade->itemid}_{$this->grade->userid}";
+    }
+
+    /**
+     * Get the tabindex for this form input
+     *
+     * @return int The tab index
+     */
+    public function get_tabindex() {
+        return isset($this->tabindex) ? $this->tabindex : null;
+    }
+
+    /**
+     * Should be overridden by the child class to save the value returned in this input.
+     *
+     * @param string $value The value from the form.
+     * @return string Any error message
+     */
+    public abstract function set($value);
+}
diff --git a/grade/report/singleview/classes/local/ui/override.php b/grade/report/singleview/classes/local/ui/override.php
new file mode 100644 (file)
index 0000000..64b8292
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * An override grade checkbox element
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * An override grade checkbox element
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class override extends grade_attribute_format implements be_checked, be_disabled {
+
+    /** @var string $name The name for this input */
+    public $name = 'override';
+
+    /**
+     * Is this input checked
+     *
+     * @return bool
+     */
+    public function is_checked() {
+        return $this->grade->is_overridden();
+    }
+
+    /**
+     * Is this input disabled
+     *
+     * @return bool
+     */
+    public function is_disabled() {
+        $lockedgrade = $lockedgradeitem = 0;
+        if (!empty($this->grade->locked)) {
+            $lockedgrade = 1;
+        }
+        if (!empty($this->grade->grade_item->locked)) {
+            $lockedgradeitem = 1;
+        }
+        return ($lockedgrade || $lockedgradeitem);
+    }
+
+    /**
+     * Get the label for this form element.
+     *
+     * @return string
+     */
+    public function get_label() {
+        if (!isset($this->grade->label)) {
+            $this->grade->label = '';
+        }
+        return $this->grade->label;
+    }
+
+    /**
+     * Generate the element for this form input.
+     *
+     * @return element
+     */
+    public function determine_format() {
+        if (!$this->grade->grade_item->is_overridable_item()) {
+            return new empty_element();
+        }
+        return new checkbox_attribute(
+            $this->get_name(),
+            $this->get_label(),
+            $this->is_checked(),
+            null,
+            $this->is_disabled()
+        );
+    }
+
+    /**
+     * Save the modified value of this form element.
+     *
+     * @param string $value The new value to set
+     * @return mixed string|false Any error message
+     */
+    public function set($value) {
+        if (empty($this->grade->id)) {
+            return false;
+        }
+
+        $state = $value == 0 ? false : true;
+
+        $this->grade->set_overridden($state);
+        $this->grade->grade_item->get_parent_category()->force_regrading();
+        return false;
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/range.php b/grade/report/singleview/classes/local/ui/range.php
new file mode 100644 (file)
index 0000000..aa77f2e
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * UI element that generates a min/max range (text only).
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * UI element that generates a grade_item min/max range (text only).
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class range extends attribute_format {
+
+    /**
+     * Constructor
+     * @param grade_item $item The grade item
+     */
+    public function __construct($item) {
+        $this->item = $item;
+    }
+
+    /**
+     * Build this UI element.
+     *
+     * @return element
+     */
+    public function determine_format() {
+        $decimals = $this->item->get_decimals();
+
+        $min = format_float($this->item->grademin, $decimals);
+        $max = format_float($this->item->grademax, $decimals);
+
+        return new empty_element("$min - $max");
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/tabbable.php b/grade/report/singleview/classes/local/ui/tabbable.php
new file mode 100644 (file)
index 0000000..d904931
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook simple view - UI factory
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * This element has a tabindex
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface tabbable {
+    /**
+     * Get the tabindex for this element
+     * @return int
+     */
+    public function get_tabindex();
+}
+
diff --git a/grade/report/singleview/classes/local/ui/text_attribute.php b/grade/report/singleview/classes/local/ui/text_attribute.php
new file mode 100644 (file)
index 0000000..8c86349
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * UI element for a text input field.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+use html_writer;
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * UI element for a text input field.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class text_attribute extends element {
+
+    /** @var bool $isdisabled Is this input disabled? */
+    private $isdisabled;
+
+    /** @var int $tabindex Tabindex value for this input. */
+    private $tabindex;
+
+    /**
+     * Constructor
+     *
+     * @param string $name The input name (the first bit)
+     * @param string $value The input initial value.
+     * @param string $label The label for this input field.
+     * @param bool $isdisabled Is this input disabled.
+     * @param int $tabindex Tab index for this input.
+     */
+    public function __construct($name, $value, $label, $isdisabled = false, $tabindex = null) {
+        $this->isdisabled = $isdisabled;
+        $this->tabindex = $tabindex;
+        parent::__construct($name, $value, $label);
+    }
+
+    /**
+     * Nasty function allowing custom textbox behaviour outside the class.
+     * @return bool Is this a textbox.
+     */
+    public function is_textbox() {
+        return true;
+    }
+
+    /**
+     * Render the html for this field.
+     * @return string The HTML.
+     */
+    public function html() {
+        $attributes = array(
+            'type' => 'text',
+            'name' => $this->name,
+            'value' => $this->value,
+            'id' => $this->name
+        );
+
+        if (!empty($this->tabindex)) {
+            $attributes['tabindex'] = $this->tabindex;
+        }
+        if ($this->isdisabled) {
+            $attributes['disabled'] = 'DISABLED';
+        }
+
+        $hidden = array(
+            'type' => 'hidden',
+            'name' => 'old' . $this->name,
+            'value' => $this->value
+        );
+
+        $label = '';
+        if (preg_match("/^feedback/", $this->name)) {
+            $labeltitle = get_string('feedbackfor', 'gradereport_singleview', $this->label);
+            $label = html_writer::tag('label', $labeltitle,  array('for' => $this->name, 'class' => 'accesshide'));
+        } else if (preg_match("/^finalgrade/", $this->name)) {
+            $labeltitle = get_string('gradefor', 'gradereport_singleview', $this->label);
+            $label = html_writer::tag('label', $labeltitle,  array('for' => $this->name, 'class' => 'accesshide'));
+        }
+
+        return (
+            $label .
+            html_writer::empty_tag('input', $attributes) .
+            html_writer::empty_tag('input', $hidden)
+        );
+    }
+}
diff --git a/grade/report/singleview/classes/local/ui/unique_name.php b/grade/report/singleview/classes/local/ui/unique_name.php
new file mode 100644 (file)
index 0000000..00b7d73
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * A form element with a name field.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * A form element with a name field.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface unique_name {
+
+    /**
+     * Get the name for this form element
+     * @return string
+     */
+    public function get_name();
+}
diff --git a/grade/report/singleview/classes/local/ui/unique_value.php b/grade/report/singleview/classes/local/ui/unique_value.php
new file mode 100644 (file)
index 0000000..a3e3ffd
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook simple view - UI factory
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace gradereport_singleview\local\ui;
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Simple interface for an item with a value.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface unique_value {
+    /**
+     * Get the value for this item.
+     * @return string
+     */
+    public function get_value();
+}
diff --git a/grade/report/singleview/db/access.php b/grade/report/singleview/db/access.php
new file mode 100755 (executable)
index 0000000..2d73261
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The gradebook simple view - Database file
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$capabilities = array(
+
+    'gradereport/singleview:view' => array(
+        'riskbitmask' => RISK_PERSONAL,
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW,
+        )
+    )
+);
diff --git a/grade/report/singleview/index.php b/grade/report/singleview/index.php
new file mode 100755 (executable)
index 0000000..2b347fa
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Displays the Single view
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../../../config.php');
+require_once($CFG->dirroot.'/lib/gradelib.php');
+require_once($CFG->dirroot.'/grade/lib.php');
+require_once($CFG->dirroot.'/grade/report/singleview/lib.php');
+
+$courseid = required_param('id', PARAM_INT);
+$groupid  = optional_param('group', null, PARAM_INT);
+
+// Making this work with profile reports.
+$userid   = optional_param('userid', null, PARAM_INT);
+
+$defaulttype = $userid ? 'user' : 'select';
+
+$itemid   = optional_param('itemid', $userid, PARAM_INT);
+$itemtype = optional_param('item', $defaulttype, PARAM_TEXT);
+$page = optional_param('page', 0, PARAM_INT);
+$perpage = optional_param('perpage', 100, PARAM_INT);
+
+$courseparams = array('id' => $courseid);
+$PAGE->set_url(new moodle_url('/grade/report/singleview/index.php', $courseparams));
+
+if (!$course = $DB->get_record('course', $courseparams)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$PAGE->set_pagelayout('report');
+
+if (!in_array($itemtype, gradereport_singleview::valid_screens())) {
+    print_error('notvalid', 'gradereport_singleview', '', $itemtype);
+}
+
+$context = context_course::instance($course->id);
+
+// This is the normal requirements.
+require_capability('gradereport/singleview:view', $context);
+require_capability('moodle/grade:viewall', $context);
+require_capability('moodle/grade:edit', $context);
+
+$gpr = new grade_plugin_return(array(
+    'type' => 'report',
+    'plugin' => 'singleview',
+    'courseid' => $courseid
+));
+
+// Last selected report session tracking.
+if (!isset($USER->grade_last_report)) {
+    $USER->grade_last_report = array();
+}
+$USER->grade_last_report[$course->id] = 'singleview';
+
+// First make sure we have proper final grades -
+// this must be done before constructing of the grade tree.
+grade_regrade_final_grades($courseid);
+
+$report = new gradereport_singleview(
+    $courseid, $gpr, $context,
+    $itemtype, $itemid, $groupid
+);
+
+$reportname = $report->screen->heading();
+
+$pluginname = get_string('pluginname', 'gradereport_singleview');
+
+$pageparams = array(
+    'id' => $courseid,
+    'itemid' => $itemid,
+    'item' => $itemtype,
+    'userid' => $userid,
+    'group' => $groupid,
+    'page' => $page,
+    'perpage' => $perpage
+);
+
+$currentpage = new moodle_url('/grade/report/singleview/index.php', $pageparams);
+
+if ($data = data_submitted()) {
+    $warnings = $report->process_data($data);
+
+    if (empty($warnings)) {
+        redirect($currentpage);
+        die();
+    }
+}
+
+print_grade_page_head($course->id, 'report', 'singleview', $reportname);
+
+$graderrightnav = $graderleftnav = null;
+
+$options = $report->screen->options();
+
+if (!empty($options)) {
+
+    $optionkeys = array_keys($options);
+    $optionitemid = array_shift($optionkeys);
+
+    $relreport = new gradereport_singleview(
+                $courseid, $gpr, $context,
+                $report->screen->item_type(), $optionitemid, $groupid
+    );
+    $reloptions = $relreport->screen->options();
+    $reloptionssorting = array_keys($relreport->screen->options());
+
+    $i = array_search($itemid, $reloptionssorting);
+    $navparams = array('item' => $itemtype, 'id' => $courseid, 'group' => $groupid);
+    if ($i > 0) {
+        $navparams['itemid'] = $reloptionssorting[$i - 1];
+        $link = new moodle_url('/grade/report/singleview/index.php', $navparams);
+        $navprev = html_writer::link($link, $OUTPUT->larrow() . ' ' . $reloptions[$reloptionssorting[$i - 1]]);
+        $graderleftnav = html_writer::tag('small', $navprev, array('class' => 'itemnav previtem'));
+    }
+    if ($i < count($reloptionssorting) - 1) {
+        $navparams['itemid'] = $reloptionssorting[$i + 1];
+        $link = new moodle_url('/grade/report/singleview/index.php', $navparams);
+        $navnext = html_writer::link($link, $reloptions[$reloptionssorting[$i + 1]] . ' ' . $OUTPUT->rarrow());
+        $graderrightnav = html_writer::tag('small', $navnext, array('class' => 'itemnav nextitem'));
+    }
+}
+
+if (!is_null($graderleftnav)) {
+    echo $graderleftnav;
+}
+if (!is_null($graderrightnav)) {
+    echo $graderrightnav;
+}
+
+if ($report->screen->supports_paging()) {
+    echo $report->screen->pager();
+}
+
+if ($report->screen->display_group_selector()) {
+    echo $report->group_selector;
+}
+
+if (!empty($warnings)) {
+    foreach ($warnings as $warning) {
+        echo $OUTPUT->notification($warning);
+    }
+}
+
+echo $report->output();
+
+if ($report->screen->supports_paging()) {
+    echo $report->screen->pager();
+}
+
+if (!is_null($graderleftnav)) {
+    echo $graderleftnav;
+}
+if (!is_null($graderrightnav)) {
+    echo $graderrightnav;
+}
+
+$event = \gradereport_singleview\event\grade_report_viewed::create(
+    array(
+        'context' => $context,
+        'courseid' => $courseid,
+        'relateduserid' => $USER->id,
+    )
+);
+$event->trigger();
+
+echo $OUTPUT->footer();
diff --git a/grade/report/singleview/js/singleview.js b/grade/report/singleview/js/singleview.js
new file mode 100644 (file)
index 0000000..02d7be8
--- /dev/null
@@ -0,0 +1,41 @@
+M.gradereport_singleview = {};
+
+M.gradereport_singleview.init = function(Y) {
+    // Make toggle links
+    Y.all('.include').each(function(link) {
+        var type = link.getAttribute('class').split(" ")[2];
+
+        var toggle = function(checked) {
+            return function(input) {
+                input.getDOMNode().checked = checked;
+                Y.Event.simulate(input.getDOMNode(), 'change');
+            };
+        };
+
+        link.on('click', function() {
+            Y.all('input[name^=' + type + ']').each(toggle(link.hasClass('all')));
+            return false;
+        });
+    });
+
+    // Override Toggle
+    Y.all('input[name^=override_]').each(function(input) {
+        input.on('change', function() {
+            var checked = input.getDOMNode().checked;
+            var names = input.getAttribute('name').split("_");
+
+            var itemid = names[1];
+            var userid = names[2];
+
+            var interest = '_' + itemid + '_' + userid;
+
+            Y.all('input[name$=' + interest + ']').filter('input[type=text]').each(function(text) {
+                text.getDOMNode().disabled = !checked;
+            });
+            // deal with scales that are not text... UCSB
+            Y.all('select[name$=' + interest + ']').each(function(select) {
+                select.getDOMNode().disabled = !checked;
+            });
+        });
+    });
+};
diff --git a/grade/report/singleview/lang/en/gradereport_singleview.php b/grade/report/singleview/lang/en/gradereport_singleview.php
new file mode 100755 (executable)
index 0000000..a4d3545
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for Single view
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// General Strings.
+$string['all_grades'] = 'All grades';
+$string['assessmentname'] = 'Assessment Name';
+$string['blanks'] = 'Empty grades';
+$string['bulkappliesto'] = 'for';
+$string['bulkinsertgrade'] = 'Bulk insert';
+$string['bulkfor'] = 'Grades for {$a}';
+$string['exclude'] = 'Exclude';
+$string['excludeall'] = 'Exclude all grades';
+$string['excludefor'] = 'Exclude for {$a}';
+$string['excludenone'] = 'Exclude no grades';
+$string['feedbackfor'] = 'Feedback for {$a}';
+$string['filtergrades'] = 'Show grades for {$a}.';
+$string['gradefor'] = 'Grade for {$a}';
+$string['noscreens'] = 'Could not find a suitable single view screen.';
+$string['gradeitemcannotbeoverridden'] = 'This grade item cannot be overridden.';
+$string['notvalid'] = 'Not a valid Single view screen: {$a}';
+$string['override'] = 'Override';
+$string['overrideall'] = 'Override all grades';
+$string['overridefor'] = 'Override for {$a}';
+$string['overridenone'] = 'Override no grades';
+$string['pluginname'] = 'Single view';
+$string['singleview:view'] = 'View report';
diff --git a/grade/report/singleview/lib.php b/grade/report/singleview/lib.php
new file mode 100755 (executable)
index 0000000..5382c6c
--- /dev/null
@@ -0,0 +1,112 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Base lib class for singleview functionality.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once($CFG->dirroot . '/grade/report/lib.php');
+
+/**
+ * This class is the main class that must be implemented by a grade report plugin.
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class gradereport_singleview extends grade_report {
+
+    /**
+     * Return the list of valid screens, used to validate the input.
+     *
+     * @return array List of screens.
+     */
+    public static function valid_screens() {
+        // This is a list of all the known classes representing a screen in this plugin.
+        return array('user', 'select', 'grade');
+    }
+
+    /**
+     * Process data from a form submission. Delegated to the current screen.
+     *
+     * @param array $data The data from the form
+     * @return array List of warnings
+     */
+    public function process_data($data) {
+        if (has_capability('moodle/grade:manage', $this->context)) {
+            return $this->screen->process($data);
+        }
+    }
+
+    /**
+     * Unused - abstract function declared in the parent class.
+     *
+     * @param string $target
+     * @param string $action
+     */
+    public function process_action($target, $action) {
+    }
+
+    /**
+     * Constructor for this report. Creates the appropriate screen class based on itemtype.
+     *
+     * @param int $courseid The course id.
+     * @param object $gpr grade plugin return tracking object
+     * @param context_course $context
+     * @param string $itemtype Should be user, select or grade
+     * @param int $itemid The id of the user or grade item
+     * @param int $groupid (optional) The current groupid.
+     */
+    public function __construct($courseid, $gpr, $context, $itemtype, $itemid, $groupid=null) {
+        parent::__construct($courseid, $gpr, $context);
+
+        $screenclass = "\\gradereport_singleview\\local\\screen\\${itemtype}";
+
+        $this->screen = new $screenclass($courseid, $itemid, $groupid);
+
+        // Load custom or predifined js.
+        $this->screen->js();
+
+        $base = '/grade/report/singleview/index.php';
+
+        $idparams = array('id' => $courseid);
+
+        $this->baseurl = new moodle_url($base, $idparams);
+
+        $this->pbarurl = new moodle_url($base, $idparams + array(
+            'item' => $itemtype,
+            'itemid' => $itemid
+        ));
+
+        $this->setup_groups();
+    }
+
+    /**
+     * Build the html for the screen.
+     * @return string HTML to display
+     */
+    public function output() {
+        global $OUTPUT;
+        return $OUTPUT->box($this->screen->html());
+    }
+}
+
diff --git a/grade/report/singleview/styles.css b/grade/report/singleview/styles.css
new file mode 100644 (file)
index 0000000..3c2cca7
--- /dev/null
@@ -0,0 +1,47 @@
+.path-grade-report-singleview div.generalbox {
+  margin: 0 20px 15px 20px;
+}
+
+.path-grade-report-singleview div.generalbox div.singleselect form div {
+  text-align: center;
+}
+
+.path-grade-report-singleview div.generalbox table.generaltable {
+  margin: 0 auto 15px auto;
+}
+
+.path-grade-report-singleview div.generalbox form div {
+  text-align: center;
+}
+
+.path-grade-report-singleview .singleview_buttons {
+    padding: 10px 0;
+}
+
+.path-grade-report-singleview div.generalbox h2 {
+   text-align: center;
+}
+
+.path-grade-report-singleview input[name^="finalgrade"] {
+    width: 50px;
+}
+
+.path-grade-report-singleview #region-main h2, .paging{
+   text-align: center;
+}
+
+.path-grade-report-singleview itemnav.previtem {
+   float:left;
+}
+.path-grade-report-singleview itemnav.previtem {
+   float:left;
+}
+.path-grade-report-singleview.dir-rtl small.previtem {
+   float:right;
+}
+.path-grade-report-singleview small.nextitem {
+   float:right;
+}
+.path-grade-report-singleview.dir-rtl small.nextitem {
+   float:left;
+}
diff --git a/grade/report/singleview/tests/behat/singleview.feature b/grade/report/singleview/tests/behat/singleview.feature
new file mode 100644 (file)
index 0000000..6ea0124
--- /dev/null
@@ -0,0 +1,88 @@
+@core @core_grades @gradereport_singleview
+Feature: We can use Single view
+  As a teacher
+  In order to view and edit grades
+  For users and activities for a course.
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "users" exist:
+      | username | firstname | lastname | email | idnumber | alternatename |
+      | teacher1 | Teacher | 1 | teacher1@asd.com | t1 | teacherbro |
+      | student1 | Student | 1 | student1@asd.com | s1 | studentbro |
+      | student2 | Student | 2 | student1@asd.com | s2 | studentjo |
+      | student3 | Student | 3 | student1@asd.com | s3 | studentlo |
+      | student4 | Student | 4 | student1@asd.com | s4 | studentawesemo |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+      | student3 | C1 | student |
+      | student4 | C1 | student |
+    And the following "grade categories" exist:
+      | fullname | course |
+      | Sub category 1 | C1|
+      | Sub category 2 | C1|
+    And the following "activities" exist:
+      | activity | course | idnumber | name | intro | grade |
+      | assign | C1 | a1 | Test assignment one | Submit something! | 300 |
+      | assign | C1 | a2 | Test assignment two | Submit something! | 100 |
+      | assign | C1 | a3 | Test assignment three | Submit something! | 150 |
+      | assign | C1 | a4 | Test assignment four | Submit nothing! | 150 |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Grades"
+
+ @javascript
+  Scenario: I can update grades, add feedback and exclude grades.
+    Given I click on "Single view" "option"
+    And I click on "studentawesemo (Student) 4" "option"
+    And I click on "Override for Test assignment one" "checkbox"
+    When I set the following fields to these values:
+        | Grade for Test assignment one | 10.00 |
+        | Feedback for Test assignment one | test data |
+    And I click on "Exclude for Test assignment four" "checkbox"
+    And I press "Update"
+    Then the following should exist in the "user-grades" table:
+        | Test assignment four |
+        | excluded |
+    And the following should exist in the "user-grades" table:
+        | Test assignment one |
+        | 10.00 |
+    And I click on "Single view for Test assignment three" "link"
+    And I click on "Override for studentbro (Student) 1" "checkbox"
+    And I set the following fields to these values:
+        | Grade for studentbro (Student) 1 | 12.05 |
+        | Feedback for studentbro (Student) 1 | test data2 |
+    And I click on "Exclude for studentjo (Student) 2" "checkbox"
+    And I press "Update"
+    And the following should exist in the "user-grades" table:
+        | Test assignment three |
+        | 12.05 |
+        | Excluded |
+
+  Scenario: Single view links work on grade report.
+    Given I follow "Single view for Test assignment one"
+    Then I should see "Test assignment one"
+    Then I follow "Grader report"
+    And I follow "Single view for Student 1"
+    Then I should see "Student 1"
+
+  @javascript
+  Scenario: Navigation works in the Single view.
+    Given I click on "Single view" "option"
+    Then I click on "studentbro (Student) 1" "option"
+    Then I should see "Student 1"
+    And I follow "studentjo (Student) 2"
+    Then I should see "Student 2"
+    And I follow "studentbro (Student) 1"
+    Then I should see "Student 1"
+    And I click on "Show grades for Test assignment four" "link"
+    Then I should see "Test assignment four"
+    And I follow "Test assignment three"
+    Then I should see "Test assignment three"
+    And I follow "Test assignment four"
+    Then I should see "Test assignment four"
diff --git a/grade/report/singleview/version.php b/grade/report/singleview/version.php
new file mode 100755 (executable)
index 0000000..e56813f
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Standard version file
+ *
+ * @package   gradereport_singleview
+ * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$plugin->component = 'gradereport_singleview'; // Full name of the plugin (used for diagnostics).
+$plugin->version  = 2013081002;
+$plugin->requires = 2010090501;
index 16212a9..5fb6426 100644 (file)
@@ -309,6 +309,7 @@ $string['gradereport'] = 'Grade report';
 $string['graderreport'] = 'Grader report';
 $string['grades'] = 'Grades';
 $string['gradesforuser'] = 'Grades for {$a->user}';
+$string['singleview'] = 'Single view for {$a}';
 $string['gradesonly'] = 'Grades only';
 $string['gradessettings'] = 'Grade settings';
 $string['gradetype'] = 'Grade type';
@@ -655,6 +656,7 @@ $string['showrank_help'] = 'Show the position of the student in relation to the
 $string['showuserimage'] = 'Show user profile images';
 $string['showuserimage_help'] = 'Whether to show the user\'s profile image next to the name in the grader report.';
 $string['showverbose'] = 'Show {$a->category} {$a->itemmodule} {$a->itemname}';
+$string['simpleview'] = 'Single view';
 $string['sitewide'] = 'Site-wide';
 $string['sort'] = 'sort';
 $string['sortasc'] = 'Sort in ascending order';
index 818832d..a6c409e 100644 (file)
@@ -1038,7 +1038,7 @@ class core_plugin_manager {
             ),
 
             'gradereport' => array(
-                'grader', 'history', 'outcomes', 'overview', 'user'
+                'grader', 'history', 'outcomes', 'overview', 'user', 'singleview'
             ),
 
             'gradingform' => array(
index 06f1863..2afe218 100644 (file)
@@ -848,9 +848,9 @@ function scorm_get_all_attempts($scormid, $userid) {
 }
 
 function scorm_view_display ($user, $scorm, $action, $cm) {
-    global $CFG, $DB, $PAGE, $OUTPUT, $COURSE;
+    global $CFG, $DB, $OUTPUT;
 
-    if ($scorm->scormtype != SCORM_TYPE_LOCAL && $scorm->updatefreq == SCORM_UPDATE_EVERYTIME) {
+    if ($scorm->updatefreq == SCORM_UPDATE_EVERYTIME) {
         scorm_parse($scorm, false);
     }
 
@@ -952,7 +952,7 @@ function scorm_simple_play($scorm, $user, $context, $cmid) {
         return $result;
     }
 
-    if ($scorm->scormtype != SCORM_TYPE_LOCAL && $scorm->updatefreq == SCORM_UPDATE_EVERYTIME) {
+    if ($scorm->updatefreq == SCORM_UPDATE_EVERYTIME) {
         scorm_parse($scorm, false);
     }
     $scoes = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '.
index af8334e..c097b67 100644 (file)
@@ -278,8 +278,9 @@ if (!empty($instanceid) && !empty($roleid)) {
                        AND anonymous = 0
                        AND contextlevel = :contextlevel
                        AND (origin = 'web' OR origin = 'ws')
-                  GROUP BY userid,timecreated) l ON (l.userid = ra.userid)
-             GROUP BY ra.userid, $usernamefields, u.idnumber";
+                  GROUP BY userid,timecreated) l ON (l.userid = ra.userid)";
+        // We add this after the WHERE statement that may come below.
+        $groupbysql = " GROUP BY ra.userid, $usernamefields, u.idnumber";
 
         $params['edulevel'] = core\event\base::LEVEL_PARTICIPATING;
         $params['contextlevel'] = CONTEXT_MODULE;
@@ -287,7 +288,7 @@ if (!empty($instanceid) && !empty($roleid)) {
         if ($twhere) {
             $sql .= ' WHERE '.$twhere; // Initial bar.
         }
-
+        $sql .= $groupbysql;
         if ($table->get_sql_sort()) {
             $sql .= ' ORDER BY '.$table->get_sql_sort();
         }