diff --git a/README.txt b/README.txt
index d23372d1..bc50dc2e 100644
--- a/README.txt
+++ b/README.txt
@@ -11,6 +11,7 @@ Students are presented with a simple chart showing how far they have progressed
==Changes==
+* 2016-09-09 - Major restructuring of checklist code, to aid future maintenance; dropping of pre-Moodle 2.7 support.
* 2016-05-20 - Minor behat fixes for Moodle 3.1 compatibility
* 2016-03-15 - Show/hide multiple activity items at once when editing the checklist (Tony Butler)
* 2015-12-23 - Handle missing calendar events + fix deprecated 'get_referer' warning.
diff --git a/classes/local/checklist_check.php b/classes/local/checklist_check.php
new file mode 100644
index 00000000..7a1288cb
--- /dev/null
+++ b/classes/local/checklist_check.php
@@ -0,0 +1,128 @@
+.
+
+/**
+ * Holds the checkmark information
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_checklist\local;
+
+use data_object;
+
+defined('MOODLE_INTERNAL') || die();
+global $CFG;
+require_once($CFG->dirroot.'/completion/data_object.php');
+
+class checklist_check extends data_object {
+ public $table = 'checklist_check';
+ public $required_fields = [
+ 'id', 'item', 'userid', 'usertimestamp', 'teachermark', 'teachertimestamp', 'teacherid'
+ ];
+
+ // DB fields.
+ public $item;
+ public $userid;
+ public $usertimestamp = 0;
+ public $teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
+ public $teachertimestamp = 0;
+ public $teacherid = null;
+
+ public static function fetch($params) {
+ return self::fetch_helper('checklist_check', __CLASS__, $params);
+ }
+
+ public static function fetch_all($params, $sort = false) {
+ $ret = self::fetch_all_helper('checklist_check', __CLASS__, $params);
+ if (!$ret) {
+ $ret = [];
+ }
+ return $ret;
+ }
+
+ /**
+ * @param $userid
+ * @param $itemids
+ * @return checklist_check[] $itemid => $check
+ */
+ public static function fetch_by_userid_itemids($userid, $itemids) {
+ global $DB;
+
+ $ret = [];
+ if (!$itemids) {
+ return $ret;
+ }
+
+ list($isql, $params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED);
+ $params['userid'] = $userid;
+ $checks = $DB->get_records_select('checklist_check', "userid = :userid AND item $isql", $params);
+ foreach ($checks as $check) {
+ $ret[$check->item] = new checklist_check();
+ self::set_properties($ret[$check->item], $check);
+ }
+ return $ret;
+ }
+
+ public static function teachermark_valid($teachermark) {
+ return in_array($teachermark, [CHECKLIST_TEACHERMARK_YES, CHECKLIST_TEACHERMARK_NO, CHECKLIST_TEACHERMARK_UNDECIDED]);
+ }
+
+ protected function check_fields_valid() {
+ if (!self::teachermark_valid($this->teachermark)) {
+ debugging('Unexpected teachermark value: '.$this->teachermark);
+ $this->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
+ }
+ }
+
+ public function save() {
+ if ($this->id) {
+ $this->update();
+ } else {
+ $this->insert();
+ }
+ }
+
+ public function insert() {
+ $this->check_fields_valid();
+ return parent::insert();
+ }
+
+ public function update() {
+ $this->check_fields_valid();
+ return parent::update();
+ }
+
+ public function is_checked_student() {
+ return $this->usertimestamp > 0;
+ }
+
+ public function is_checked_teacher() {
+ return ($this->teachermark == CHECKLIST_TEACHERMARK_YES);
+ }
+
+ public function set_teachermark($teachermark, $teacherid) {
+ $this->teachermark = $teachermark;
+ $this->teacherid = $teacherid;
+ $this->teachertimestamp = time();
+ }
+
+ public function set_checked_student($checked) {
+ $this->usertimestamp = $checked ? time() : 0;
+ }
+}
diff --git a/classes/local/checklist_comment.php b/classes/local/checklist_comment.php
new file mode 100644
index 00000000..f1014019
--- /dev/null
+++ b/classes/local/checklist_comment.php
@@ -0,0 +1,130 @@
+.
+
+/**
+ * A comment added, by a teacher, to a checklist item
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_checklist\local;
+
+use data_object;
+use moodle_url;
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot.'/completion/data_object.php');
+
+class checklist_comment extends data_object {
+ public $table = 'checklist_comment';
+ public $required_fields = [
+ 'id', 'itemid', 'userid', 'commentby', 'text'
+ ];
+
+ // DB fields.
+ public $itemid;
+ public $userid;
+ public $commentby;
+ public $text;
+
+ // Extra data.
+ protected $commentbyname = null;
+
+ protected static $courseid = null;
+
+ public static function fetch($params) {
+ return self::fetch_helper('checklist_comment', __CLASS__, $params);
+ }
+
+ public static function fetch_all($params, $sort = false) {
+ $ret = self::fetch_all_helper('checklist_comment', __CLASS__, $params);
+ if (!$ret) {
+ $ret = [];
+ }
+ return $ret;
+ }
+
+ /**
+ * @param int $userid
+ * @param int[] $itemids
+ * @return checklist_comment[] $itemid => $check
+ */
+ public static function fetch_by_userid_itemids($userid, $itemids) {
+ global $DB;
+
+ $ret = [];
+ if (!$itemids) {
+ return $ret;
+ }
+
+ list($isql, $params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED);
+ $params['userid'] = $userid;
+ $comments = $DB->get_records_select('checklist_comment', "userid = :userid AND itemid $isql", $params);
+ foreach ($comments as $comment) {
+ $ret[$comment->itemid] = new checklist_comment();
+ self::set_properties($ret[$comment->itemid], $comment);
+ }
+ return $ret;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function get_commentby_name() {
+ return $this->commentbyname;
+ }
+
+ /**
+ * @return moodle_url
+ */
+ public function get_commentby_url() {
+ return new moodle_url('/user/view.php', ['id' => $this->commentby, 'course' => self::$courseid]);
+ }
+
+ /**
+ * @param checklist_comment[] $comments
+ */
+ public static function add_commentby_names($comments) {
+ global $DB;
+
+ $userids = [];
+ foreach ($comments as $comment) {
+ if ($comment->commentby) {
+ $userids[] = $comment->commentby;
+ }
+ }
+ if (!$userids) {
+ return;
+ }
+
+ $commentusers = $DB->get_records_list('user', 'id', $userids, '', 'id,'.get_all_user_name_fields(true));
+ foreach ($comments as $comment) {
+ if ($comment->commentby) {
+ if (isset($commentusers[$comment->commentby])) {
+ $comment->commentbyname = fullname($commentusers[$comment->commentby]);
+ }
+ }
+ }
+ }
+
+ public static function set_courseid($courseid) {
+ self::$courseid = $courseid;
+ }
+}
\ No newline at end of file
diff --git a/classes/local/checklist_item.php b/classes/local/checklist_item.php
new file mode 100644
index 00000000..ba093dfd
--- /dev/null
+++ b/classes/local/checklist_item.php
@@ -0,0 +1,313 @@
+.
+
+/**
+ * Class to hold a checklist item.
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_checklist\local;
+
+use data_object;
+
+defined('MOODLE_INTERNAL') || die();
+global $CFG;
+require_once($CFG->dirroot.'/completion/data_object.php');
+
+class checklist_item extends data_object {
+ public $table = 'checklist_item';
+ public $required_fields = [
+ 'id', 'checklist', 'userid', 'displaytext', 'position', 'indent', 'itemoptional', 'duetime',
+ 'eventid', 'colour', 'moduleid', 'hidden', 'grouping'
+ ];
+
+ // DB fields.
+ public $checklist;
+ public $userid;
+ public $displaytext;
+ public $position;
+ public $indent = 0;
+ public $itemoptional = CHECKLIST_OPTIONAL_NO;
+ public $duetime = 0;
+ public $eventid = 0;
+ public $colour = 'black';
+ public $moduleid = 0;
+ public $hidden = CHECKLIST_HIDDEN_NO;
+ public $grouping = 0;
+
+ // Extra status fields (for a particular student).
+ public $usertimestamp = 0;
+ public $teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
+ public $teachertimestamp = 0;
+ public $teacherid = null;
+
+ protected $teachername = null;
+ /** @var checklist_comment|null */
+ protected $comment = null;
+ protected $editme = false;
+
+ public static function fetch($params) {
+ return self::fetch_helper('checklist_item', __CLASS__, $params);
+ }
+
+ public static function fetch_all($params, $sort = false) {
+ $ret = self::fetch_all_helper('checklist_item', __CLASS__, $params);
+ if (!$ret) {
+ $ret = [];
+ }
+ if ($sort) {
+ self::sort_items($ret);
+ }
+ return $ret;
+ }
+
+ public static function sort_items(&$items) {
+ if (!$items) {
+ return;
+ }
+ uasort($items, function (checklist_item $a, checklist_item $b) {
+ if ($a->position < $b->position) {
+ return -1;
+ }
+ if ($a->position > $b->position) {
+ return 1;
+ }
+ // Sort by id, if the positions are the same.
+ if ($a->id < $b->id) {
+ return -1;
+ }
+ if ($a->id > $b->id) {
+ return 1;
+ }
+ return 0;
+ });
+ }
+
+ public function store_status($usertimestamp = null, $teachermark = null, $teachertimestamp = null, $teacherid = null) {
+ if ($usertimestamp !== null) {
+ $this->usertimestamp = $usertimestamp;
+ }
+ if ($teachermark !== null) {
+ if (!checklist_check::teachermark_valid($teachermark)) {
+ debugging('Unexpected teachermark value: '.$teachermark);
+ $teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
+ }
+ $this->teachermark = $teachermark;
+ }
+ if ($teachertimestamp !== null) {
+ $this->teachertimestamp = $teachertimestamp;
+ }
+ if ($teacherid !== null) {
+ $this->teacherid = $teacherid;
+ }
+ }
+
+ public function is_checked($byteacher) {
+ if ($this->userid > 0 || !$byteacher) {
+ // User custom items are always checked-off by students (regardless of checklist settings).
+ return $this->usertimestamp > 0;
+ } else {
+ return ($this->teachermark == CHECKLIST_TEACHERMARK_YES);
+ }
+ }
+
+ public function is_checked_teacher() {
+ return $this->is_checked(true);
+ }
+
+ public function is_checked_student() {
+ return $this->is_checked(false);
+ }
+
+ public function is_heading() {
+ return ($this->itemoptional == CHECKLIST_OPTIONAL_HEADING);
+ }
+
+ public function is_required() {
+ return ($this->itemoptional == CHECKLIST_OPTIONAL_NO);
+ }
+
+ public function is_optional() {
+ return ($this->itemoptional == CHECKLIST_OPTIONAL_YES);
+ }
+
+ public function get_teachermark_image_url() {
+ global $OUTPUT;
+ static $images = null;
+ if ($images === null) {
+ $images = [
+ CHECKLIST_TEACHERMARK_YES => $OUTPUT->pix_url('tick_box', 'mod_checklist'),
+ CHECKLIST_TEACHERMARK_NO => $OUTPUT->pix_url('cross_box', 'mod_checklist'),
+ CHECKLIST_TEACHERMARK_UNDECIDED => $OUTPUT->pix_url('empty_box', 'mod_checklist'),
+ ];
+ }
+ return $images[$this->teachermark];
+ }
+
+ public function get_teachermark_text() {
+ static $text = null;
+ if ($text === null) {
+ $text = [
+ CHECKLIST_TEACHERMARK_YES => get_string('teachermarkyes', 'mod_checklist'),
+ CHECKLIST_TEACHERMARK_NO => get_string('teachermarkno', 'mod_checklist'),
+ CHECKLIST_TEACHERMARK_UNDECIDED => get_string('teachermarkundecided', 'mod_checklist'),
+ ];
+ }
+ return $text[$this->teachermark];
+ }
+
+ public function get_teachermark_class() {
+ static $classes = null;
+ if ($classes === null) {
+ $classes = [
+ CHECKLIST_TEACHERMARK_YES => 'teachermarkyes',
+ CHECKLIST_TEACHERMARK_NO => 'teachermarkno',
+ CHECKLIST_TEACHERMARK_UNDECIDED => 'teachermarkundecided',
+ ];
+ }
+ return $classes[$this->teachermark];
+ }
+
+ public function toggle_hidden() {
+ if ($this->hidden == CHECKLIST_HIDDEN_BYMODULE) {
+ return; // Do not override items linked to hidden Moodle activities.
+ }
+ if ($this->hidden == CHECKLIST_HIDDEN_NO) {
+ $this->hidden = CHECKLIST_HIDDEN_MANUAL;
+ } else {
+ $this->hidden = CHECKLIST_HIDDEN_NO;
+ }
+ $this->update();
+ }
+
+ public function hide_item() {
+ if (!$this->moduleid) {
+ return;
+ }
+ if ($this->hidden != CHECKLIST_HIDDEN_NO) {
+ return;
+ }
+ $this->hidden = CHECKLIST_HIDDEN_MANUAL;
+ $this->update();
+ }
+
+ public function show_item() {
+ if (!$this->moduleid) {
+ return;
+ }
+ if ($this->hidden != CHECKLIST_HIDDEN_MANUAL) {
+ return;
+ }
+ $this->hidden = CHECKLIST_HIDDEN_NO;
+ $this->update();
+ }
+
+ public function set_checked_student($userid, $checked) {
+ if ($checked == $this->is_checked_student()) {
+ return false; // No change.
+ }
+
+ // Update checkmark in the database.
+ $check = new checklist_check(['item' => $this->id, 'userid' => $userid]);
+ $check->set_checked_student($checked);
+ $check->save();
+
+ // Update the stored value in this item.
+ $this->usertimestamp = $check->usertimestamp;
+ return true;
+ }
+
+ public function set_teachermark($userid, $teachermark, $teacherid) {
+ if ($teachermark == $this->teachermark) {
+ return false; // No change.
+ }
+
+ if (!checklist_check::teachermark_valid($teachermark)) {
+ throw new \coding_exception('Invalid teachermark '.$teachermark);
+ }
+
+ // Update checkmark in the database.
+ $check = new checklist_check(['item' => $this->id, 'userid' => $userid]);
+ $check->set_teachermark($teachermark, $teacherid);
+ $check->save();
+
+ // Update the stored value in this item.
+ $this->teachertimestamp = $check->teachertimestamp;
+ $this->teachermark = $check->teachermark;
+ $this->teacherid = $check->teacherid;
+
+ return true;
+ }
+
+ public function get_teachername() {
+ return $this->teachername;
+ }
+
+ public function get_comment() {
+ return $this->comment;
+ }
+
+ public function set_editme($editme = true) {
+ $this->editme = $editme;
+ }
+
+ public function is_editme() {
+ return $this->editme;
+ }
+
+ /**
+ * Add links from the checklist items to the comments on them (for a particular user).
+ * @param checklist_item[] $items (indexed by id)
+ * @param checklist_comment[] $comments (indexed by itemid)
+ */
+ public static function add_comments($items, $comments) {
+ foreach ($items as $item) {
+ if (isset($comments[$item->id])) {
+ $item->comment = $comments[$item->id];
+ }
+ }
+ }
+
+ /**
+ * Add the names of all the teachers who have updated the checklist items.
+ * @param checklist_item[] $items
+ */
+ public static function add_teacher_names($items) {
+ global $DB;
+
+ $userids = [];
+ foreach ($items as $item) {
+ if ($item->teacherid) {
+ $userids[] = $item->teacherid;
+ }
+ }
+ if (!$userids) {
+ return;
+ }
+
+ $teachers = $DB->get_records_list('user', 'id', $userids, '', 'id,'.get_all_user_name_fields(true));
+ foreach ($items as $item) {
+ if ($item->teacherid) {
+ if (isset($teachers[$item->teacherid])) {
+ $item->teachername = fullname($teachers[$item->teacherid]);
+ }
+ }
+ }
+ }
+}
diff --git a/classes/local/output_status.php b/classes/local/output_status.php
new file mode 100644
index 00000000..3e5cc22f
--- /dev/null
+++ b/classes/local/output_status.php
@@ -0,0 +1,359 @@
+.
+
+/**
+ * Stores fields that define the status of the checklist output
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_checklist\local;
+
+defined('MOODLE_INTERNAL') || die();
+
+class output_status {
+ // All output.
+ protected $additemafter = 0;
+
+ // View items only.
+ protected $viewother = false;
+ protected $userreport = false;
+ protected $teachercomments = false;
+ protected $editcomments = false;
+ protected $teachermarklocked = false;
+ protected $showcompletiondates = false;
+ protected $canupdateown = false;
+ protected $canaddown = false;
+ protected $addown = false;
+ protected $showprogressbar = false;
+ protected $showteachermark = false;
+ protected $showcheckbox = false;
+ protected $overrideauto = false;
+ protected $checkgroupings = false;
+ protected $updateform = false;
+
+ // Edit items only.
+ protected $editdates = false;
+ protected $itemid = null;
+ protected $autopopulate = false;
+ protected $autoupdatewarning = null;
+
+ /**
+ * Viewing another user (i.e. teacher report about a single user)
+ * @return boolean
+ */
+ public function is_viewother() {
+ return $this->viewother;
+ }
+
+ /**
+ * @param boolean $viewother
+ */
+ public function set_viewother($viewother) {
+ $this->viewother = $viewother;
+ }
+
+ /**
+ * Viewing complete user report (so no updating of checkmarks)
+ * @return boolean
+ */
+ public function is_userreport() {
+ return $this->userreport;
+ }
+
+ /**
+ * @param boolean $userreport
+ */
+ public function set_userreport($userreport) {
+ $this->userreport = $userreport;
+ }
+
+ /**
+ * Are teacher comments enabled for this instance?
+ * @return boolean
+ */
+ public function is_teachercomments() {
+ return $this->teachercomments;
+ }
+
+ /**
+ * @param boolean $teachercomments
+ */
+ public function set_teachercomments($teachercomments) {
+ $this->teachercomments = $teachercomments;
+ }
+
+ /**
+ * Is the user editing comments at the moment?
+ * @return boolean
+ */
+ public function is_editcomments() {
+ return $this->editcomments;
+ }
+
+ /**
+ * @param boolean $editcomments
+ */
+ public function set_editcomments($editcomments) {
+ $this->editcomments = $editcomments;
+ }
+
+ /**
+ * Are completed teacher marks locked (so the current user can't update them)?
+ * @return boolean
+ */
+ public function is_teachermarklocked() {
+ return $this->teachermarklocked;
+ }
+
+ /**
+ * @param boolean $teachermarklocked
+ */
+ public function set_teachermarklocked($teachermarklocked) {
+ $this->teachermarklocked = $teachermarklocked;
+ }
+
+ /**
+ * Should the completion dates be output?
+ * @return boolean
+ */
+ public function is_showcompletiondates() {
+ return $this->showcompletiondates;
+ }
+
+ /**
+ * @param boolean $showcompletiondates
+ */
+ public function set_showcompletiondates($showcompletiondates) {
+ $this->showcompletiondates = $showcompletiondates;
+ }
+
+ /**
+ * Can the user update their own checkmarks (students).
+ * @return boolean
+ */
+ public function is_canupdateown() {
+ return $this->canupdateown;
+ }
+
+ /**
+ * @param boolean $canupdateown
+ */
+ public function set_canupdateown($canupdateown) {
+ $this->canupdateown = $canupdateown;
+ }
+
+ /**
+ * Should the progress bar be shown?
+ * @return boolean
+ */
+ public function is_showprogressbar() {
+ return $this->showprogressbar;
+ }
+
+ /**
+ * @param boolean $showprogressbar
+ */
+ public function set_showprogressbar($showprogressbar) {
+ $this->showprogressbar = $showprogressbar;
+ }
+
+ /**
+ * Should the teacher mark be shown?
+ * @return boolean
+ */
+ public function is_showteachermark() {
+ return $this->showteachermark;
+ }
+
+ /**
+ * @param boolean $showteachermark
+ */
+ public function set_showteachermark($showteachermark) {
+ $this->showteachermark = $showteachermark;
+ }
+
+ /**
+ * Should the student mark be shown?
+ * @return boolean
+ */
+ public function is_showcheckbox() {
+ return $this->showcheckbox;
+ }
+
+ /**
+ * @param boolean $showcheckbox
+ */
+ public function set_showcheckbox($showcheckbox) {
+ $this->showcheckbox = $showcheckbox;
+ }
+
+ /**
+ * Can the user override automatically-calculated checkbox items (linked to activity completion)?
+ * @return boolean
+ */
+ public function is_overrideauto() {
+ return $this->overrideauto;
+ }
+
+ /**
+ * @param boolean $overrideauto
+ */
+ public function set_overrideauto($overrideauto) {
+ $this->overrideauto = $overrideauto;
+ }
+
+ /**
+ * Should items be checked against groupings, for visibility purposes?
+ * @return boolean
+ */
+ public function is_checkgroupings() {
+ return $this->checkgroupings;
+ }
+
+ /**
+ * @param boolean $checkgroupings
+ */
+ public function set_checkgroupings($checkgroupings) {
+ $this->checkgroupings = $checkgroupings;
+ }
+
+ /**
+ * Can the student add their own items?
+ * @return boolean
+ */
+ public function is_canaddown() {
+ return $this->canaddown;
+ }
+
+ /**
+ * @param boolean $canaddown
+ */
+ public function set_canaddown($canaddown) {
+ $this->canaddown = $canaddown;
+ }
+
+ /**
+ * Is the user currently adding/editing their own items?
+ * @return boolean
+ */
+ public function is_addown() {
+ return $this->addown;
+ }
+
+ /**
+ * @param boolean $addown
+ */
+ public function set_addown($addown) {
+ $this->addown = $addown;
+ }
+
+ /**
+ * Output 'add item' fields after this item.
+ * @return int
+ */
+ public function get_additemafter() {
+ return $this->additemafter;
+ }
+
+ /**
+ * @param int $additemafter
+ */
+ public function set_additemafter($additemafter) {
+ $this->additemafter = $additemafter;
+ }
+
+ /**
+ * Should an update form be output?
+ * @return boolean
+ */
+ public function is_updateform() {
+ return $this->updateform;
+ }
+
+ /**
+ * @param boolean $updateform
+ */
+ public function set_updateform($updateform) {
+ $this->updateform = $updateform;
+ }
+
+ /**
+ * Is date editing enabled?
+ * @return boolean
+ */
+ public function is_editdates() {
+ return $this->editdates;
+ }
+
+ /**
+ * @param boolean $editdates
+ */
+ public function set_editdates($editdates) {
+ $this->editdates = $editdates;
+ }
+
+ /**
+ * The ID of the item being edited (to generate the correct URLs).
+ * @return int|null
+ */
+ public function get_itemid() {
+ return $this->itemid;
+ }
+
+ /**
+ * @param null $itemid
+ */
+ public function set_itemid($itemid) {
+ $this->itemid = $itemid;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function is_autopopulate() {
+ return $this->autopopulate;
+ }
+
+ /**
+ * @param boolean $autopopulate
+ */
+ public function set_autopopulate($autopopulate) {
+ $this->autopopulate = $autopopulate;
+ }
+
+ /**
+ * Should the autoupdate warning be shown and, if so, what type?
+ * @return int|null
+ */
+ public function get_autoupdatewarning() {
+ return $this->autoupdatewarning;
+ }
+
+ public function is_autoupdatewarning() {
+ return ($this->autoupdatewarning !== null);
+ }
+
+ /**
+ * @param boolean $autoupdatewarning
+ */
+ public function set_autoupdatewarning($autoupdatewarning) {
+ $this->autoupdatewarning = $autoupdatewarning;
+ }
+
+}
\ No newline at end of file
diff --git a/classes/local/progress_info.php b/classes/local/progress_info.php
new file mode 100644
index 00000000..90c939f3
--- /dev/null
+++ b/classes/local/progress_info.php
@@ -0,0 +1,48 @@
+.
+
+/**
+ * Information about the student's progress, to pass on to the progress bar output
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_checklist\local;
+
+defined('MOODLE_INTERNAL') || die();
+
+class progress_info {
+ public $totalitems;
+ public $requireditems;
+ public $allcompleteitems;
+ public $requiredcompleteitems;
+
+ /**
+ * progress_info constructor.
+ * @param $totalitems
+ * @param $requireditems
+ * @param $allcompleteitems
+ * @param $requiredcompleteitems
+ */
+ public function __construct($totalitems, $requireditems, $allcompleteitems, $requiredcompleteitems) {
+ $this->totalitems = $totalitems;
+ $this->requireditems = $requireditems;
+ $this->allcompleteitems = $allcompleteitems;
+ $this->requiredcompleteitems = $requiredcompleteitems;
+ }
+}
diff --git a/edit.php b/edit.php
index 406c1567..fae036bb 100644
--- a/edit.php
+++ b/edit.php
@@ -22,7 +22,7 @@
$id = required_param('id', PARAM_INT); // Course_module ID.
-$url = new moodle_url('/mod/checklist/view.php', array('id' => $id));
+$url = new moodle_url('/mod/checklist/edit.php', array('id' => $id));
$cm = get_coursemodule_from_id('checklist', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
diff --git a/import.php b/import.php
index 3dbdce14..6032cbb8 100644
--- a/import.php
+++ b/import.php
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see .
+use mod_checklist\local\checklist_item;
+
require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once(dirname(__FILE__).'/importexportfields.php');
global $CFG, $PAGE, $OUTPUT, $DB;
@@ -159,7 +161,7 @@ function cleanrow($separator, $row) {
}
$itemfield = reset($item);
- $newitem = new stdClass;
+ $newitem = new checklist_item();
$newitem->checklist = $checklist->id;
$newitem->position = $position++;
$newitem->userid = 0;
@@ -214,7 +216,7 @@ function cleanrow($separator, $row) {
}
if ($newitem->displaytext) { // Don't insert items without any text in them.
- if (!$DB->insert_record('checklist_item', $newitem)) {
+ if (!$newitem->insert()) {
$ok = false;
$errormsg = 'Unable to insert DB record for item';
break;
diff --git a/lib.php b/lib.php
index 53dbafc4..d2bb423a 100644
--- a/lib.php
+++ b/lib.php
@@ -185,14 +185,14 @@ function checklist_update_all_grades() {
function checklist_update_grades($checklist, $userid = 0) {
global $CFG, $DB;
- $items = $DB->get_records('checklist_item',
- array(
- 'checklist' => $checklist->id,
- 'userid' => 0,
- 'itemoptional' => CHECKLIST_OPTIONAL_NO,
- 'hidden' => CHECKLIST_HIDDEN_NO
- ),
- '', 'id, grouping');
+ $params = array(
+ 'checklist' => $checklist->id,
+ 'userid' => 0,
+ 'itemoptional' => CHECKLIST_OPTIONAL_NO,
+ 'hidden' => CHECKLIST_HIDDEN_NO
+ );
+ $items = \mod_checklist\local\checklist_item::fetch_all($params);
+
if (!$items) {
return;
}
@@ -238,16 +238,17 @@ function checklist_update_grades($checklist, $userid = 0) {
$groupings = checklist_class::get_user_groupings($userid, $course->id);
$total = 0;
- $itemlist = '';
+ $itemlist = [];
foreach ($items as $item) {
if ($item->grouping) {
if (!in_array($item->grouping, $groupings)) {
continue;
}
}
- $itemlist .= $item->id.',';
+ $itemlist[] = $item->id;
$total++;
}
+ $itemlist = implode(',', $itemlist);
if (!$total) { // No items - set score to 0.
$ugrade = new stdClass;
@@ -256,8 +257,6 @@ function checklist_update_grades($checklist, $userid = 0) {
$ugrade->date = time();
} else {
- $itemlist = substr($itemlist, 0, -1); // Remove trailing ','.
-
$sql = 'SELECT (SUM(CASE WHEN '.$where.' THEN 1 ELSE 0 END) * ? / ? ) AS rawgrade'.$date;
$sql .= " FROM {checklist_check} c ";
$sql .= " WHERE c.item IN ($itemlist)";
diff --git a/locallib.php b/locallib.php
index 7e695bd7..1aae194e 100644
--- a/locallib.php
+++ b/locallib.php
@@ -21,6 +21,11 @@
* @package mod/checklist
*/
+use mod_checklist\local\checklist_check;
+use mod_checklist\local\checklist_comment;
+use mod_checklist\local\checklist_item;
+use mod_checklist\local\output_status;
+
require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once(dirname(__FILE__).'/lib.php');
@@ -41,13 +46,17 @@ class checklist_class {
protected $strchecklist;
protected $context;
protected $userid;
+ /** @var checklist_item[] */
protected $items;
+ /** @var checklist_item[] */
protected $useritems;
protected $useredit;
protected $additemafter;
protected $editdates;
/** @var bool|int[] */
protected $groupings;
+ /** @var mod_checklist_renderer */
+ protected $output;
/**
* @param int|string $cmid optional
@@ -64,6 +73,8 @@ public function __construct($cmid = 'staticonly', $userid = 0, $checklist = null
return;
}
+ $this->output = self::get_renderer();
+
$this->userid = $userid;
if ($cm) {
@@ -81,6 +92,7 @@ public function __construct($cmid = 'staticonly', $userid = 0, $checklist = null
} else {
$this->course = $DB->get_record('course', array('id' => $this->cm->course), '*', MUST_EXIST);
}
+ checklist_comment::set_courseid($this->course->id);
if ($checklist) {
$this->checklist = $checklist;
@@ -106,6 +118,14 @@ public function __construct($cmid = 'staticonly', $userid = 0, $checklist = null
}
}
+ /**
+ * @return mod_checklist_renderer
+ */
+ private static function get_renderer() {
+ global $PAGE;
+ return $PAGE->get_renderer('mod_checklist');
+ }
+
/**
* Get an array of the items in a checklist
*
@@ -114,17 +134,14 @@ protected function get_items() {
global $DB;
// Load all shared checklist items.
- $this->items = $DB->get_records('checklist_item', array('checklist' => $this->checklist->id, 'userid' => 0), 'position');
+ $this->items = checklist_item::fetch_all(['checklist' => $this->checklist->id, 'userid' => 0], true);
// Makes sure all items are numbered sequentially, starting at 1.
$this->update_item_positions();
// Load student's own checklist items.
if ($this->userid && $this->canaddown()) {
- $this->useritems = $DB->get_records('checklist_item', array(
- 'checklist' => $this->checklist->id,
- 'userid' => $this->userid
- ), 'position, id');
+ $this->useritems = checklist_item::fetch_all(['checklist' => $this->checklist->id, 'userid' => $this->userid], true);
} else {
$this->useritems = false;
}
@@ -142,14 +159,10 @@ protected function get_items() {
$id = $check->id;
if (isset($this->items[$id])) {
- $this->items[$id]->checked = $check->usertimestamp > 0;
- $this->items[$id]->teachermark = $check->teachermark;
- $this->items[$id]->usertimestamp = $check->usertimestamp;
- $this->items[$id]->teachertimestamp = $check->teachertimestamp;
- $this->items[$id]->teacherid = $check->teacherid;
+ $this->items[$id]->store_status($check->usertimestamp, $check->teachermark,
+ $check->teachertimestamp, $check->teacherid);
} else if ($this->useritems && isset($this->useritems[$id])) {
- $this->useritems[$id]->checked = $check->usertimestamp > 0;
- $this->useritems[$id]->usertimestamp = $check->usertimestamp;
+ $this->useritems[$id]->store_status($check->usertimestamp);
// User items never have a teacher mark to go with them.
}
}
@@ -383,8 +396,6 @@ protected function removeauto() {
* @param bool $end (optional) - where to stop offsetting positions
*/
protected function update_item_positions($move = 0, $start = 1, $end = false) {
- global $DB;
-
$pos = 1;
if (!$this->items) {
@@ -398,10 +409,8 @@ protected function update_item_positions($move = 0, $start = 1, $end = false) {
if ($item->position != $pos) {
$oldpos = $item->position;
$item->position = $pos;
- $upditem = new stdClass;
- $upditem->id = $item->id;
- $upditem->position = $pos;
- $DB->update_record('checklist_item', $upditem);
+ $item->update();
+
if ($oldpos == $end) {
break;
}
@@ -693,11 +702,9 @@ protected function view_tabs($currenttab) {
print_tabs($tabs, $currenttab, $inactive, $activated);
}
- protected function view_progressbar() {
- global $OUTPUT;
-
+ protected function get_progress() {
if (!$this->items) {
- return;
+ return null;
}
$teacherprogress = ($this->checklist->teacheredit != CHECKLIST_MARKING_STUDENT);
@@ -706,9 +713,9 @@ protected function view_progressbar() {
$requireditems = 0;
$completeitems = 0;
$allcompleteitems = 0;
- $checkgroupings = $this->checklist->autopopulate && ($this->groupings !== false);
+ $checkgroupings = ($this->groupings !== false);
foreach ($this->items as $item) {
- if (($item->itemoptional == CHECKLIST_OPTIONAL_HEADING) || ($item->hidden)) {
+ if (($item->is_heading()) || ($item->hidden)) {
continue;
}
if ($checkgroupings && !empty($item->grouping)) {
@@ -716,30 +723,23 @@ protected function view_progressbar() {
continue; // Current user is not a member of this item's grouping.
}
}
- if ($item->itemoptional == CHECKLIST_OPTIONAL_NO) {
+ if ($item->is_required()) {
$requireditems++;
- if ($teacherprogress) {
- if ($item->teachermark == CHECKLIST_TEACHERMARK_YES) {
- $completeitems++;
- $allcompleteitems++;
- }
- } else if ($item->checked) {
+ if ($item->is_checked($teacherprogress)) {
$completeitems++;
$allcompleteitems++;
}
- } else if ($teacherprogress) {
- if ($item->teachermark == CHECKLIST_TEACHERMARK_YES) {
+ } else {
+ if ($item->is_checked($teacherprogress)) {
$allcompleteitems++;
}
- } else if ($item->checked) {
- $allcompleteitems++;
}
$totalitems++;
}
if (!$teacherprogress) {
if ($this->useritems) {
foreach ($this->useritems as $item) {
- if ($item->checked) {
+ if ($item->is_checked_student()) {
$allcompleteitems++;
}
$totalitems++;
@@ -747,617 +747,108 @@ protected function view_progressbar() {
}
}
if ($totalitems == 0) {
- return;
+ return null;
}
- $allpercentcomplete = ($allcompleteitems * 100) / $totalitems;
-
- if ($requireditems > 0 && $totalitems > $requireditems) {
- $percentcomplete = ($completeitems * 100) / $requireditems;
- echo '
';
- echo get_string('percentcomplete', 'checklist').': ';
- echo '
';
- echo '';
- echo '';
- echo '
';
- echo '
';
- echo '
';
- echo ' '.sprintf('%0d', $percentcomplete).'% ';
- echo ' ';
- echo ' ';
- }
-
- echo '';
- echo get_string('percentcompleteall', 'checklist').': ';
- echo '
';
- echo '';
- echo '';
- echo '
';
- echo '
';
- echo '
';
- echo ' '.sprintf('%0d', $allpercentcomplete).'% ';
- echo ' ';
- echo ' ';
- }
-
- protected function get_teachermark($itemid) {
- global $OUTPUT;
-
- if (!isset($this->items[$itemid])) {
- return array('', '');
- }
- switch ($this->items[$itemid]->teachermark) {
- case CHECKLIST_TEACHERMARK_YES:
- return array(
- $OUTPUT->pix_url('tick_box', 'checklist'),
- get_string('teachermarkyes', 'checklist'),
- 'teachermarkyes'
- );
-
- case CHECKLIST_TEACHERMARK_NO:
- return array(
- $OUTPUT->pix_url('cross_box', 'checklist'),
- get_string('teachermarkno', 'checklist'),
- 'teachermarkno'
- );
-
- default:
- return array(
- $OUTPUT->pix_url('empty_box', 'checklist'),
- get_string('teachermarkundecided', 'checklist'),
- 'teachermarkundecided'
- );
- }
+ return new \mod_checklist\local\progress_info($totalitems, $requireditems, $allcompleteitems, $completeitems);
}
+ /**
+ * @param bool $viewother
+ * @param bool $userreport
+ */
protected function view_items($viewother = false, $userreport = false) {
- global $DB, $OUTPUT, $PAGE, $CFG;
-
- echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter checklistbox');
-
- echo html_writer::tag('div', ' ', array('id' => 'checklistspinner'));
-
- $comments = $this->checklist->teachercomments;
- $editcomments = false;
- $thispage = new moodle_url('/mod/checklist/view.php', array('id' => $this->cm->id));
-
- $teachermarklocked = false;
- $showcompletiondates = false;
- $strteachername = '';
- $struserdate = '';
- $strteacherdate = '';
- if ($viewother) {
- if ($comments) {
- $editcomments = optional_param('editcomments', false, PARAM_BOOL);
- }
- $thispage = new moodle_url('/mod/checklist/report.php', array('id' => $this->cm->id, 'studentid' => $this->userid));
-
- if (!$student = $DB->get_record('user', array('id' => $this->userid))) {
- error('No such user!');
- }
-
- echo ''.get_string('checklistfor', 'checklist').' '.fullname($student, true).' ';
- echo ' ';
- echo '';
-
- if (!$editcomments) {
- echo '';
- }
- echo '';
-
- $teachermarklocked = $this->checklist->lockteachermarks
- && !has_capability('mod/checklist:updatelocked', $this->context);
-
+ global $DB, $PAGE;
+
+ // Configure the status of the checklist output.
+ $status = new output_status();
+ $status->set_viewother($viewother);
+ $status->set_userreport($userreport);
+ $status->set_teachercomments($this->checklist->teachercomments);
+ $status->set_canupdateown($this->canupdateown());
+ $status->set_canaddown($this->canaddown());
+
+ if ($status->is_teachercomments()) {
+ if ($status->is_viewother()) {
+ $status->set_editcomments(optional_param('editcomments', false, PARAM_BOOL));
+ }
+ $comments = checklist_comment::fetch_by_userid_itemids($this->userid, array_keys($this->items));
+ checklist_comment::add_commentby_names($comments);
+ checklist_item::add_comments($this->items, $comments);
+ }
+ if ($status->is_canupdateown() || $status->is_viewother() || $status->is_userreport()) {
+ $status->set_showprogressbar(true);
+ $showteachermark = in_array($this->checklist->teacheredit, [CHECKLIST_MARKING_TEACHER, CHECKLIST_MARKING_BOTH]);
+ $status->set_showteachermark($showteachermark);
+ $showcheckbox = in_array($this->checklist->teacheredit, [CHECKLIST_MARKING_STUDENT, CHECKLIST_MARKING_BOTH]);
+ $status->set_showcheckbox($showcheckbox);
+ }
+ if ($status->is_showteachermark() && $this->checklist->lockteachermarks) {
+ $status->set_teachermarklocked(!has_capability('mod/checklist:updatelocked', $this->context));
+ }
+ if ($status->is_viewother()) {
$reportsettings = $this->get_report_settings();
- $showcompletiondates = $reportsettings->showcompletiondates;
-
- $strteacherdate = get_string('teacherdate', 'mod_checklist');
- $struserdate = get_string('userdate', 'mod_checklist');
- $strteachername = get_string('teacherid', 'mod_checklist');
-
- if ($showcompletiondates) {
- $teacherids = array();
- foreach ($this->items as $item) {
- if ($item->teacherid) {
- $teacherids[$item->teacherid] = $item->teacherid;
- }
- }
- $fields = get_all_user_name_fields(true);
- $teachers = $DB->get_records_list('user', 'id', $teacherids, '', 'id, '.$fields);
- foreach ($this->items as $item) {
- if (isset($teachers[$item->teacherid])) {
- $item->teachername = fullname($teachers[$item->teacherid]);
- } else {
- $item->teachername = false;
- }
- }
+ $status->set_showcompletiondates($reportsettings->showcompletiondates);
+ if ($status->is_showcompletiondates()) {
+ checklist_item::add_teacher_names($this->items);
}
}
-
- $intro = file_rewrite_pluginfile_urls($this->checklist->intro, 'pluginfile.php', $this->context->id,
- 'mod_checklist', 'intro', null);
- $opts = array('trusted' => $CFG->enabletrusttext);
- echo format_text($intro, $this->checklist->introformat, $opts);
- echo ' ';
-
- $showteachermark = false;
- $showcheckbox = true;
- if ($this->canupdateown() || $viewother || $userreport) {
- $this->view_progressbar();
- $showteachermark = ($this->checklist->teacheredit == CHECKLIST_MARKING_TEACHER)
- || ($this->checklist->teacheredit == CHECKLIST_MARKING_BOTH);
- $showcheckbox = ($this->checklist->teacheredit == CHECKLIST_MARKING_STUDENT)
- || ($this->checklist->teacheredit == CHECKLIST_MARKING_BOTH);
- $teachermarklocked = $teachermarklocked && $showteachermark; // Make sure this is OFF, if not showing teacher marks.
- }
- $overrideauto = ($this->checklist->autoupdate != CHECKLIST_AUTOUPDATE_YES);
- $checkgroupings = $this->checklist->autopopulate && ($this->groupings !== false);
-
- if (!$this->items) {
- print_string('noitems', 'checklist');
- } else {
- $focusitem = false;
- $updateform = ($showcheckbox && $this->canupdateown() && !$viewother && !$userreport)
- || ($viewother && ($showteachermark || $editcomments));
- $addown = $this->canaddown() && $this->useredit;
- if ($updateform) {
- if ($this->canaddown() && !$viewother) {
- echo '';
- }
-
- if (!$viewother) {
- // Load the Javascript required to send changes back to the server (without clicking 'save')
- if ($CFG->version < 2012120300) { // < Moodle 2.4.
- $jsmodule = array(
- 'name' => 'mod_checklist',
- 'fullpath' => new moodle_url('/mod/checklist/updatechecks.js')
- );
- $PAGE->requires->yui2_lib('dom');
- $PAGE->requires->yui2_lib('event');
- $PAGE->requires->yui2_lib('connection');
- $PAGE->requires->yui2_lib('animation');
- } else {
- $jsmodule = array(
- 'name' => 'mod_checklist',
- 'fullpath' => new moodle_url('/mod/checklist/updatechecks24.js')
- );
- }
- $updatechecksurl = new moodle_url('/mod/checklist/updatechecks.php');
- $updateprogress = $showteachermark ? 0 : 1; // Progress bars should be updated on 'student only' checklists.
- $PAGE->requires->js_init_call('M.mod_checklist.init', array(
- $updatechecksurl->out(), sesskey(), $this->cm->id, $updateprogress
- ), true, $jsmodule);
- }
-
- echo '';
+ }
+ if ($status->is_viewother()) {
+ if ($status->is_showteachermark() || $status->is_editcomments()) {
+ // Viewing another user + teacher checklist or editing comments.
+ $status->set_updateform(true);
}
+ }
- if ($focusitem) {
- echo '';
- }
+ // Gather some extra details needed in the output.
+ $intro = $this->formatted_intro();
+ $progress = null;
+ if ($status->is_showprogressbar()) {
+ $progress = $this->get_progress();
+ }
+ $student = null;
+ if ($status->is_viewother()) {
+ $student = $DB->get_record('user', ['id' => $this->userid], '*', MUST_EXIST);
+ }
- if ($addown) {
- echo '';
- }
+ // Add the javascript, if needed.
+ if (!$status->is_viewother()) {
+ // Load the Javascript required to send changes back to the server (without clicking 'save').
+ $jsmodule = array(
+ 'name' => 'mod_checklist',
+ 'fullpath' => new moodle_url('/mod/checklist/updatechecks24.js')
+ );
+ $updatechecksurl = new moodle_url('/mod/checklist/updatechecks.php');
+ // Progress bars should be updated on 'student only' checklists.
+ $updateprogress = $status->is_showteachermark() ? 0 : 1;
+ $PAGE->requires->js_init_call('M.mod_checklist.init', array(
+ $updatechecksurl->out(), sesskey(), $this->cm->id, $updateprogress
+ ), true, $jsmodule);
}
- echo $OUTPUT->box_end();
+ $this->output->checklist_items($this->items, $this->useritems, $this->groupings, $intro, $status, $progress, $student);
}
- protected function print_edit_date($ts = 0) {
- // TODO - use fancy JS calendar instead.
-
- $id = rand();
- if ($ts == 0) {
- $disabled = true;
- $date = usergetdate(time());
- } else {
- $disabled = false;
- $date = usergetdate($ts);
- }
- $day = $date['mday'];
- $month = $date['mon'];
- $year = $date['year'];
-
- echo '';
- for ($i = 1; $i <= 31; $i++) {
- $selected = ($i == $day) ? 'selected="selected" ' : '';
- echo ''.$i.' ';
- }
- echo ' ';
- echo '';
- for ($i = 1; $i <= 12; $i++) {
- $selected = ($i == $month) ? 'selected="selected" ' : '';
- echo ''.userdate(gmmktime(12, 0, 0, $i, 15, 2000), "%B").' ';
- }
- echo ' ';
- echo '';
- $today = usergetdate(time());
- $thisyear = $today['year'];
- for ($i = $thisyear - 5; $i <= ($thisyear + 10); $i++) {
- $selected = ($i == $year) ? 'selected="selected" ' : '';
- echo ''.$i.' ';
- }
- echo ' ';
- $checked = $disabled ? 'checked="checked" ' : '';
- echo ''.get_string('disable').' '."\n";
- echo '
- ";
+ protected function formatted_intro() {
+ global $CFG;
+ $intro = file_rewrite_pluginfile_urls($this->checklist->intro, 'pluginfile.php', $this->context->id,
+ 'mod_checklist', 'intro', null);
+ $opts = array('trusted' => $CFG->enabletrusttext);
+ return format_text($intro, $this->checklist->introformat, $opts);
}
protected function view_import_export() {
@@ -1373,295 +864,16 @@ protected function view_import_export() {
}
protected function view_edit_items() {
- global $OUTPUT;
-
- echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter');
-
- $currindent = 0;
- $addatend = true;
- $focusitem = false;
- $hasauto = false;
-
- $thispage = new moodle_url('/mod/checklist/edit.php', array('id' => $this->cm->id, 'sesskey' => sesskey()));
- if ($this->additemafter) {
- $thispage->param('additemafter', $this->additemafter);
+ $status = new output_status();
+ $status->set_additemafter($this->additemafter);
+ $status->set_editdates($this->editdates);
+ $status->set_itemid(optional_param('itemid', null, PARAM_INT));
+ $status->set_autopopulate($this->checklist->autopopulate);
+ if ($this->checklist->autopopulate && $this->checklist->autoupdate) {
+ $status->set_autoupdatewarning($this->checklist->teacheredit);
}
- if ($this->editdates) {
- $thispage->param('editdates', 'on');
- }
- if ($itemid = optional_param('itemid', null, PARAM_INT)) {
- $thispage->param('itemid', $itemid);
- }
-
- if ($this->checklist->autoupdate && $this->checklist->autopopulate) {
- if ($this->checklist->teacheredit == CHECKLIST_MARKING_STUDENT) {
- echo ''.get_string('autoupdatewarning_student', 'checklist').'
';
- } else if ($this->checklist->teacheredit == CHECKLIST_MARKING_TEACHER) {
- echo ''.get_string('autoupdatewarning_teacher', 'checklist').'
';
- } else {
- echo ''.get_string('autoupdatewarning_both', 'checklist').'
';
- }
- }
-
- echo '';
- if ($this->items) {
- $lastitem = count($this->items);
- $lastindent = 0;
-
- echo html_writer::start_tag('form', array('action' => $thispage->out_omit_querystring(), 'method' => 'post'));
- echo html_writer::input_hidden_params($thispage);
-
- if ($this->checklist->autopopulate) {
- echo html_writer::empty_tag('input', array(
- 'type' => 'submit', 'name' => 'showhideitems',
- 'value' => get_string('showhidechecked', 'checklist')
- ));
- }
- foreach ($this->items as $item) {
-
- while ($item->indent > $currindent) {
- $currindent++;
- echo '';
- }
- while ($item->indent < $currindent) {
- $currindent--;
- echo ' ';
- }
-
- $itemname = '"item'.$item->id.'"';
- $thispage->param('itemid', $item->id);
-
- switch ($item->colour) {
- case 'red':
- $itemcolour = 'itemred';
- $nexticon = 'colour_orange';
- break;
- case 'orange':
- $itemcolour = 'itemorange';
- $nexticon = 'colour_green';
- break;
- case 'green':
- $itemcolour = 'itemgreen';
- $nexticon = 'colour_purple';
- break;
- case 'purple':
- $itemcolour = 'itempurple';
- $nexticon = 'colour_black';
- break;
- default:
- $itemcolour = 'itemblack';
- $nexticon = 'colour_red';
- }
-
- $autoitem = ($this->checklist->autopopulate) && ($item->moduleid != 0);
- if ($autoitem) {
- $autoclass = ' itemauto';
- } else {
- $autoclass = '';
- }
- $hasauto = $hasauto || ($item->moduleid != 0);
-
- echo '';
-
- echo html_writer::start_span('', array('style' => 'display: inline-block; width: 16px;'));
- if ($autoitem && $item->hidden != CHECKLIST_HIDDEN_BYMODULE) {
- echo html_writer::checkbox('items['.$item->id.']', $item->id, false, '',
- array('title' => $item->displaytext));
- }
- echo html_writer::end_span();
-
- if ($item->itemoptional == CHECKLIST_OPTIONAL_YES) {
- $title = '"'.get_string('optionalitem', 'checklist').'"';
- echo '';
- echo ' ';
- $optional = ' class="itemoptional '.$itemcolour.$autoclass.'" ';
- } else if ($item->itemoptional == CHECKLIST_OPTIONAL_HEADING) {
- if ($item->hidden) {
- $title = '"'.get_string('headingitem', 'checklist').'"';
- echo ' ';
- $optional = ' class="'.$itemcolour.$autoclass.' itemdisabled"';
- } else {
- $title = '"'.get_string('headingitem', 'checklist').'"';
- if (!$autoitem) {
- echo '';
- }
- echo ' ';
- if (!$autoitem) {
- echo ' ';
- }
- echo ' ';
- $optional = ' class="itemheading '.$itemcolour.$autoclass.'" ';
- }
- } else if ($item->hidden) {
- $title = '"'.get_string('requireditem', 'checklist').'"';
- echo ' ';
- $optional = ' class="'.$itemcolour.$autoclass.' itemdisabled"';
- } else {
- $title = '"'.get_string('requireditem', 'checklist').'"';
- echo '';
- echo ' ';
- $optional = ' class="'.$itemcolour.$autoclass.'"';
- }
-
- if (isset($item->editme)) {
- echo ' ';
- if ($this->editdates) {
- $this->print_edit_date($item->duetime);
- }
- echo ' ';
-
- $focusitem = 'updateitembox';
-
- echo ' ';
-
- $addatend = false;
-
- } else {
- echo ''.format_string($item->displaytext).' ';
-
- echo '';
- $title = '"'.get_string('changetextcolour', 'checklist').'"';
- echo ' ';
-
- if (!$autoitem) {
- echo '';
- $title = '"'.get_string('edititem', 'checklist').'"';
- echo ' ';
- }
-
- if (!$autoitem && $item->indent > 0) {
- echo '';
- $title = '"'.get_string('unindentitem', 'checklist').'"';
- echo ' ';
- }
-
- if (!$autoitem && ($item->indent < CHECKLIST_MAX_INDENT) && (($lastindent + 1) > $currindent)) {
- echo '';
- $title = '"'.get_string('indentitem', 'checklist').'"';
- echo ' ';
- }
-
- echo ' ';
-
- // TODO more complex checks to take into account indentation.
- if (!$autoitem && $item->position > 1) {
- echo '';
- $title = '"'.get_string('moveitemup', 'checklist').'"';
- echo ' ';
- }
-
- if (!$autoitem && $item->position < $lastitem) {
- echo '';
- $title = '"'.get_string('moveitemdown', 'checklist').'"';
- echo ' ';
- }
-
- if ($autoitem) {
- if ($item->hidden != CHECKLIST_HIDDEN_BYMODULE) {
- echo ' ';
- if ($item->hidden == CHECKLIST_HIDDEN_MANUAL) {
- $title = '"'.get_string('show').'"';
- echo ' ';
- } else {
- $title = '"'.get_string('hide').'"';
- echo ' ';
- }
- }
- } else {
- echo ' ';
- $title = '"'.get_string('deleteitem', 'checklist').'"';
- echo ' ';
- }
-
- echo ' ';
- $title = '"'.get_string('additemhere', 'checklist').'"';
- echo ' ';
- if ($item->duetime) {
- if ($item->duetime > time()) {
- echo ' '.userdate($item->duetime, get_string('strftimedate')).' ';
- } else {
- echo ' '.
- userdate($item->duetime, get_string('strftimedate')).' ';
- }
- }
-
- }
-
- $thispage->remove_params(array('itemid'));
-
- if ($this->additemafter == $item->id) {
- $addatend = false;
- echo ' ';
- echo ' ';
- echo ' ';
- echo ' ';
- echo ' ';
- if ($this->editdates) {
- $this->print_edit_date();
- }
- echo ' ';
- echo ' ';
- echo ' ';
-
- if (!$focusitem) {
- $focusitem = 'additembox';
- }
- }
-
- $lastindent = $currindent;
-
- echo '';
- }
-
- echo html_writer::end_tag('form');
- }
-
- $thispage->remove_params(array('itemid'));
-
- if ($addatend) {
- echo '';
- echo '';
- echo html_writer::input_hidden_params($thispage);
- echo ' ';
- echo ' ';
- echo ' ';
- if ($this->editdates) {
- $this->print_edit_date();
- }
- echo ' ';
- echo ' ';
- echo ' ';
- if (!$focusitem) {
- $focusitem = 'additembox';
- }
- }
- echo ' ';
- while ($currindent) {
- $currindent--;
- echo '';
- }
-
- echo '';
- echo html_writer::input_hidden_params($thispage, array('sesskey', 'editdates'));
- if (!$this->editdates) {
- echo ' ';
- echo ' ';
- } else {
- echo ' ';
- }
- if (!$this->checklist->autopopulate && $hasauto) {
- echo ' ';
- echo ' ';
- }
- echo ' ';
-
- if ($focusitem) {
- echo '';
- }
-
- echo $OUTPUT->box_end();
+ $this->output->checklist_edit_items($this->items, $status);
}
protected function view_report() {
@@ -2174,7 +1386,7 @@ protected function process_view_actions() {
case 'edititem':
if ($this->useritems && isset($this->useritems[$itemid])) {
- $this->useritems[$itemid]->editme = true;
+ $this->useritems[$itemid]->set_editme();
}
break;
@@ -2262,7 +1474,7 @@ protected function process_edit_actions() {
break;
case 'edititem':
if (isset($this->items[$itemid])) {
- $this->items[$itemid]->editme = true;
+ $this->items[$itemid]->set_editme();
}
$additemafter = false;
break;
@@ -2414,8 +1626,6 @@ protected function process_report_actions() {
public function additem($displaytext, $userid = 0, $indent = 0, $position = false, $duetime = false, $moduleid = 0,
$optional = CHECKLIST_OPTIONAL_NO, $hidden = CHECKLIST_HIDDEN_NO) {
- global $DB;
-
$displaytext = trim($displaytext);
if ($displaytext == '') {
return false;
@@ -2432,7 +1642,7 @@ public function additem($displaytext, $userid = 0, $indent = 0, $position = fals
}
}
- $item = new stdClass;
+ $item = new checklist_item();
$item->checklist = $this->checklist->id;
$item->displaytext = $displaytext;
if ($position) {
@@ -2451,15 +1661,13 @@ public function additem($displaytext, $userid = 0, $indent = 0, $position = fals
$item->eventid = 0;
$item->colour = 'black';
$item->moduleid = $moduleid;
- $item->checked = false;
- $item->id = $DB->insert_record('checklist_item', $item);
+ $item->insert();
if ($item->id) {
if ($userid) {
$this->useritems[$item->id] = $item;
- $this->useritems[$item->id]->checked = false;
if ($position) {
- uasort($this->useritems, 'checklist_itemcompare');
+ checklist_item::sort_items($this->useritems);
}
} else {
if ($position) {
@@ -2467,11 +1675,9 @@ public function additem($displaytext, $userid = 0, $indent = 0, $position = fals
$this->update_item_positions(1, $position);
}
$this->items[$item->id] = $item;
- $this->items[$item->id]->checked = false;
- $this->items[$item->id]->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
- uasort($this->items, 'checklist_itemcompare');
+ checklist_item::sort_items($this->items);
if ($this->checklist->duedatesoncalendar) {
- $this->setevent($item->id, true);
+ $this->setevent($item, true);
}
}
}
@@ -2479,13 +1685,10 @@ public function additem($displaytext, $userid = 0, $indent = 0, $position = fals
return $item->id;
}
- protected function setevent($itemid, $add) {
- global $CFG, $DB;
+ protected function setevent(checklist_item $item, $add) {
+ global $CFG;
require_once($CFG->dirroot.'/calendar/lib.php');
- $item = $this->items[$itemid];
- $update = false;
-
if ((!$add) || ($item->duetime == 0)) { // Remove the event (if any).
if (!$item->eventid) {
return; // No event to remove.
@@ -2497,8 +1700,11 @@ protected function setevent($itemid, $add) {
} catch (dml_missing_record_exception $e) {
// Just ignore this error - the event is missing, so does not need deleting.
}
- $this->items[$itemid]->eventid = 0;
- $update = true;
+ $item->eventid = 0;
+ if ($add) {
+ // Don't bother updating the record if we are deleting.
+ $item->update();
+ }
} else { // Add/update event.
$eventdata = new stdClass();
@@ -2520,17 +1726,10 @@ protected function setevent($itemid, $add) {
}
if (!$item->eventid) {
$event = calendar_event::create($eventdata, false);
- $this->items[$itemid]->eventid = $event->id;
- $update = true;
+ $item->eventid = $event->id;
+ $item->update();
}
}
-
- if ($update) { // Event added or removed.
- $upditem = new stdClass();
- $upditem->id = $itemid;
- $upditem->eventid = $this->items[$itemid]->eventid;
- $DB->update_record('checklist_item', $upditem);
- }
}
public function setallevents() {
@@ -2539,14 +1738,12 @@ public function setallevents() {
}
$add = $this->checklist->duedatesoncalendar;
- foreach ($this->items as $key => $value) {
- $this->setevent($key, $add);
+ foreach ($this->items as $item) {
+ $this->setevent($item, $add);
}
}
protected function updateitemtext($itemid, $displaytext, $duetime = false) {
- global $DB;
-
$displaytext = trim($displaytext);
if ($displaytext == '') {
return;
@@ -2554,95 +1751,48 @@ protected function updateitemtext($itemid, $displaytext, $duetime = false) {
if (isset($this->items[$itemid])) {
if ($this->canedit()) {
- $this->items[$itemid]->displaytext = $displaytext;
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->displaytext = $displaytext;
-
- $upditem->duetime = 0;
+ $item = $this->items[$itemid];
+ $item->displaytext = $displaytext;
+ $item->duetime = 0;
if ($duetime) {
- $upditem->duetime = make_timestamp($duetime['year'], $duetime['month'], $duetime['day']);
+ $item->duetime = make_timestamp($duetime['year'], $duetime['month'], $duetime['day']);
}
- $this->items[$itemid]->duetime = $upditem->duetime;
-
- $DB->update_record('checklist_item', $upditem);
-
+ $item->update();
if ($this->checklist->duedatesoncalendar) {
- $this->setevent($itemid, true);
+ $this->setevent($item, true);
}
}
} else if (isset($this->useritems[$itemid])) {
if ($this->canaddown()) {
- $this->useritems[$itemid]->displaytext = $displaytext;
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->displaytext = $displaytext;
- $DB->update_record('checklist_item', $upditem);
+ $item = $this->useritems[$itemid];
+ $item->displaytext = $displaytext;
+ $item->update();
}
}
}
protected function toggledisableitem($itemid) {
- global $DB;
-
if (isset($this->items[$itemid])) {
if (!$this->canedit()) {
return;
}
$item = $this->items[$itemid];
- if ($item->hidden == CHECKLIST_HIDDEN_NO) {
- $item->hidden = CHECKLIST_HIDDEN_MANUAL;
- } else if ($item->hidden == CHECKLIST_HIDDEN_MANUAL) {
- $item->hidden = CHECKLIST_HIDDEN_NO;
- }
-
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->hidden = $item->hidden;
- $DB->update_record('checklist_item', $upditem);
+ $item->toggle_hidden();
// If the item is a section heading, then show/hide all items in that section.
- if ($item->itemoptional == CHECKLIST_OPTIONAL_HEADING) {
- if ($item->hidden) {
- foreach ($this->items as $it) {
- if ($it->position <= $item->position) {
- continue;
- }
- if ($it->itemoptional == CHECKLIST_OPTIONAL_HEADING) {
- break;
- }
- if (!$it->moduleid) {
- continue;
- }
- if ($it->hidden == CHECKLIST_HIDDEN_NO) {
- $it->hidden = CHECKLIST_HIDDEN_MANUAL;
- $upditem = new stdClass;
- $upditem->id = $it->id;
- $upditem->hidden = $it->hidden;
- $DB->update_record('checklist_item', $upditem);
- }
+ if ($item->is_heading()) {
+ foreach ($this->items as $it) {
+ if ($it->position <= $item->position) {
+ continue; // Loop until we find the current item.
}
-
- } else {
-
- foreach ($this->items as $it) {
- if ($it->position <= $item->position) {
- continue;
- }
- if ($it->itemoptional == CHECKLIST_OPTIONAL_HEADING) {
- break;
- }
- if (!$it->moduleid) {
- continue;
- }
- if ($it->hidden == CHECKLIST_HIDDEN_MANUAL) {
- $it->hidden = CHECKLIST_HIDDEN_NO;
- $upditem = new stdClass;
- $upditem->id = $it->id;
- $upditem->hidden = $it->hidden;
- $DB->update_record('checklist_item', $upditem);
- }
+ if ($it->is_heading()) {
+ break; // Stop at the next heading.
+ }
+ if ($item->hidden) {
+ $it->hide_item();
+ } else {
+ $it->show_item();
}
}
}
@@ -2657,19 +1807,21 @@ protected function deleteitem($itemid, $forcedelete = false) {
if (!$forcedelete && !$this->canedit()) {
return;
}
- $this->setevent($itemid, false); // Remove any calendar events.
+ $item = $this->items[$itemid];
+ $this->setevent($item, false); // Remove any calendar events.
unset($this->items[$itemid]);
} else if (isset($this->useritems[$itemid])) {
if (!$this->canaddown()) {
return;
}
+ $item = $this->useritems[$itemid];
unset($this->useritems[$itemid]);
} else {
// Item for deletion is not currently available.
return;
}
- $DB->delete_records('checklist_item', array('id' => $itemid));
+ $item->delete();
$DB->delete_records('checklist_check', array('item' => $itemid));
$this->update_item_positions();
@@ -2681,11 +1833,9 @@ protected function moveitemto($itemid, $newposition, $forceupdate = false) {
if (!isset($this->items[$itemid])) {
if (isset($this->useritems[$itemid])) {
if ($this->canupdateown()) {
- $this->useritems[$itemid]->position = $newposition;
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->position = $newposition;
- $DB->update_record('checklist_item', $upditem);
+ $item = $this->useritems[$itemid];
+ $item->position = $newposition;
+ $item->update();
}
}
return;
@@ -2713,12 +1863,10 @@ protected function moveitemto($itemid, $newposition, $forceupdate = false) {
$this->update_item_positions(-1, $oldposition, $newposition); // Move items up (including this one).
}
- $this->items[$itemid]->position = $newposition; // Move item to new position.
- uasort($this->items, 'checklist_itemcompare'); // Sort the array by position.
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->position = $newposition;
- $DB->update_record('checklist_item', $upditem); // Update the database.
+ $item = $this->items[$itemid];
+ $item->position = $newposition; // Move item to new position.
+ $item->update();
+ checklist_item::sort_items($this->items);
}
protected function moveitemup($itemid) {
@@ -2746,15 +1894,13 @@ protected function moveitemdown($itemid) {
}
protected function indentitemto($itemid, $indent) {
- global $DB;
-
if (!isset($this->items[$itemid])) {
// Not able to indent useritems, as they are always parent + 1.
return;
}
+ $item = $this->items[$itemid];
- $position = $this->items[$itemid]->position;
- if ($position == 1) {
+ if ($item->position == 1) {
$indent = 0;
}
@@ -2764,26 +1910,20 @@ protected function indentitemto($itemid, $indent) {
$indent = CHECKLIST_MAX_INDENT;
}
- $oldindent = $this->items[$itemid]->indent;
+ $oldindent = $item->indent;
$adjust = $indent - $oldindent;
if ($adjust == 0) {
return;
}
- $this->items[$itemid]->indent = $indent;
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->indent = $indent;
- $DB->update_record('checklist_item', $upditem);
+ $item->indent = $indent;
+ $item->update();
// Update all 'children' of this item to new indent.
- foreach ($this->items as $item) {
- if ($item->position > $position) {
- if ($item->indent > $oldindent) {
- $item->indent += $adjust;
- $upditem = new stdClass;
- $upditem->id = $item->id;
- $upditem->indent = $item->indent;
- $DB->update_record('checklist_item', $upditem);
+ foreach ($this->items as $it) {
+ if ($it->position > $item->position) {
+ if ($it->indent > $oldindent) {
+ $it->indent += $adjust;
+ $it->update();
} else {
break;
}
@@ -2813,6 +1953,7 @@ protected function makeoptional($itemid, $optional, $heading = false) {
if (!isset($this->items[$itemid])) {
return;
}
+ $item = $this->items[$itemid];
if ($heading) {
$optional = CHECKLIST_OPTIONAL_HEADING;
@@ -2822,32 +1963,27 @@ protected function makeoptional($itemid, $optional, $heading = false) {
$optional = CHECKLIST_OPTIONAL_NO;
}
- if ($this->items[$itemid]->moduleid) {
- $op = $this->items[$itemid]->itemoptional;
- if ($op == CHECKLIST_OPTIONAL_HEADING) {
+ if ($item->moduleid) {
+ if ($item->is_heading()) {
return; // Topic headings must stay as headings.
- } else if ($this->items[$itemid]->itemoptional == CHECKLIST_OPTIONAL_YES) {
+ } else if ($item->itemoptional == CHECKLIST_OPTIONAL_YES) {
$optional = CHECKLIST_OPTIONAL_NO; // Module links cannot become headings.
} else {
$optional = CHECKLIST_OPTIONAL_YES;
}
}
- $this->items[$itemid]->itemoptional = $optional;
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->itemoptional = $optional;
- $DB->update_record('checklist_item', $upditem);
+ $item->itemoptional = $optional;
+ $item->update();
}
protected function nextcolour($itemid) {
- global $DB;
-
if (!isset($this->items[$itemid])) {
return;
}
+ $item = $this->items[$itemid];
- switch ($this->items[$itemid]->colour) {
+ switch ($item->colour) {
case 'black':
$nextcolour = 'red';
break;
@@ -2864,11 +2000,8 @@ protected function nextcolour($itemid) {
$nextcolour = 'black';
}
- $upditem = new stdClass;
- $upditem->id = $itemid;
- $upditem->colour = $nextcolour;
- $DB->update_record('checklist_item', $upditem);
- $this->items[$itemid]->colour = $nextcolour;
+ $item->colour = $nextcolour;
+ $item->update();
}
public function ajaxupdatechecks($changechecks) {
@@ -2882,7 +2015,7 @@ public function ajaxupdatechecks($changechecks) {
}
} else {
// If no new status, include in array if checked.
- if ($item->checked) {
+ if ($item->is_checked_student()) {
$newchecks[] = $item->id;
}
}
@@ -2896,7 +2029,7 @@ public function ajaxupdatechecks($changechecks) {
}
} else {
// If no new status, include in array if checked.
- if ($item->checked) {
+ if ($item->is_checked_student()) {
$newchecks[] = $item->id;
}
}
@@ -2907,8 +2040,6 @@ public function ajaxupdatechecks($changechecks) {
}
protected function updatechecks($newchecks) {
- global $DB;
-
if (!is_array($newchecks)) {
// Something has gone wrong, so update nothing.
return;
@@ -2929,31 +2060,8 @@ protected function updatechecks($newchecks) {
}
$newval = in_array($item->id, $newchecks);
-
- if ($newval != $item->checked) {
+ if ($item->set_checked_student($this->userid, $newval)) {
$updategrades = true;
- $item->checked = $newval;
-
- $check = $DB->get_record('checklist_check', array('item' => $item->id, 'userid' => $this->userid));
- if ($check) {
- if ($newval) {
- $check->usertimestamp = time();
- } else {
- $check->usertimestamp = 0;
- }
-
- $DB->update_record('checklist_check', $check);
-
- } else {
- $check = new stdClass;
- $check->item = $item->id;
- $check->userid = $this->userid;
- $check->usertimestamp = time();
- $check->teachertimestamp = 0;
- $check->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
-
- $check->id = $DB->insert_record('checklist_check', $check);
- }
}
}
}
@@ -2964,36 +2072,13 @@ protected function updatechecks($newchecks) {
if ($this->useritems) {
foreach ($this->useritems as $item) {
$newval = in_array($item->id, $newchecks);
-
- if ($newval != $item->checked) {
- $item->checked = $newval;
-
- $check = $DB->get_record('checklist_check', array('item' => $item->id, 'userid' => $this->userid));
- if ($check) {
- if ($newval) {
- $check->usertimestamp = time();
- } else {
- $check->usertimestamp = 0;
- }
- $DB->update_record('checklist_check', $check);
-
- } else {
- $check = new stdClass;
- $check->item = $item->id;
- $check->userid = $this->userid;
- $check->usertimestamp = time();
- $check->teachertimestamp = 0;
- $check->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
-
- $check->id = $DB->insert_record('checklist_check', $check);
- }
- }
+ $item->set_checked_student($this->userid, $newval);
}
}
}
protected function updateteachermarks() {
- global $USER, $DB, $CFG;
+ global $USER, $DB;
$newchecks = optional_param_array('items', array(), PARAM_TEXT);
if (!is_array($newchecks)) {
@@ -3002,7 +2087,7 @@ protected function updateteachermarks() {
}
if ($this->checklist->teacheredit != CHECKLIST_MARKING_STUDENT) {
- if (!$student = $DB->get_record('user', array('id' => $this->userid))) {
+ if (!$DB->record_exists('user', ['id' => $this->userid])) {
error('No such user!');
}
$params = array(
@@ -3019,11 +2104,7 @@ protected function updateteachermarks() {
$this->update_teachermarks($newchecks, $USER->id, $teachermarklocked);
}
- if ($CFG->version < 2011120100) {
- $newcomments = optional_param('teachercomment', false, PARAM_TEXT);
- } else {
- $newcomments = optional_param_array('teachercomment', false, PARAM_TEXT);
- }
+ $newcomments = optional_param_array('teachercomment', false, PARAM_TEXT);
if (!$this->checklist->teachercomments || !$newcomments || !is_array($newcomments)) {
return;
}
@@ -3075,37 +2156,17 @@ protected function updateteachermarks() {
* @param bool $teachermarklocked (optional) set to true to prevent teachers from changing 'yes' to 'no'.
*/
public function update_teachermarks($newchecks, $teacherid, $teachermarklocked = false) {
- global $DB;
-
$updategrades = false;
foreach ($newchecks as $itemid => $newval) {
if (isset($this->items[$itemid])) {
$item = $this->items[$itemid];
- if ($teachermarklocked && $item->teachermark == CHECKLIST_TEACHERMARK_YES) {
+ if ($teachermarklocked && $item->is_checked_teacher()) {
continue; // Does not have permission to update marks that are already 'Yes'.
}
- if ($newval != $item->teachermark) {
- $updategrades = true;
-
- $newcheck = new stdClass;
- $newcheck->teachertimestamp = time();
- $newcheck->teachermark = $newval;
- $newcheck->teacherid = $teacherid;
-
- $item->teachermark = $newcheck->teachermark;
- $item->teachertimestamp = $newcheck->teachertimestamp;
- $item->teacherid = $newcheck->teacherid;
- $oldcheck = $DB->get_record('checklist_check', array('item' => $item->id, 'userid' => $this->userid));
- if ($oldcheck) {
- $newcheck->id = $oldcheck->id;
- $DB->update_record('checklist_check', $newcheck);
- } else {
- $newcheck->item = $itemid;
- $newcheck->userid = $this->userid;
- $newcheck->id = $DB->insert_record('checklist_check', $newcheck);
- }
+ if ($item->set_teachermark($this->userid, $newval, $teacherid)) {
+ $updategrades = true;
}
}
}
@@ -3135,17 +2196,15 @@ protected function updateallteachermarks() {
continue;
}
foreach ($checkdata as $itemid => $val) {
- if ($val != CHECKLIST_TEACHERMARK_NO && $val != CHECKLIST_TEACHERMARK_YES
- && $val != CHECKLIST_TEACHERMARK_UNDECIDED
- ) {
- continue; // Invalid value.
- }
if (!$itemid) {
continue;
}
if (!array_key_exists($itemid, $this->items)) {
continue; // Item is not part of this checklist.
}
+ if (!checklist_check::teachermark_valid($val)) {
+ continue; // Invalid value.
+ }
if (!array_key_exists($userid, $userchecks)) {
$userchecks[$userid] = array();
}
@@ -3160,10 +2219,7 @@ protected function updateallteachermarks() {
$teachermarklocked = $this->checklist->lockteachermarks && !has_capability('mod/checklist:updatelocked', $this->context);
foreach ($userchecks as $userid => $items) {
- list($isql, $iparams) = $DB->get_in_or_equal(array_keys($items));
- $params = array_merge(array($userid), $iparams);
- $currentchecks = $DB->get_records_select('checklist_check', "userid = ? AND item $isql",
- $params, '', 'item, id, teachermark');
+ $currentchecks = checklist_check::fetch_by_userid_itemids($userid, array_keys($items));
$updategrades = false;
foreach ($items as $itemid => $val) {
if (!array_key_exists($itemid, $currentchecks)) {
@@ -3172,30 +2228,25 @@ protected function updateallteachermarks() {
}
// No entry for this item - need to create it.
- $newcheck = new stdClass;
- $newcheck->item = $itemid;
- $newcheck->userid = $userid;
- $newcheck->teachermark = $val;
- $newcheck->teachertimestamp = time();
- $newcheck->usertimestamp = 0;
- $newcheck->teacherid = $USER->id;
-
- $DB->insert_record('checklist_check', $newcheck);
+ $newcheck = new checklist_check(['item' => $itemid, 'userid' => $userid], false);
+ $newcheck->set_teachermark($val, $USER->id);
+ $newcheck->save();
+
$updategrades = true;
- } else if ($currentchecks[$itemid]->teachermark != $val) {
- if ($teachermarklocked && $currentchecks[$itemid]->teachermark == CHECKLIST_TEACHERMARK_YES) {
- continue;
- }
+ } else {
+ $current = $currentchecks[$itemid];
+ if ($current->teachermark != $val) {
+ if ($teachermarklocked && $current->teachermark == CHECKLIST_TEACHERMARK_YES) {
+ continue;
+ }
- $updcheck = new stdClass;
- $updcheck->id = $currentchecks[$itemid]->id;
- $updcheck->teachermark = $val;
- $updcheck->teachertimestamp = time();
- $updcheck->teacherid = $USER->id;
+ // Update the existing item.
+ $current->set_teachermark($val, $USER->id);
+ $current->save();
- $DB->update_record('checklist_check', $updcheck);
- $updategrades = true;
+ $updategrades = true;
+ }
}
}
if ($updategrades) {
@@ -3244,22 +2295,10 @@ public function update_all_autoupdate_checks() {
if ($compdata->completionstate == COMPLETION_COMPLETE
|| $compdata->completionstate == COMPLETION_COMPLETE_PASS
) {
- $check = $DB->get_record('checklist_check', array('item' => $item->itemid, 'userid' => $user->id));
- if ($check) {
- if ($check->usertimestamp) {
- continue;
- }
- $check->usertimestamp = time();
- $DB->update_record('checklist_check', $check);
- } else {
- $check = new stdClass;
- $check->item = $item->itemid;
- $check->userid = $user->id;
- $check->usertimestamp = time();
- $check->teachertimestamp = 0;
- $check->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
-
- $check->id = $DB->insert_record('checklist_check', $check);
+ $check = new checklist_check(['item' => $item->itemid, 'userid' => $user->id]);
+ if (!$check->is_checked_student()) {
+ $check->set_checked_student(true);
+ $check->save();
}
}
}
@@ -3272,22 +2311,10 @@ public function update_all_autoupdate_checks() {
}
foreach ($loguserids as $loguserid) {
- $check = $DB->get_record('checklist_check', array('item' => $item->itemid, 'userid' => $loguserid));
- if ($check) {
- if ($check->usertimestamp) {
- continue;
- }
- $check->usertimestamp = time();
- $DB->update_record('checklist_check', $check);
- } else {
- $check = new stdClass;
- $check->item = $item->itemid;
- $check->userid = $loguserid;
- $check->usertimestamp = time();
- $check->teachertimestamp = 0;
- $check->teachermark = CHECKLIST_TEACHERMARK_UNDECIDED;
-
- $check->id = $DB->insert_record('checklist_check', $check);
+ $check = new checklist_check(['item' => $item->itemid, 'userid' => $loguserid]);
+ if (!$check->is_checked_student()) {
+ $check->set_checked_student(true);
+ $check->save();
}
}
@@ -3349,8 +2376,6 @@ protected function getnextuserid() {
public static function print_user_progressbar($checklistid, $userid, $width = '300px', $showpercent = true,
$return = false, $hidecomplete = false) {
- global $OUTPUT;
-
list($ticked, $total) = self::get_user_progress($checklistid, $userid);
if (!$total) {
return '';
@@ -3358,22 +2383,15 @@ public static function print_user_progressbar($checklistid, $userid, $width = '3
if ($hidecomplete && ($ticked == $total)) {
return '';
}
- $percent = $ticked * 100 / $total;
- // TODO - fix this now that styles.css is included.
- $output = '';
- $output .= '
';
- $output .= '
';
- if ($showpercent) {
- $output .= ' '.sprintf('%0d%%', $percent).' ';
- }
- $output .= ' ';
+ $output = self::get_renderer();
+
+ $out = $output->progress_bar_external($total, $ticked, $width, $showpercent);
if ($return) {
- return $output;
+ return $out;
}
- echo $output;
+ echo $out;
return '';
}
@@ -3451,19 +2469,4 @@ public function get_itemid_by_name($itemname, $strictness = MUST_EXIST) {
}
return null;
}
-
-}
-
-function checklist_itemcompare($item1, $item2) {
- if ($item1->position < $item2->position) {
- return -1;
- } else if ($item1->position > $item2->position) {
- return 1;
- }
- if ($item1->id < $item2->id) {
- return -1;
- } else if ($item1->id > $item2->id) {
- return 1;
- }
- return 0;
}
diff --git a/renderer.php b/renderer.php
new file mode 100644
index 00000000..d25e4e3d
--- /dev/null
+++ b/renderer.php
@@ -0,0 +1,898 @@
+.
+
+/**
+ * Checklist output functions.
+ *
+ * @package mod_checklist
+ * @copyright 2016 Davo Smith, Synergy Learning
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+use mod_checklist\local\checklist_item;
+use mod_checklist\local\output_status;
+use mod_checklist\local\progress_info;
+
+defined('MOODLE_INTERNAL') || die();
+
+class mod_checklist_renderer extends plugin_renderer_base {
+ public function progress_bars($totalitems, $requireditems, $allcompleteitems, $reqcompleteitems) {
+ $out = '';
+
+ if ($requireditems > 0 && $totalitems > $requireditems) {
+ $out .= $this->progress_bar($requireditems, $reqcompleteitems, true);
+ }
+ $out .= $this->progress_bar($totalitems, $allcompleteitems, false);
+
+ return $out;
+ }
+
+ public function progress_bar($totalitems, $completeitems, $isrequired) {
+ $out = '';
+
+ $percentcomplete = $totalitems ? (($completeitems * 100.0) / $totalitems) : 0.0;
+ if ($isrequired) {
+ $heading = get_string('percentcomplete', 'checklist');
+ $spanid = 'checklistprogressrequired';
+ } else {
+ $heading = get_string('percentcompleteall', 'checklist');
+ $spanid = 'checklistprogressall';
+ }
+
+ // Heading.
+ $heading .= ': ';
+ $out .= html_writer::div($heading, 'checklist_progress_heading');
+
+ // Progress bar.
+ $progress = '';
+ $progress .= html_writer::div(' ', 'checklist_progress_inner', ['style' => "width: {$percentcomplete}%;"]);
+ $progress .= html_writer::div(' ', 'checklist_progress_anim', ['style' => "width: {$percentcomplete}%;"]);
+ $progress = html_writer::div($progress, 'checklist_progress_outer');
+ $progress .= html_writer::span(' '.sprintf('%0d%%', $percentcomplete), 'checklist_progress_percent');
+
+ // Wrap in span + add clearer br.
+ $out .= html_writer::span($progress, '', ['id' => $spanid]);
+ $out .= html_writer::empty_tag('br', ['class' => 'clearer']);
+
+ return $out;
+ }
+
+ public function progress_bar_external($totalitems, $completeitems, $width, $showpercent) {
+ $out = '';
+
+ $percentcomplete = $totalitems ? ($completeitems * 100.0 / $totalitems) : 0.0;
+
+ $out .= html_writer::div(' ', 'checklist_progress_inner', ['style' => "width: {$percentcomplete}%;"]);
+ $out = html_writer::div($out, 'checklist_progress_outer', ['style' => "width: $width;"]);
+ if ($showpercent) {
+ $out .= html_writer::span(' '.sprintf('%0d%%', $percentcomplete), 'checklist_progress_percent');
+ }
+ $out .= html_writer::empty_tag('br', ['class' => 'clearer']);
+ return $out;
+ }
+
+ /**
+ * @param checklist_item[] $items
+ * @param checklist_item[] $useritems
+ * @param bool|int[] $groupings
+ * @param string $intro
+ * @param output_status $status
+ * @param progress_info|null $progress
+ * @param object $student (optional) the student whose checklist is being viewed (if not viewing own checklist)
+ */
+ public function checklist_items($items, $useritems, $groupings, $intro, output_status $status, $progress, $student = null) {
+ echo $this->output->box_start('generalbox boxwidthwide boxaligncenter checklistbox');
+
+ echo html_writer::tag('div', ' ', array('id' => 'checklistspinner'));
+
+ $thispageurl = new moodle_url($this->page->url);
+
+ $strteachername = '';
+ $struserdate = '';
+ $strteacherdate = '';
+ if ($status->is_viewother()) {
+ echo ''.get_string('checklistfor', 'checklist').' '.fullname($student, true).' ';
+ echo ' ';
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl, array('studentid'));
+ echo ' ';
+ echo ' ';
+
+ if (!$status->is_editcomments()) {
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ }
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ' ';
+
+ $strteacherdate = get_string('teacherdate', 'mod_checklist');
+ $struserdate = get_string('userdate', 'mod_checklist');
+ $strteachername = get_string('teacherid', 'mod_checklist');
+ }
+
+ echo $intro;
+ echo ' ';
+
+ if ($status->is_showprogressbar() && $progress) {
+ echo $this->progress_bars($progress->totalitems, $progress->requireditems,
+ $progress->allcompleteitems, $progress->requiredcompleteitems);
+ }
+
+ if (!$items) {
+ print_string('noitems', 'checklist');
+ } else {
+ $focusitem = false;
+ if ($status->is_updateform()) {
+ if ($status->is_canaddown() && !$status->is_viewother()) {
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ if ($status->is_addown()) {
+ // Switch on for any other forms on this page (but off if this form submitted).
+ $thispageurl->param('useredit', 'on');
+ echo ' ';
+ } else {
+ echo ' ';
+ echo ' ';
+ }
+ echo ' ';
+ }
+
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ echo ' ';
+ echo ' ';
+ }
+
+ if ($useritems) {
+ reset($useritems);
+ }
+
+ if ($status->is_teachermarklocked()) {
+ echo ''.get_string('lockteachermarkswarning', 'checklist').'
';
+ }
+
+ echo '';
+ $currindent = 0;
+ foreach ($items as $item) {
+
+ if ($item->hidden) {
+ continue;
+ }
+
+ if ($status->is_checkgroupings() && $item->grouping) {
+ if (!in_array($item->grouping, $groupings)) {
+ continue; // Current user is not a member of this item's grouping, so skip.
+ }
+ }
+
+ while ($item->indent > $currindent) {
+ $currindent++;
+ echo '';
+ }
+ while ($item->indent < $currindent) {
+ $currindent--;
+ echo ' ';
+ }
+ $itemname = '"item'.$item->id.'"';
+ $checked = '';
+ if ($status->is_updateform() || $status->is_viewother() || $status->is_userreport()) {
+ if ($item->is_checked_student()) {
+ $checked = ' checked="checked" ';
+ }
+ }
+ if ($status->is_viewother() || $status->is_userreport()) {
+ $checked .= ' disabled="disabled" ';
+ } else if (!$status->is_overrideauto() && $item->moduleid) {
+ $checked .= ' disabled="disabled" ';
+ }
+ switch ($item->colour) {
+ case 'red':
+ $itemcolour = 'itemred';
+ break;
+ case 'orange':
+ $itemcolour = 'itemorange';
+ break;
+ case 'green':
+ $itemcolour = 'itemgreen';
+ break;
+ case 'purple':
+ $itemcolour = 'itempurple';
+ break;
+ default:
+ $itemcolour = 'itemblack';
+ }
+
+ $checkclass = '';
+ if ($item->is_heading()) {
+ $optional = ' class="itemheading '.$itemcolour.'" ';
+ } else if ($item->is_required()) {
+ $optional = ' class="'.$itemcolour.'" ';
+ } else {
+ $optional = ' class="itemoptional '.$itemcolour.'" ';
+ $checkclass = ' itemoptional';
+ }
+
+ echo '';
+ if ($status->is_showteachermark()) {
+ if (!$item->is_heading()) {
+ if ($status->is_viewother()) {
+ $opts = [
+ CHECKLIST_TEACHERMARK_UNDECIDED => '',
+ CHECKLIST_TEACHERMARK_YES => get_string('yes'),
+ CHECKLIST_TEACHERMARK_NO => get_string('no'),
+ ];
+ $attr = ['id' => 'item'.$item->id]; // TODO davo - fix itemname handling.
+ if ($status->is_teachermarklocked() && $item->is_checked_teacher()) {
+ $attr['disabled'] = 'disabled';
+ }
+
+ echo html_writer::select($opts, "items[{$item->id}]", $item->teachermark, false, $attr);
+
+ } else {
+ echo html_writer::empty_tag('img', [
+ 'src' => $item->get_teachermark_image_url(),
+ 'alt' => $item->get_teachermark_text(),
+ 'title' => $item->get_teachermark_text(),
+ 'class' => $item->get_teachermark_class(),
+ ]);
+ }
+ }
+ }
+ if ($status->is_showcheckbox()) {
+ if (!$item->is_heading()) {
+ $id = ' id='.$itemname.' ';
+ if ($status->is_viewother() && $status->is_showteachermark()) {
+ $id = '';
+ }
+ echo ' ';
+ }
+ }
+ echo ''.format_string($item->displaytext).' ';
+ if (isset($item->modulelink)) {
+ echo ' ';
+ }
+
+ if ($status->is_addown()) {
+ echo ' ';
+ $title = '"'.get_string('additemalt', 'checklist').'"';
+ echo ' ';
+ }
+
+ if ($item->duetime) {
+ if ($item->duetime > time()) {
+ echo ' '.userdate($item->duetime, get_string('strftimedate')).' ';
+ } else {
+ echo ' '.userdate($item->duetime, get_string('strftimedate')).' ';
+ }
+ }
+
+ if ($status->is_showcompletiondates()) {
+ if (!$item->is_heading()) {
+ if ($status->is_showteachermark() && $item->teachertimestamp) {
+ if ($item->get_teachername()) {
+ echo ''.$item->get_teachername().' ';
+ }
+ echo ''.
+ userdate($item->teachertimestamp, get_string('strftimedatetimeshort')).' ';
+ }
+ if ($status->is_showcheckbox() && $item->usertimestamp) {
+ echo ''.
+ userdate($item->usertimestamp, get_string('strftimedatetimeshort')).' ';
+ }
+ }
+ }
+
+ if ($status->is_teachercomments()) {
+ if ($comment = $item->get_comment()) {
+ echo ' ';
+ } else if ($status->is_editcomments()) {
+ echo ' ';
+ }
+ }
+
+ echo ' ';
+
+ // Output any user-added items.
+ if ($useritems) {
+ /** @var checklist_item $useritem */
+ $useritem = current($useritems);
+
+ if ($useritem && ($useritem->position == $item->position)) {
+ $thisitemurl = new moodle_url($thispageurl, ['action' => 'updateitem', 'sesskey' => sesskey()]);
+
+ echo '';
+ while ($useritem && ($useritem->position == $item->position)) {
+ $itemname = '"item'.$useritem->id.'"';
+ $checked = ($status->is_updateform() && $useritem->is_checked_student()) ? ' checked="checked" ' : '';
+ if ($useritem->is_editme()) {
+ $itemtext = explode("\n", $useritem->displaytext, 2);
+ $itemtext[] = '';
+ $text = $itemtext[0];
+ $note = $itemtext[1];
+ $thisitemurl->param('itemid', $useritem->id);
+
+ echo '';
+ echo '';
+ if ($status->is_showcheckbox()) {
+ echo ' ';
+ }
+ echo '
';
+ echo html_writer::input_hidden_params($thisitemurl);
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ''.s($note).' ';
+ echo ' ';
+ echo '';
+
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ' ';
+
+ $focusitem = 'updateitembox';
+ } else {
+ echo '';
+ if ($status->is_showcheckbox()) {
+ echo ' ';
+ }
+ $splittext = explode("\n", s($useritem->displaytext), 2);
+ $splittext[] = '';
+ $text = $splittext[0];
+ $note = str_replace("\n", ' ', $splittext[1]);
+ echo ''.$text.' ';
+
+ if ($status->is_addown()) {
+ $baseurl = $thispageurl.'&itemid='.$useritem->id.'&sesskey='.sesskey().'&action=';
+ echo ' ';
+ $title = '"'.get_string('edititem', 'checklist').'"';
+ echo ' ';
+
+ echo ' ';
+ $title = '"'.get_string('deleteitem', 'checklist').'"';
+ echo ' ';
+ }
+ if ($note != '') {
+ echo ''.$note.'
';
+ }
+
+ echo ' ';
+ }
+ $useritem = next($useritems);
+ }
+ echo ' ';
+ }
+ }
+
+ if ($status->is_addown() && ($item->id == $status->get_additemafter())) {
+ $thisitemurl = clone $thispageurl;
+ $thisitemurl->param('action', 'additem');
+ $thisitemurl->param('position', $item->position);
+ $thisitemurl->param('sesskey', sesskey());
+
+ echo '';
+ echo '';
+ echo '
';
+ echo html_writer::input_hidden_params($thisitemurl);
+ if ($status->is_showcheckbox()) {
+ echo ' ';
+ }
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo '';
+
+ echo '';
+ echo html_writer::input_hidden_params($thispageurl);
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ echo ' ';
+
+ if (!$focusitem) {
+ $focusitem = 'additembox';
+ }
+ }
+ }
+ echo ' ';
+
+ if ($status->is_updateform()) {
+ echo ' ';
+ if ($status->is_viewother()) {
+ echo ' ';
+ echo ' ';
+ echo ' ';
+ }
+ echo ' ';
+ }
+
+ if ($focusitem) {
+ echo '';
+ }
+
+ if ($status->is_addown()) {
+ echo '';
+ }
+ }
+
+ echo $this->output->box_end();
+ }
+
+ /**
+ * @param checklist_item[] $items
+ * @param output_status $status
+ */
+ public function checklist_edit_items($items, $status) {
+ echo $this->output->box_start('generalbox boxwidthwide boxaligncenter');
+
+ $currindent = 0;
+ $addatend = true;
+ $focusitem = false;
+ $hasauto = false;
+
+ $thispageurl = new moodle_url($this->page->url, ['sesskey' => sesskey()]);
+ if ($status->get_additemafter()) {
+ $thispageurl->param('additemafter', $status->get_additemafter());
+ }
+ if ($status->is_editdates()) {
+ $thispageurl->param('editdates', 'on');
+ }
+ if ($status->get_itemid()) {
+ $thispageurl->param('itemid', $status->get_itemid());
+ }
+
+ if ($status->is_autoupdatewarning()) {
+ switch ($status->get_autoupdatewarning()) {
+ case CHECKLIST_MARKING_STUDENT:
+ echo ''.get_string('autoupdatewarning_student', 'checklist').'
';
+ break;
+ case CHECKLIST_MARKING_TEACHER:
+ echo ''.get_string('autoupdatewarning_teacher', 'checklist').'
';
+ break;
+ default:
+ echo ''.get_string('autoupdatewarning_both', 'checklist').'
';
+ break;
+ }
+ }
+
+ // Start the ordered list of checklist items.
+ $attr = ['class' => 'checklist'];
+ if ($status->is_editdates()) {
+ $attr['class'] .= ' checklist-extendedit';
+ }
+ echo html_writer::start_tag('ol', $attr);
+
+ // Output each item.
+ if ($items) {
+ $lastitem = count($items);
+ $lastindent = 0;
+
+ echo html_writer::start_tag('form', array('action' => $thispageurl->out_omit_querystring(), 'method' => 'post'));
+ echo html_writer::input_hidden_params($thispageurl);
+
+ if ($status->is_autopopulate()) {
+ echo html_writer::empty_tag('input', array(
+ 'type' => 'submit', 'name' => 'showhideitems',
+ 'value' => get_string('showhidechecked', 'checklist')
+ ));
+ }
+
+ foreach ($items as $item) {
+
+ while ($item->indent > $currindent) {
+ $currindent++;
+ echo '';
+ }
+ while ($item->indent < $currindent) {
+ $currindent--;
+ echo ' ';
+ }
+
+ $itemname = '"item'.$item->id.'"';
+ $itemurl = new moodle_url($thispageurl, ['itemid' => $item->id]);
+
+ switch ($item->colour) {
+ case 'red':
+ $itemcolour = 'itemred';
+ $nexticon = 'colour_orange';
+ break;
+ case 'orange':
+ $itemcolour = 'itemorange';
+ $nexticon = 'colour_green';
+ break;
+ case 'green':
+ $itemcolour = 'itemgreen';
+ $nexticon = 'colour_purple';
+ break;
+ case 'purple':
+ $itemcolour = 'itempurple';
+ $nexticon = 'colour_black';
+ break;
+ default:
+ $itemcolour = 'itemblack';
+ $nexticon = 'colour_red';
+ }
+
+ $autoitem = ($status->is_autopopulate()) && ($item->moduleid != 0);
+ if ($autoitem) {
+ $autoclass = ' itemauto';
+ } else {
+ $autoclass = '';
+ }
+ $hasauto = $hasauto || ($item->moduleid != 0);
+
+ if ($item->is_editme()) {
+ echo '';
+ } else {
+ echo ' ';
+ }
+
+ echo html_writer::start_span('', array('style' => 'display: inline-block; width: 16px;'));
+ if ($autoitem && $item->hidden != CHECKLIST_HIDDEN_BYMODULE) {
+ echo html_writer::checkbox('items['.$item->id.']', $item->id, false, '',
+ array('title' => $item->displaytext));
+ }
+ echo html_writer::end_span();
+
+ // Item optional toggle.
+ if ($item->is_optional()) {
+ $title = '"'.get_string('optionalitem', 'checklist').'"';
+ echo '';
+ echo ' ';
+ $optional = ' class="itemoptional '.$itemcolour.$autoclass.'" ';
+ } else if ($item->is_heading()) {
+ if ($item->hidden) {
+ $title = '"'.get_string('headingitem', 'checklist').'"';
+ echo ' ';
+ $optional = ' class="'.$itemcolour.$autoclass.' itemdisabled"';
+ } else {
+ $title = '"'.get_string('headingitem', 'checklist').'"';
+ if (!$autoitem) {
+ echo '';
+ }
+ echo ' ';
+ if (!$autoitem) {
+ echo ' ';
+ }
+ echo ' ';
+ $optional = ' class="itemheading '.$itemcolour.$autoclass.'" ';
+ }
+ } else if ($item->hidden) {
+ $title = '"'.get_string('requireditem', 'checklist').'"';
+ echo ' ';
+ $optional = ' class="'.$itemcolour.$autoclass.' itemdisabled"';
+ } else {
+ $title = '"'.get_string('requireditem', 'checklist').'"';
+ echo '';
+ echo ' ';
+ $optional = ' class="'.$itemcolour.$autoclass.'"';
+ }
+
+ if ($item->is_editme()) {
+ // Edit item form.
+ $focusitem = 'updateitembox';
+ $addatend = false;
+ echo $this->edit_item_form($status, $item);
+
+ } else {
+ // Item text.
+ echo ''.format_string($item->displaytext).' ';
+
+ // Item colour.
+ echo '';
+ $title = '"'.get_string('changetextcolour', 'checklist').'"';
+ echo ' ';
+
+ // Edit item.
+ if (!$autoitem) {
+ $edititemurl = new moodle_url($itemurl, ['action' => 'edititem']);
+ $edititemurl->remove_params('additemafter');
+ echo '';
+ $title = '"'.get_string('edititem', 'checklist').'"';
+ echo ' ';
+ }
+
+ // Change item indent.
+ if (!$autoitem && $item->indent > 0) {
+ echo '';
+ $title = '"'.get_string('unindentitem', 'checklist').'"';
+ echo ' ';
+ }
+ if (!$autoitem && ($item->indent < CHECKLIST_MAX_INDENT) && (($lastindent + 1) > $currindent)) {
+ echo '';
+ $title = '"'.get_string('indentitem', 'checklist').'"';
+ echo ' ';
+ }
+
+ echo ' ';
+
+ // Move item up/down.
+ if (!$autoitem && $item->position > 1) {
+ echo '';
+ $title = '"'.get_string('moveitemup', 'checklist').'"';
+ echo ' ';
+ }
+ if (!$autoitem && $item->position < $lastitem) {
+ echo '';
+ $title = '"'.get_string('moveitemdown', 'checklist').'"';
+ echo ' ';
+ }
+
+ // Hide/delete item.
+ if ($autoitem) {
+ if ($item->hidden != CHECKLIST_HIDDEN_BYMODULE) {
+ echo ' ';
+ if ($item->hidden == CHECKLIST_HIDDEN_MANUAL) {
+ $title = '"'.get_string('show').'"';
+ echo ' ';
+ } else {
+ $title = '"'.get_string('hide').'"';
+ echo ' ';
+ }
+ }
+ } else {
+ echo ' ';
+ $title = '"'.get_string('deleteitem', 'checklist').'"';
+ echo ' ';
+ }
+
+ // Add item icon.
+ echo ' ';
+ $title = '"'.get_string('additemhere', 'checklist').'"';
+ echo ' ';
+ if ($item->duetime) {
+ if ($item->duetime > time()) {
+ echo ' '.userdate($item->duetime, get_string('strftimedate')).' ';
+ } else {
+ echo ' '.
+ userdate($item->duetime, get_string('strftimedate')).' ';
+ }
+ }
+
+ }
+
+ if ($status->get_additemafter() == $item->id) {
+ $addatend = false;
+ if (!$focusitem) {
+ $focusitem = 'additembox';
+ }
+ echo $this->add_item_form($status, $thispageurl, $currindent, $item->position + 1);
+ }
+
+ $lastindent = $currindent;
+
+ echo ' ';
+ }
+
+ echo html_writer::end_tag('form');
+ }
+
+ if ($addatend) {
+ if (!$focusitem) {
+ $focusitem = 'additembox';
+ }
+ echo $this->add_item_form($status, $thispageurl, $currindent);
+ }
+ echo '';
+ while ($currindent) {
+ $currindent--;
+ echo '';
+ }
+
+ // Edit dates button.
+ $editdatesurl = new moodle_url($thispageurl);
+ $editdatesurl->remove_params('sesskey');
+ if ($status->is_editdates()) {
+ $editdatesurl->remove_params('editdates');
+ $editdatesstr = get_string('editdatesstop', 'mod_checklist');
+ } else {
+ $editdatesurl->param('editdates', 'on');
+ $editdatesstr = get_string('editdatesstart', 'mod_checklist');
+ }
+ echo $this->output->single_button($editdatesurl, $editdatesstr, 'get');
+
+ // Remove autopopulate button.
+ if (!$status->is_autopopulate() && $hasauto) {
+ $removeautourl = new moodle_url($thispageurl, ['removeauto' => 1]);
+ echo $this->output->single_button($removeautourl, get_string('removeauto', 'mod_checklist'));
+ }
+
+ if ($focusitem) {
+ echo '';
+ }
+
+ echo $this->output->box_end();
+ }
+
+ protected function print_edit_date($ts = 0) {
+ $out = '';
+
+ $out .= ' ';
+ $id = uniqid();
+ if ($ts == 0) {
+ $disabled = true;
+ $date = usergetdate(time());
+ } else {
+ $disabled = false;
+ $date = usergetdate($ts);
+ }
+ $day = $date['mday'];
+ $month = $date['mon'];
+ $year = $date['year'];
+
+ // Day.
+ $opts = range(1, 31);
+ $opts = array_combine($opts, $opts);
+ $out .= html_writer::select($opts, 'duetime[day]', $day, null, ['id' => "timedueday{$id}"]);
+
+ // Month.
+ $opts = [];
+ for ($i = 1; $i <= 12; $i++) {
+ $opts[$i] = userdate(gmmktime(12, 0, 0, $i, 15, 2000), "%B");
+ }
+ $out .= html_writer::select($opts, 'duetime[month]', $month, null, ['id' => "timeduemonth{$id}"]);
+
+ // Year.
+ $today = usergetdate(time());
+ $thisyear = $today['year'];
+ $opts = range($thisyear - 5, $thisyear + 10);
+ $opts = array_combine($opts, $opts);
+ $out .= html_writer::select($opts, 'duetime[year]', $year, null, ['id' => "timedueyear{$id}"]);
+
+ // Disabled checkbox.
+ $attr = [
+ 'type' => 'checkbox', 'name' => 'duetimedisable',
+ 'id' => "timeduedisable{$id}", 'onclick' => "toggledate{$id}()"
+ ];
+ if ($disabled) {
+ $attr['checked'] = 'checked';
+ }
+ $out .= html_writer::empty_tag('input', $attr);
+ $out .= html_writer::label(get_string('disable'), "timeduedisable{$id}");
+
+ // Script to disable items when unchecked.
+ $out .= <<< ENDSCRIPT
+
+ENDSCRIPT;
+
+ return $out;
+ }
+
+ /**
+ * @param output_status $status
+ * @param moodle_url $thispageurl
+ * @param int $currindent
+ * @param int $position (optional)
+ * @return string
+ */
+ protected function add_item_form(output_status $status, moodle_url $thispageurl, $currindent, $position = null) {
+ $out = '';
+ $addingatend = ($position === null);
+
+ $out .= '';
+ if ($addingatend) {
+ $out .= '';
+ $out .= html_writer::input_hidden_params($thispageurl);
+ }
+
+ if ($addingatend) {
+ $out .= ' ';
+ } else {
+ $out .= ' ';
+ }
+ $out .= ' ';
+ $out .= ' ';
+ $out .= ' ';
+ $out .= ' ';
+ if (!$addingatend) {
+ $out .= ' ';
+ }
+ if ($status->is_editdates()) {
+ $out .= $this->print_edit_date();
+ }
+
+ if ($position === null) {
+ $out .= ' ';
+ }
+ $out .= ' ';
+
+ return $out;
+ }
+
+ /**
+ * @param output_status $status
+ * @param checklist_item $item
+ * @return string
+ */
+ protected function edit_item_form(output_status $status, checklist_item $item) {
+ $out = '';
+
+ $out .= ' ';
+ $out .= ' ';
+ $out .= ' ';
+ if ($status->is_editdates()) {
+ $out .= $this->print_edit_date($item->duetime);
+ }
+
+ return $out;
+ }
+}
\ No newline at end of file
diff --git a/styles.css b/styles.css
index eed4f536..94bdc5d4 100644
--- a/styles.css
+++ b/styles.css
@@ -4,6 +4,9 @@ ol.checklist {
margin-top: 10px;
margin-bottom: 0;
}
+ol.checklist ol.checklist {
+ margin-top: 0;
+}
ol.checklist li {
list-style-type: none;
@@ -175,6 +178,12 @@ ol.checklist li .itemteachername {
background-color: #bf0000;
}
+.checklist_progress_heading {
+ display: block;
+ float: left;
+ width: 150px;
+}
+
.checklist_progress_outer {
border-width: 1px;
border-style: solid;
@@ -191,6 +200,7 @@ ol.checklist li .itemteachername {
.checklist_progress_inner {
background-color: #229b15;
+ background-image: url([[pix:mod_checklist|progress]]);
height: 100%;
width: 100%;
background-repeat: repeat-x;
@@ -206,6 +216,7 @@ ol.checklist li .itemteachername {
.checklist_progress_anim {
background-color: #98c193;
+ background-image: url([[pix:mod_checklist|progress-fade]]);
height: 15px;
width: 0;
background-repeat: repeat-x;
@@ -256,4 +267,10 @@ p.checklistwarning {
ol.checklist label {
display: inline;
+}
+
+.checklist-extendedit .checklist-edititem {
+ border: 1px solid #ddd;
+ padding: 10px 0 5px;
+ margin: 5px 0;
}
\ No newline at end of file
diff --git a/updatechecks.php b/updatechecks.php
index f93f5461..f7b5dc53 100644
--- a/updatechecks.php
+++ b/updatechecks.php
@@ -28,7 +28,7 @@
global $DB, $CFG, $PAGE, $USER;
$id = required_param('id', PARAM_INT); // Course_module ID.
-$items = optional_param_array('items', false, PARAM_INT);
+$items = required_param_array('items', PARAM_INT);
$url = new moodle_url('/mod/checklist/view.php', array('id' => $id));
@@ -41,19 +41,10 @@
$context = context_module::instance($cm->id);
$userid = $USER->id;
-if (!has_capability('mod/checklist:updateown', $context)) {
- echo 'Error: you do not have permission to update this checklist';
- die();
-}
-if (!confirm_sesskey()) {
- echo 'Error: invalid sesskey';
- die();
-}
-if (!$items || !is_array($items)) {
- echo 'Error: invalid (or missing) items list';
- die();
-}
-if (!empty($items)) {
+require_capability('mod/checklist:updateown', $context);
+require_sesskey();
+
+if ($items) {
$chk = new checklist_class($cm->id, $userid, $checklist, $cm, $course);
$chk->ajaxupdatechecks($items);
}
diff --git a/version.php b/version.php
index 23441515..25433963 100644
--- a/version.php
+++ b/version.php
@@ -27,7 +27,7 @@
$plugin->version = 2016090900; // The current module version (Date: YYYYMMDDXX)
$plugin->cron = 0; // Period for cron to check this module (secs).
-$plugin->maturity = MATURITY_STABLE;
+$plugin->maturity = MATURITY_BETA;
$plugin->release = '2.7+ (Build: 2016090900)';
$plugin->requires = 2014051200; // Moodle 2.7+.
$plugin->component = 'mod_checklist';