From 353228d8f4e420e252ec592700faa4d686d49ba9 Mon Sep 17 00:00:00 2001 From: skodak Date: Sun, 3 Jun 2007 16:24:03 +0000 Subject: [PATCH] MDL-9548 Implement grade_updated event triggers in Forum --- mod/forum/db/upgrade.php | 8 + mod/forum/lib.php | 322 ++++++++++++++++++++++++++------------- mod/forum/mod_form.php | 9 +- mod/forum/rate.php | 104 +++++++------ mod/forum/version.php | 4 +- 5 files changed, 290 insertions(+), 157 deletions(-) diff --git a/mod/forum/db/upgrade.php b/mod/forum/db/upgrade.php index 3825b67c72..999183cc7a 100644 --- a/mod/forum/db/upgrade.php +++ b/mod/forum/db/upgrade.php @@ -32,6 +32,14 @@ function xmldb_forum_upgrade($oldversion=0) { /// $result = result of "/lib/ddllib.php" function calls /// } + if ($result && $oldversion < 2007060300) { + require_once($CFG->dirroot.'/mod/forum/lib.php'); + // too much debug output + $db->debug = false; + forum_update_grades(); + $db->debug = true; + } + return $result; } diff --git a/mod/forum/lib.php b/mod/forum/lib.php index d0b05e3f16..29760055f4 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1,6 +1,7 @@ libdir.'/filelib.php'); +require_once($CFG->libdir.'/gradelib.php'); /// CONSTANTS /////////////////////////////////////////////////////////// @@ -97,11 +98,11 @@ function forum_add_instance($forum) { $forum->timemodified = time(); - if (!isset($forum->assessed)) { + if (empty($forum->assessed)) { $forum->assessed = 0; } - if (empty($forum->ratingtime)) { + if (empty($forum->ratingtime) or empty($forum->assessed)) { $forum->assesstimestart = 0; $forum->assesstimefinish = 0; } @@ -111,6 +112,7 @@ function forum_add_instance($forum) { } if ($forum->type == 'single') { // Create related discussion. + $discussion = new object(); $discussion->course = $forum->course; $discussion->forum = $forum->id; $discussion->name = $forum->name; @@ -131,6 +133,9 @@ function forum_add_instance($forum) { } } + $forum = stripslashes_recursive($forum); + forum_grade_item_create($forum); + return $forum->id; } @@ -142,13 +147,13 @@ function forum_add_instance($forum) { */ function forum_update_instance($forum) { $forum->timemodified = time(); - $forum->id = $forum->instance; + $forum->id = $forum->instance; if (empty($forum->assessed)) { $forum->assessed = 0; } - if (empty($forum->ratingtime)) { + if (empty($forum->ratingtime) or empty($forum->assessed)) { $forum->assesstimestart = 0; $forum->assesstimefinish = 0; } @@ -170,18 +175,25 @@ function forum_update_instance($forum) { $post->message = $forum->intro; $post->modified = $forum->timemodified; - if (! update_record('forum_posts', $post)) { + if (! update_record('forum_posts', ($post))) { error('Could not update the first post'); } $discussion->name = $forum->name; - if (! update_record('forum_discussions', $discussion)) { + if (! update_record('forum_discussions', ($discussion))) { error('Could not update the discussion'); } } - return update_record('forum', $forum); + if (!update_record('forum', $forum)) { + error('Can not update forum'); + } + + $forum = stripslashes_recursive($forum); + forum_grade_item_update($forum); + + return true; } @@ -216,6 +228,8 @@ function forum_delete_instance($id) { $result = false; } + forum_grade_item_delete($forum); + return $result; } @@ -950,7 +964,7 @@ function forum_print_overview($courses,&$htmlarray) { ' JOIN '.$CFG->prefix.'forum_discussions d ON p.discussion = d.id '. ' LEFT JOIN '.$CFG->prefix.'forum_read r ON r.postid = p.id AND r.userid = '.$USER->id.' WHERE ('; foreach ($trackingforums as $track) { - $sql .= '(d.forum = '.$track->id.' AND (d.groupid = -1 OR d.groupid = 0 OR d.groupid = '.get_current_group($track->course,false).')) OR '; + $sql .= '(d.forum = '.$track->id.' AND (d.groupid = -1 OR d.groupid = 0 OR d.groupid = '.get_current_group($track->course).')) OR '; } $sql = substr($sql,0,-3); // take off the last OR $sql .= ') AND p.modified >= '.$cutoffdate.' AND r.id is NULL GROUP BY d.forum,d.course'; @@ -1095,75 +1109,180 @@ function forum_print_recent_activity($course, $isteacher, $timestart) { return $content; } +/** + * Return grade for given user or all users. + * + * @param int $forumid id of forum + * @param int $userid optional user id, 0 means all users + * @return array array of grades, false if none + */ +function forum_get_user_grades($forumid, $userid=0) { + global $CFG; + + $user = $userid ? "AND u.id = $userid" : ""; + + $sql = "SELECT u.id, avg(fr.rating) AS gradevalue + FROM {$CFG->prefix}user u, {$CFG->prefix}forum_posts fp, + {$CFG->prefix}forum_ratings fr, {$CFG->prefix}forum_discussions fd + WHERE u.id = fp.userid AND fp.discussion = fd.id AND fr.post = fp.id + AND fr.userid != u.id AND fd.forum = $forumid + $user + GROUP BY u.id"; + + return get_records_sql($sql); +} /** - * Must return an array of grades, indexed by user, and a max grade. + * Update grades by firing grade_updated event + * + * @param object $grade_item null means all forums + * @param int $userid specific user only, 0 mean all */ -function forum_grades($forumid) { +function forum_update_grades($grade_item=null, $userid=0, $nullifnone=true) { + global $CFG; - if (!$forum = get_record("forum", "id", $forumid)) { - return false; - } - if (!$forum->assessed) { - return false; - } - $scalemenu = make_grades_menu($forum->scale); + if ($grade_item != null) { + if ($grades = forum_get_user_grades($grade_item->iteminstance, $userid)) { + foreach ($grades as $grade) { + $eventdata = new object(); + $eventdata->itemid = $grade_item->id; + $eventdata->userid = $grade->id; + $eventdata->gradevalue = $grade->gradevalue; + events_trigger('grade_updated', $eventdata); + } - $currentuser = 0; - $ratingsuser = array(); + } else if ($userid and $nullifnone) { + $eventdata = new object(); + $eventdata->itemid = $grade_item->id; + $eventdata->userid = $userid; + $eventdata->gradevalue = NULL; + events_trigger('grade_updated', $eventdata); + } - if ($ratings = forum_get_user_grades($forumid)) { - foreach ($ratings as $rating) { // Ordered by user - if ($currentuser and $rating->userid != $currentuser) { - if (!empty($ratingsuser)) { - if ($forum->scale < 0) { - $return->grades[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser); - $return->grades[$currentuser] .= "
".forum_get_ratings_summary(0, $scalemenu, $ratingsuser); - } else { - $total = 0; - $count = 0; - foreach ($ratingsuser as $ra) { - $total += $ra; - $count ++; - } - $return->grades[$currentuser] = format_float($total/$count, 2); + } else { + $sql = "SELECT f.*, cm.idnumber as cmidnumber + FROM {$CFG->prefix}forum f, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m + WHERE m.name='forum' AND m.id=cm.module AND cm.instance=f.id"; + if ($rs = get_recordset_sql($sql)) { + if ($rs->RecordCount() > 0) { + while ($forum = rs_fetch_next_record($rs)) { + if (!$forum->assessed) { + continue; // no grading } - } else { - $return->grades[$currentuser] = ""; + $grade_item = forum_grade_item_get($forum); + forum_update_grades($grade_item, 0, false); } - $ratingsuser = array(); } - $ratingsuser[] = $rating->rating; - $currentuser = $rating->userid; + rs_close($rs); } - if (!empty($ratingsuser)) { - if ($forum->scale < 0) { - $return->grades[$currentuser] = forum_get_ratings_mean(0, $scalemenu, $ratingsuser); - $return->grades[$currentuser] .= "
".forum_get_ratings_summary(0, $scalemenu, $ratingsuser); - } else { - $total = 0; - $count = 0; - foreach ($ratingsuser as $ra) { - $total += $ra; - $count ++; - } - $return->grades[$currentuser] = format_float((float)$total/(float)$count, 2); - } - } else { - $return->grades[$currentuser] = ""; + } +} + +/** + * Return (create if needed) grade item for given forum + * + * @param object $forum object with optional cmidnumber + * @return object grade_item + */ +function forum_grade_item_get($forum) { + if ($items = grade_get_items($forum->course, 'mod', 'forum', $forum->id)) { + if (count($items) > 1) { + debugging('Multiple grade items present!'); } + $grade_item = reset($items); + } else { - $return->grades = array(); + if (!isset($forum->cmidnumber)) { + if (!$cm = get_coursemodule_from_instance('forum', $forum->id)) { + error("Course Module ID was incorrect"); + } + $forum->cmidnumber = $cm->idnumber; + } + if (!$itemid = forum_grade_item_create($forum)) { + error('Can not create grade item!'); + } + $grade_item = grade_item::fetch('id', $itemid); } - if ($forum->scale < 0) { - $return->maxgrade = ""; - } else { - $return->maxgrade = $forum->scale; + return $grade_item; +} + +/** + * Update grade item for given forum + * + * @param object $forum object with extra cmidnumber + * @return object grade_item + */ +function forum_grade_item_update($forum) { + $grade_item = forum_grade_item_get($forum); + + $grade_item->name = $forum->name; + $grade_item->idnumber = $forum->cmidnumber; + + if (!$forum->assessed) { + //how to indicate no grading? + $grade_item->gradetype = GRADE_TYPE_TEXT; + + } else if ($forum->scale > 0) { + $grade_item->gradetype = GRADE_TYPE_VALUE; + $grade_item->grademax = $forum->scale; + $grade_item->grademin = 0; + + } else if ($forum->scale < 0) { + $grade_item->gradetype = GRADE_TYPE_SCALE; + $grade_item->scaleid = -$forum->scale; } - return $return; + + $grade_item->update(); } +/** + * Create grade item for given forum + * + * @param object $forum object with extra cmidnumber + * @return object grade_item + */ +function forum_grade_item_create($forum) { + $params = array('courseid' =>$forum->course, + 'itemtype' =>'mod', + 'itemmodule' =>'forum', + 'iteminstance'=>$forum->id, + 'itemname' =>$forum->name, + 'idnumber' =>$forum->cmidnumber); + + if (!$forum->assessed) { + //how to indicate no grading? + $params['gradetype'] = GRADE_TYPE_TEXT; + + } else if ($forum->scale > 0) { + $params['gradetype'] = GRADE_TYPE_VALUE; + $params['grademax'] = $forum->scale; + $params['grademin'] = 0; + + } else if ($forum->scale < 0) { + $params['gradetype'] = GRADE_TYPE_SCALE; + $params['scaleid'] = -$forum->scale; + } + + $itemid = grade_create_item($params); + return $itemid; +} + +/** + * Delete grade item for given forum + * + * @param object $forum object + * @return object grade_item + */ +function forum_grade_item_delete($forum) { + if ($grade_items = grade_get_items($forum->course, 'mod', 'forum', $forum->id)) { + foreach($grade_items as $grade_item) { + $grade_item->delete(); + } + } +} + + /** * Returns the users with data in one forum * (users with records in forum_subscriptions, forum_posts and forum_ratings, students) @@ -1652,24 +1771,6 @@ function forum_get_firstpost_from_discussion($discussionid) { AND d.firstpost = p.id "); } - -/** - * Get all user grades for a forum - */ -function forum_get_user_grades($forumid) { - global $CFG; - - return get_records_sql("SELECT r.id, p.userid, r.rating - FROM {$CFG->prefix}forum_discussions d, - {$CFG->prefix}forum_posts p, - {$CFG->prefix}forum_ratings r - WHERE d.forum = '$forumid' - AND p.discussion = d.id - AND r.post = p.id - ORDER by p.userid "); -} - - /** * Returns an array of counts of replies to each discussion (optionally in one forum or course and/or user) */ @@ -1730,7 +1831,7 @@ function forum_count_unrated_posts($discussionid, $userid) { * Get all discussions in a forum */ function forum_get_discussions($forum="0", $forumsort="d.timemodified DESC", - $user=0, $fullpost=true, $visiblegroups=-1, $limit=0, $userlastmodified=false) { + $user=0, $fullpost=true, $currentgroup=-1, $limit=0, $userlastmodified=false) { global $CFG, $USER; $timelimit = ''; @@ -1764,10 +1865,14 @@ function forum_get_discussions($forum="0", $forumsort="d.timemodified DESC", $limitnum = $limit; } - if ($visiblegroups == -1) { + if ($currentgroup == -1) { + $currentgroup = get_current_group($cm->course); + } + + if ($currentgroup) { + $groupselect = " AND (d.groupid = '$currentgroup' OR d.groupid = -1) "; + } else { $groupselect = ""; - } else { - $groupselect = " AND (d.groupid = '$visiblegroups' OR d.groupid = '-1') "; } if (empty($forumsort)) { @@ -3211,7 +3316,7 @@ function forum_user_has_posted($forumid, $did, $userid) { /** * TODO document */ -function forum_user_can_post_discussion($forum, $currentgroup=false, $groupmode=false, $cm=NULL, $context=NULL) { +function forum_user_can_post_discussion($forum, $currentgroup=-1, $groupmode=-1, $cm=NULL, $context=NULL) { // $forum is an object global $USER, $SESSION; @@ -3224,6 +3329,17 @@ function forum_user_can_post_discussion($forum, $currentgroup=false, $groupmode= $context = get_context_instance(CONTEXT_MODULE, $cm->id); } + if ($currentgroup == -1) { + $currentgroup = get_current_group($cm->course); + } + + if ($groupmode == -1) { + if (!$course = get_record('course', 'id', $cm->course)) { + error('Can not find course'); + } + $groupmode = groupmode($course, $cm); + } + if ($forum->type == 'news') { $capname = 'mod/forum:addnews'; } else { @@ -3235,17 +3351,23 @@ function forum_user_can_post_discussion($forum, $currentgroup=false, $groupmode= } if ($forum->type == 'eachuser') { - return (!forum_user_has_posted_discussion($forum->id, $USER->id)); - } else if ($currentgroup) { - return (has_capability('moodle/site:accessallgroups', $context) - or ismember($currentgroup)); + if (forum_user_has_posted_discussion($forum->id, $USER->id)) { + return false; + } + } + + if (!$groupmode or has_capability('moodle/site:accessallgroups', $context)) { + return true; + } + + if ($currentgroup) { + return ismember($currentgroup); } else { //else it might be group 0 in visible mode if ($groupmode == VISIBLEGROUPS){ - return (ismember($currentgroup)); - } - else { return true; + } else { + return false; } } } @@ -3435,21 +3557,8 @@ function forum_print_latest_discussions($course, $forum, $maxdiscussions=5, $dis // Decide if current user is allowed to see ALL the current discussions or not // First check the group stuff - - if ($groupmode == -1) { // We need to reconstruct groupmode because none was given - $groupmode = groupmode($course, $cm); // Works even if $cm is not valid - } - - if ($currentgroup == -1) { // We need to reconstruct currentgroup because none was given - $currentgroup = get_current_group($course->id); - } - - if (!$currentgroup and - ($groupmode != SEPARATEGROUPS or has_capability('moodle/site:accessallgroups', $context)) ) { - $visiblegroups = -1; - } else { - $visiblegroups = $currentgroup; - } + $groupmode = groupmode($course, $cm); + $currentgroup = get_and_set_current_group($course, $groupmode); // If the user can post discussions, then this is a good place to put the // button for it. We do not show the button if we are showing site news @@ -3480,7 +3589,7 @@ function forum_print_latest_discussions($course, $forum, $maxdiscussions=5, $dis $getuserlastmodified = ($displayformat == 'header'); - if (! $discussions = forum_get_discussions($forum->id, $sort, 0, $fullpost, $visiblegroups,0,$getuserlastmodified) ) { + if (! $discussions = forum_get_discussions($forum->id, $sort, 0, $fullpost, $currentgroup,0,$getuserlastmodified) ) { echo '
'; if ($forum->type == 'news') { echo '('.get_string('nonews', 'forum').')'; @@ -3676,7 +3785,6 @@ function forum_print_discussion($course, $forum, $discussion, $post, $mode, $can if ($ratings->allow) { echo '
'; echo '
'; - echo ''; echo ''; $ratingsformused = true; } diff --git a/mod/forum/mod_form.php b/mod/forum/mod_form.php index f68029b62c..20d383f81f 100644 --- a/mod/forum/mod_form.php +++ b/mod/forum/mod_form.php @@ -152,10 +152,11 @@ class mod_forum_mod_form extends moodleform_mod { } function data_preprocessing($default_values){ - if (isset($default_values['assessed'])){ - $default_values['ratingtime']=($default_values['assessed'] - && $default_values['assesstimestart'] - && $default_values['assesstimefinish'] )?1:0; + if (empty($default_values['assessed'])){ + $default_values['ratingtime'] = 0; + } else { + $default_values['ratingtime']= + ($default_values['assesstimestart'] && $default_values['assesstimefinish']) ? 1 : 0; } } diff --git a/mod/forum/rate.php b/mod/forum/rate.php index 3d5207b35d..4d0b9ccb8e 100644 --- a/mod/forum/rate.php +++ b/mod/forum/rate.php @@ -3,81 +3,97 @@ // Collect ratings, store them, then return to where we came from - require_once("../../config.php"); - require_once("lib.php"); - - - $id = required_param('id',PARAM_INT); // The course these ratings are part of - $forumid = required_param('forumid',PARAM_INT); // The forum the rated posts are from - - if (! $cm = get_coursemodule_from_instance('forum', $forumid, $id)) { - error('Course Module ID was incorrect'); - } - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - if (!has_capability('mod/forum:rate', $context)) { - error('You do not have the permission to rate this post'); + require_once('../../config.php'); + require_once('lib.php'); + + $forumid = required_param('forumid', PARAM_INT); // The forum the rated posts are from + + if (!$forum = get_record('forum', 'id', $forumid)) { + error("Course ID was incorrect"); } - - - if (! $course = get_record("course", "id", $id)) { + + if (!$course = get_record('course', 'id', $forum->course)) { error("Course ID was incorrect"); } - require_login($course->id); + if (!$cm = get_coursemodule_from_instance('forum', $forum->id)) { + error("Course Module ID was incorrect"); + } - $returntoview = false; + require_login($course, false, $cm); - if (!$data = data_submitted("$CFG->wwwroot/mod/forum/discuss.php")) { // form submitted - if ($data = data_submitted("$CFG->wwwroot/mod/forum/view.php")) { // Single forums are special case - $returntoview = true; - } + if (isguestuser()) { + error("Guests are not allowed to rate entries."); + } + + if (!$forum->assessed) { + error("Rating of items not allowed!"); } - if ($data) { + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + require_capability('mod/forum:rate', $context); + + $grade_item = forum_grade_item_get($forum); - $lastpostid = 0; + if ($data = data_submitted()) { + + $discussionid = false; foreach ((array)$data as $postid => $rating) { - if ($postid == "id") { + if (!is_numeric($postid)) { continue; } - $postid = (int)$postid; - $lastpostid = $postid; + // following query validates the submitted postid too + $sql = "SELECT fp.* + FROM {$CFG->prefix}forum_posts fp, {$CFG->prefix}forum_discussions fd + WHERE fp.id = '$postid' AND fp.discussion = fd.id AND fd.forum = $forum->id"; + + if (!$post = get_record_sql($sql)) { + error("Incorrect postid - $postid"); + } + + $discussionid = $post->discussion; + + if ($forum->assesstimestart and $forum->assesstimefinish) { + if ($post->created < $forum->assesstimestart or $post->created > $forum->assesstimefinish) { + // we can not rate this, ignore it - this should not happen anyway unless teacher changes setting + continue; + } + } if ($rating == FORUM_UNSET_POST_RATING) { delete_records('forum_ratings', 'post', $postid, 'userid', $USER->id); + forum_update_grades($grade_item, $post->userid); - } else if ($oldrating = get_record("forum_ratings", "userid", $USER->id, "post", $postid)) { + } else if ($oldrating = get_record('forum_ratings', 'userid', $USER->id, 'post', $post->id)) { if ($rating != $oldrating->rating) { $oldrating->rating = $rating; - $oldrating->time = time(); - if (! update_record("forum_ratings", $oldrating)) { - error("Could not update an old rating ($postid = $rating)"); + $oldrating->time = time(); + if (! update_record('forum_ratings', $oldrating)) { + error("Could not update an old rating ($post->id = $rating)"); } + forum_update_grades($grade_item, $post->userid); } + } else { - unset($newrating); + $newrating = new object(); $newrating->userid = $USER->id; - $newrating->time = time(); - $newrating->post = $postid; + $newrating->time = time(); + $newrating->post = $post->id; $newrating->rating = $rating; - if (! insert_record("forum_ratings", $newrating)) { + if (! insert_record('forum_ratings', $newrating)) { error("Could not insert a new rating ($postid = $rating)"); } + forum_update_grades($grade_item, $post->userid); } } - if ($post = get_record('forum_posts', 'id', $lastpostid)) { // To find discussion we're in - if ($returntoview and ($discussion = get_record('forum_discussions', 'id', $post->discussion))) { - redirect("$CFG->wwwroot/mod/forum/view.php?f=$discussion->forum", get_string("ratingssaved", "forum")); - } else { - redirect("$CFG->wwwroot/mod/forum/discuss.php?d=$post->discussion", get_string("ratingssaved", "forum")); - } + + if ($forum->type == 'single' or !$discussionid) { + redirect("$CFG->wwwroot/mod/forum/view.php?id=$cm->id", get_string('ratingssaved', 'forum')); } else { - redirect($_SERVER["HTTP_REFERER"], get_string("ratingssaved", "forum")); + redirect("$CFG->wwwroot/mod/forum/discuss.php?d=$discussionid", get_string('ratingssaved', 'forum')); } } else { diff --git a/mod/forum/version.php b/mod/forum/version.php index a5ef2a685f..d049494ac6 100644 --- a/mod/forum/version.php +++ b/mod/forum/version.php @@ -5,8 +5,8 @@ // This fragment is called by /admin/index.php //////////////////////////////////////////////////////////////////////////////// -$module->version = 2007020202; -$module->requires = 2007020201; // Requires this Moodle version +$module->version = 2007060300; +$module->requires = 2007060100; // Requires this Moodle version $module->cron = 60; ?> -- 2.39.5