From f4b98f1c9e935bff7abc7a92d4c84f5cc7f9cd08 Mon Sep 17 00:00:00 2001 From: AL Rachels Date: Mon, 1 Jul 2024 12:05:25 -0500 Subject: [PATCH] Completion fixes --- classes/completion/custom_completion.php | 45 +++++++++---- classes/event/update_vote.php | 4 +- classes/privacy/provider.php | 4 +- lang/en/hotquestion.php | 84 ++++++++++++------------ lib.php | 7 +- locallib.php | 9 +-- pix/monologo.svg | 17 ++++- renderer.php | 10 +-- view.php | 6 ++ 9 files changed, 113 insertions(+), 73 deletions(-) diff --git a/classes/completion/custom_completion.php b/classes/completion/custom_completion.php index b047d70..1abf4e8 100644 --- a/classes/completion/custom_completion.php +++ b/classes/completion/custom_completion.php @@ -42,42 +42,59 @@ public function get_state(string $rule): int { global $DB; $this->validate_rule($rule); - $userid = $this->userid; $hotquestionid = $this->cm->instance; if (!$hotquestion = $DB->get_record('hotquestion', ['id' => $hotquestionid])) { throw new moodle_exception(get_string('incorrectmodule', 'hotquestion')); - } + $status = COMPLETION_INCOMPLETE; $questioncountparams = ['userid' => $userid, 'hotquestionid' => $hotquestionid]; $questionvoteparams = ['userid' => $userid, 'hotquestionid' => $hotquestionid]; + $questionpostsql = "SELECT COUNT(hqq.id) + FROM {hotquestion_questions} hqq + WHERE hqq.hotquestion = :hotquestionid + AND hqq.userid = :userid"; + $questionvotesql = "SELECT COUNT(hv.id) FROM {hotquestion_votes} hv - JOIN {hotquestion_questions} hq ON hq.id = hv.question - WHERE hq.hotquestion = :hotquestionid + JOIN {hotquestion_questions} hqq ON hqq.id = hv.question + WHERE hqq.hotquestion = :hotquestionid AND hv.voter = :userid"; $questiongradesql = "SELECT * FROM {hotquestion_grades} hqg JOIN {hotquestion_questions} hqq ON hqg.hotquestion = hqq.id + JOIN {hotquestion} hq ON hq.id = hqg.hotquestion WHERE hqg.userid = :userid AND hqq.id = :hotquestionid"; if ($rule == 'completionpost') { - $status = $hotquestion->completionpost <= - $DB->count_records('hotquestion_questions', ['hotquestion' => $hotquestionid, 'userid' => $userid]); - + if ($status = $hotquestion->completionpost <= + $DB->get_field_sql($questionpostsql, $questioncountparams)) { + $status = $hotquestion->completionpost = 1; + } else { + $status = $hotquestion->completionpost = 0; + } } else if ($rule == 'completionvote') { - $status = $hotquestion->completionvote <= - $DB->get_field_sql($questionvotesql, $questionvoteparams); + if ($status = $hotquestion->completionvote <= + $DB->get_field_sql($questionvotesql, $questionvoteparams)) { + $status = $hotquestion->completionvote = 1; + } else { + $status = $hotquestion->completionvote = 0; + } } else if ($rule == 'completionpass') { - $status = $hotquestion->completionpass <= + if ($status = $hotquestion->completionpass <= $DB->get_field_sql($questioncountsql. - ' AND hqg.userid = $userid AND hqg.rawrating >= hqqcompletionpass', - $questioncountparams); + //' AND hqg.userid = $userid AND hqg.rawrating >= hqqcompletionpass', + ' AND hqg.userid = $userid AND hqg.rawrating >= hqgrade', + $questioncountparams)) { + $status = $hotquestion->completionpass = 1; + } else { + $status = $hotquestion->completionpass = 0; + } } return $status ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE; } @@ -91,6 +108,7 @@ public static function get_defined_custom_rules(): array { return [ 'completionpost', 'completionvote', + 'completionpass', ]; } @@ -102,9 +120,11 @@ public static function get_defined_custom_rules(): array { public function get_custom_rule_descriptions(): array { $completionpost = $this->cm->customdata['customcompletionrules']['completionpost'] ?? 0; $completionvote = $this->cm->customdata['customcompletionrules']['completionvote'] ?? 0; + $completionpass = $this->cm->customdata['customcompletionrules']['completionpass'] ?? 0; return [ 'completionpost' => get_string('completiondetail:post', 'hotquestion', $completionpost), 'completionvote' => get_string('completiondetail:vote', 'hotquestion', $completionvote), + 'completionpass' => get_string('completiondetail:pass', 'hotquestion', $completionpass), ]; } @@ -118,6 +138,7 @@ public function get_sort_order(): array { 'completionview', 'completionpost', 'completionvote', + 'completionpass', 'completionusegrade', 'completionpassgrade', ]; diff --git a/classes/event/update_vote.php b/classes/event/update_vote.php index d41e433..bd6fb64 100644 --- a/classes/event/update_vote.php +++ b/classes/event/update_vote.php @@ -59,8 +59,8 @@ public static function get_name() { * @return string */ public function get_description() { - return "The user with id '$this->userid' has just voted for a question in the hotquestion activity with the course module ". - " id '$this->contextinstanceid'."; + return "The user with id '$this->userid' has just voted for a question in the hotquestion activity with the course module id + '$this->contextinstanceid'."; } /** diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index c8d31aa..f662a84 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -58,7 +58,7 @@ class provider implements \core_privacy\local\metadata\provider, * @param collection $collection The initialised collection to add items to. * @return collection The updated collection of metadata items. */ - public static function get_metadata(collection $collection): collection { + public static function get_metadata(collection $collection) : collection { $collection->add_database_table( 'hotquestion_questions', [ @@ -107,7 +107,7 @@ private static function get_modid() { * @param int $userid The user to search. * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. */ - public static function get_contexts_for_userid(int $userid): contextlist { + public static function get_contexts_for_userid(int $userid) : contextlist { $contextlist = new contextlist(); $modid = self::get_modid(); if (!$modid) { diff --git a/lang/en/hotquestion.php b/lang/en/hotquestion.php index dbf550f..67cf32d 100644 --- a/lang/en/hotquestion.php +++ b/lang/en/hotquestion.php @@ -28,11 +28,11 @@ $string['ago'] = '{$a} ago'; $string['allowanonymouspost'] = 'Allow post question as anonymous'; -$string['allowanonymouspost_descr'] = 'If enabled, questions can be posted anonomously, and if approved for viewing heat votes can be made by everyone.'; $string['allowanonymouspost_help'] = 'If enabled, questions can be posted anonomously, and if approved for viewing heat votes can be made by everyone.'; +$string['allowanonymouspost_descr'] = 'If enabled, questions can be posted anonomously, and if approved for viewing heat votes can be made by everyone.'; $string['allowauthorinfohide'] = 'Allow authors name to be hidden'; -$string['allowauthorinfohide_descr'] = 'If enabled, the name of the questions author can be visible to teachers but hidden from students.'; $string['allowauthorinfohide_help'] = 'If enabled, the name of the questions author can be visible to teachers but hidden from students.'; +$string['allowauthorinfohide_descr'] = 'If enabled, the name of the questions author can be visible to teachers but hidden from students.'; $string['allowcomments'] = 'Allow comments on entries'; $string['allowcomments_help'] = 'If enabled, all participants with permission to create comments will be able to add comments to hot question entries.'; $string['alwaysshowdescription'] = 'Always show description'; @@ -40,25 +40,25 @@ $string['anonymous'] = 'Anonymous'; $string['approvallabel'] = 'Approval required column label'; $string['approvallabel_descr'] = 'Enter a default label for the Approved column.'; -$string['approvedno'] = 'Not approved'; $string['approvedyes'] = 'Approved'; +$string['approvedno'] = 'Not approved'; $string['authorinfo'] = 'Posted by {$a->user} at {$a->time}'; $string['authorinfohide'] = 'Posted {$a->time}'; $string['calendarend'] = '{$a} closes'; $string['calendarstart'] = '{$a} opens'; $string['cnfallowcomments'] = 'Define if a hot question will accept comments on entries by default'; -$string['completiondetail:pass'] = 'Passing grade: {$a}'; $string['completiondetail:post'] = 'Post questions: {$a}'; $string['completiondetail:vote'] = 'Give heat: {$a}'; -$string['completionpass'] = 'Student must pass:'; +$string['completiondetail:pass'] = 'Passing grade: {$a}'; +$string['completionpostdesc'] = 'Student must create at least {$a} questions(s)'; +$string['completionvotedesc'] = 'Student must vote/give heat to {$a} question(s) or post(s)'; $string['completionpassdesc'] = 'Student must receive passing grade of {$a}'; +$string['completionpostgroup'] = 'Require questions'; +$string['completionvotegroup'] = 'Require heat:'; $string['completionpassgroup'] = 'Require pass:'; $string['completionpost'] = 'Student must add questions:'; -$string['completionpostdesc'] = 'Student must create at least {$a} questions(s)'; -$string['completionpostgroup'] = 'Require questions'; $string['completionvote'] = 'Student must add heat:'; -$string['completionvotedesc'] = 'Student must vote/give heat to {$a} question(s) or post(s)'; -$string['completionvotegroup'] = 'Require heat:'; +$string['completionpass'] = 'Student must pass:'; $string['connectionerror'] = 'Connection error'; $string['content'] = 'Content'; $string['csvexport'] = 'Export to .csv'; @@ -115,9 +115,15 @@ $string['heatlimit_help'] = 'Enter a default for the number of times you can apply heat/vote, per round. Zero hides the heat column.'; $string['heatreceived'] = 'Heat received'; $string['heatvisibility'] = 'Heat column visibility'; -$string['heatvisibility_descr'] = 'If enabled, the Heat column is visible, otherwise it is hidden.'; $string['heatvisibility_help'] = 'If enabled, the Heat column is visible.'; +$string['heatvisibility_descr'] = 'If enabled, the Heat column is visible, otherwise it is hidden.'; $string['hotquestion'] = 'Hotquestion'; +$string['hotquestionclosed'] = 'This activity closed on {$a}.'; +$string['hotquestionclosetime'] = 'Close time'; +$string['hotquestionintro'] = 'Topic'; +$string['hotquestionname'] = 'Activity Name'; +$string['hotquestionopentime'] = 'Open time'; +$string['hotquestionopen'] = 'This activity will be open on {$a}.'; $string['hotquestion:addinstance'] = 'Can add new Hot Question'; $string['hotquestion:ask'] = 'Ask questions'; $string['hotquestion:comment'] = 'Write comments'; @@ -126,96 +132,88 @@ $string['hotquestion:rate'] = 'Rate questions'; $string['hotquestion:view'] = 'View questions'; $string['hotquestion:vote'] = 'Vote on questions'; -$string['hotquestionclosed'] = 'This activity closed on {$a}.'; -$string['hotquestionclosetime'] = 'Close time'; -$string['hotquestionintro'] = 'Topic'; -$string['hotquestionname'] = 'Activity Name'; -$string['hotquestionopen'] = 'This activity will be open on {$a}.'; -$string['hotquestionopentime'] = 'Open time'; -$string['id'] = 'ID'; $string['improperuseviewgradesclass'] = 'Improper use of the viewgrades class. Cannot load the grade item.'; $string['incorrectmodule'] = 'Course Module ID was incorrect'; -$string['inputapprovallabel'] = 'Approved'; -$string['inputapprovallabel_descr'] = 'Change the Approved column name to what you want it to be.'; -$string['inputapprovallabel_help'] = 'Change the Approved column name to better fit the use of this activity.'; -$string['inputheatlabel'] = 'Heat'; -$string['inputheatlabel_descr'] = 'Change the Heat column name to what you want it to be.'; -$string['inputheatlabel_help'] = 'Change the Heat column name to better fit the use of this activity.'; +$string['id'] = 'ID'; $string['inputquestion'] = 'Submit your question here:'; $string['inputquestion_descr'] = 'Change submit directions to what you want them to be.'; $string['inputquestion_help'] = 'Change the submit directions to what you want them to be.'; $string['inputquestionlabel'] = 'Questions'; $string['inputquestionlabel_descr'] = 'Change the Questions column name to what you want it to be.'; $string['inputquestionlabel_help'] = 'Change the Questions column name to better fit the use of this activity.'; -$string['inputremovelabel'] = 'Remove'; -$string['inputremovelabel_descr'] = 'Change the Remove column name to what you want it to be.'; -$string['inputremovelabel_help'] = 'Change the remove column name to better fit the use of this activity.'; $string['inputteacherprioritylabel'] = 'Priority'; $string['inputteacherprioritylabel_descr'] = 'Change the Priority column name to what you want it to be.'; $string['inputteacherprioritylabel_help'] = 'Change the Priority column name to better fit the use of this activity.'; +$string['inputheatlabel'] = 'Heat'; +$string['inputheatlabel_descr'] = 'Change the Heat column name to what you want it to be.'; +$string['inputheatlabel_help'] = 'Change the Heat column name to better fit the use of this activity.'; +$string['inputremovelabel'] = 'Remove'; +$string['inputremovelabel_descr'] = 'Change the Remove column name to what you want it to be.'; +$string['inputremovelabel_help'] = 'Change the remove column name to better fit the use of this activity.'; +$string['inputapprovallabel'] = 'Approved'; +$string['inputapprovallabel_descr'] = 'Change the Approved column name to what you want it to be.'; +$string['inputapprovallabel_help'] = 'Change the Approved column name to better fit the use of this activity.'; $string['invalidquestion'] = 'Empty questions are ignored.'; $string['modulename'] = 'Hot Question'; $string['modulename_help'] = 'A Hot Question activity enables students to post and vote on posts, in response to questions asked by course teachers.'; $string['modulename_link'] = 'mod/hotquestion/view'; $string['modulenameplural'] = 'Hot Questions'; $string['newround'] = 'Open a new round'; -$string['newroundconfirm'] = 'Confirm you want to start a new round? (Existing questions and votes will be archived and can not be added to!)'; $string['newroundsuccess'] = 'You have successfully opened a new round.'; +$string['newroundconfirm'] = 'Confirm you want to start a new round? (Existing questions and votes will be archived and can not be added to!)'; $string['nextround'] = 'Next round'; $string['noquestions'] = 'No entries yet.'; -$string['notapproved'] = 'This entry is not currently approved for viewing.
'; $string['notavailable'] = 'Not currently available!
'; +$string['notapproved'] = 'This entry is not currently approved for viewing.
'; $string['pluginadministration'] = 'Hot question administration'; $string['pluginname'] = 'Hot Question'; +$string['previousround'] = 'Previous round'; $string['postbutton'] = 'Click to post'; $string['postmaxgrade'] = 'Questions for max grading'; $string['postmaxgrade_help'] = 'The number of questions required to obtain the maximum score. This is nominally a count of questions, but the value attained by a user may be improved by heat factor (questions with greater heat count more) and by voting on other questions (a user may improve the grade by participating in voting for questions by other students).'; -$string['previousround'] = 'Previous round'; -$string['prioritydown'] = 'Priority down'; -$string['priorityup'] = 'Priority up'; $string['privacy:metadata:hotquestion_questions'] = "Information about the user's entries for a given Hot Question activity. "; -$string['privacy:metadata:hotquestion_questions:anonymous'] = 'Is the entry posted as anonymous?'; -$string['privacy:metadata:hotquestion_questions:approved'] = 'Is the question approved for general viewing?'; -$string['privacy:metadata:hotquestion_questions:content'] = 'The content of the question.'; +$string['privacy:metadata:hotquestion_questions:userid'] = 'The ID of the user that posted this entry.'; $string['privacy:metadata:hotquestion_questions:hotquestion'] = 'The ID of the Hot Question activity in which the content was posted.'; -$string['privacy:metadata:hotquestion_questions:id'] = 'ID of the entry.'; +$string['privacy:metadata:hotquestion_questions:content'] = 'The content of the question.'; $string['privacy:metadata:hotquestion_questions:time'] = 'Time the question was posted.'; +$string['privacy:metadata:hotquestion_questions:id'] = 'ID of the entry.'; +$string['privacy:metadata:hotquestion_questions:anonymous'] = 'Is the entry posted as anonymous?'; +$string['privacy:metadata:hotquestion_questions:approved'] = 'Is the question approved for general viewing?'; $string['privacy:metadata:hotquestion_questions:tpriority'] = 'Has the teacher given a priority for this entry?'; -$string['privacy:metadata:hotquestion_questions:userid'] = 'The ID of the user that posted this entry.'; $string['privacy:metadata:hotquestion_votes'] = 'Information about votes on questions.'; $string['privacy:metadata:hotquestion_votes:id'] = 'ID of the entry.'; $string['privacy:metadata:hotquestion_votes:question'] = 'The ID of the entry for this vote'; $string['privacy:metadata:hotquestion_votes:voter'] = 'User ID who voted.'; +$string['teacherprioritylabel'] = 'Priority column label'; +$string['teacherprioritylabel_descr'] = 'Enter a default label for the Priority column.'; $string['question'] = 'Question'; +$string['questions'] = 'Questions'; $string['questionlabel'] = 'Questions column label'; $string['questionlabel_descr'] = 'Enter a default label for the Questions column.'; +$string['questionsubmitted'] = 'Your post has been submitted successfully.'; $string['questionremove'] = 'Remove'; $string['questionremovesuccess'] = 'You have successfully removed that question.'; -$string['questions'] = 'Questions'; -$string['questionsubmitted'] = 'Your post has been submitted successfully.'; $string['rawgrade'] = 'Raw grade {$a->rawgrade} / {$a->max}'; -$string['removedround'] = 'You have successfully removed this round.'; $string['removelabel'] = 'Remove column label'; $string['removelabel_descr'] = 'Enter a default label for the Remove column.'; $string['removeround'] = 'Remove this round'; +$string['removedround'] = 'You have successfully removed this round.'; $string['removevote'] = 'Remove my vote'; $string['requireapproval'] = 'Approval required'; -$string['requireapproval_descr'] = 'If enabled, questions require approval by a teacher before they are viewable by everyone.'; $string['requireapproval_help'] = 'If enabled, questions require approval by a teacher before they are viewable by everyone.'; +$string['requireapproval_descr'] = 'If enabled, questions require approval by a teacher before they are viewable by everyone.'; $string['resethotquestion'] = 'Delete all questions and votes'; $string['returnto'] = 'Return to {$a}'; $string['round'] = 'Round {$a}'; $string['showrecentactivity'] = 'Show recent activity'; $string['showrecentactivityconfig'] = 'Everyone can see notifications in recent activity reports.'; $string['teacherpriority'] = 'Priority'; -$string['teacherprioritylabel'] = 'Priority column label'; -$string['teacherprioritylabel_descr'] = 'Enter a default label for the Priority column.'; $string['teacherpriorityvisibility'] = 'Teacher priority column visibility'; -$string['teacherpriorityvisibility_descr'] = 'If enabled, the Teacher priority column is visible, otherwise it is hidden.'; $string['teacherpriorityvisibility_help'] = 'If enabled, the Teacher priority column is visible.'; +$string['teacherpriorityvisibility_descr'] = 'If enabled, the Teacher priority column is visible, otherwise it is hidden.'; $string['time'] = 'Time'; $string['totalcomments'] = 'Total comments'; $string['unapprovedquestionhide'] = 'Hide unapproved questions'; diff --git a/lib.php b/lib.php index 12ef29d..96a48a2 100644 --- a/lib.php +++ b/lib.php @@ -583,14 +583,17 @@ function hotquestion_get_extra_capabilities() { function hotquestion_get_completion_state($course, $cm, $userid, $type) { global $DB, $CFG; + // Get hotquestion details. $hotquestion = $DB->get_record('hotquestion', ['id' => $cm->instance], '*', MUST_EXIST); + + // If completion option is enabled, evaluate it and return true/false if (!$hotquestion->completionpost && !$hotquestion->completionvote && !$hotquestion->completionpass) { return $type; } $result = $type; // Default return value. - // Check if the user has used up all attempts. + // Check if the user has made required number of attempts. if ($hotquestion->completionpost) { $value = $hotquestion->completionpost <= $DB->count_records('hotquestion_questions', [ @@ -911,7 +914,7 @@ function hotquestion_rescale_activity_grades(stdClass $course, stdClass $cm, flo * * @param stdClass $hotquestion stdClass. */ -function hotquestion_check_ratings_recalculation(stdClass $hotquestion): bool { +function hotquestion_check_ratings_recalculation(stdClass $hotquestion) : bool { global $CFG, $DB; require_once($CFG->dirroot.'/mod/hotquestion/locallib.php'); diff --git a/locallib.php b/locallib.php index cebed52..73359ef 100644 --- a/locallib.php +++ b/locallib.php @@ -663,10 +663,7 @@ public function download_questions($chq, $filename = "export.csv", $delimiter="; if ($hqs = $DB->get_records_sql($sql, $fields)) { $firstrowflag = 1; if (is_siteadmin($USER->id)) { - // Set $currenthqhotquestion to the first hotquestion id of the $hqs array. - $temphqs = $hqs; - reset($temphqs); - $currenthqhotquestion = current($temphqs)->hotquestion; + $currenthqhotquestion = $hqs[1]->hotquestion; } else { $currenthqhotquestion = ''; } @@ -831,7 +828,7 @@ public function tpriority_change($u, $question) { * @param int $userid The single user to calculate the rating for. * @return float $rating number */ - public function calculate_user_ratings($userid = null): float { + public function calculate_user_ratings($userid = null) : float { global $DB, $USER; if (!$userid) { @@ -879,7 +876,7 @@ public function calculate_user_ratings($userid = null): float { * @param int $questionid The question id. * @return array Array of int userids or empty if none. */ - public function get_question_voters(int $questionid): array { + public function get_question_voters(int $questionid) : array { global $DB; $voters = $DB->get_records_menu('hotquestion_votes', ['question' => $questionid], '', 'id, voter'); diff --git a/pix/monologo.svg b/pix/monologo.svg index a437636..1b44e29 100644 --- a/pix/monologo.svg +++ b/pix/monologo.svg @@ -1 +1,16 @@ - \ No newline at end of file + + + + + + + + + + + + diff --git a/renderer.php b/renderer.php index 71d4f8f..d973eb6 100644 --- a/renderer.php +++ b/renderer.php @@ -441,15 +441,15 @@ public function questions($allowvote = true) { .$this->hotquestion->cm->id.'&action=tpriority&u=1&q=' .$question->id.'" class="hotquestion_vote" id="question_' .$question->id.'">'
-                                       .get_string('priorityup', 'hotquestion')
+                                       .get_string('teacherpriority', 'hotquestion').'
 '; $tpriority .= '   '
-                                       .get_string('prioritydown', 'hotquestion') .''; + .get_string('teacherpriority', 'hotquestion') .'" alt="' + .get_string('teacherpriority', 'hotquestion') .'" style="width:16px;height:16px;"/>'; } // Check teacher priority column visibilty settings. @@ -609,7 +609,7 @@ public function hotquestion_get_question_comment_count($question, $cm) { * @param bool $showrating * @return string */ - public function current_user_rating(bool $showrating): string { + public function current_user_rating(bool $showrating) : string { global $USER; $output = ''; diff --git a/view.php b/view.php index 4a30e3f..bfca1cc 100644 --- a/view.php +++ b/view.php @@ -98,6 +98,12 @@ $completion = new completion_info($course); $completion->set_module_viewed($cm); +// 20240701 Added to update completion state after a user post or adds heat. +$ci = new completion_info($course); +if ($cm->completion == COMPLETION_TRACKING_AUTOMATIC) { + $ci->update_state($cm, COMPLETION_UNKNOWN, null); +} + // Set page. if (!$ajax) { $PAGE->set_url('/mod/hotquestion/view.php', ['id' => $hq->cm->id]);