### Eclipse Workspace Patch 1.0
#P 19stable
Index: mod/forum/post.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/post.php,v
retrieving revision 1.154.2.18
diff -u -r1.154.2.18 post.php
--- mod/forum/post.php	13 Oct 2009 20:53:57 -0000	1.154.2.18
+++ mod/forum/post.php	1 Jan 2010 03:53:14 -0000
@@ -7,6 +7,7 @@
 
     $reply   = optional_param('reply', 0, PARAM_INT);
     $forum   = optional_param('forum', 0, PARAM_INT);
+    $approve    = optional_param('approve', 0, PARAM_INT);
     $edit    = optional_param('edit', 0, PARAM_INT);
     $delete  = optional_param('delete', 0, PARAM_INT);
     $prune   = optional_param('prune', 0, PARAM_INT);
@@ -16,7 +17,7 @@
 
 
     //these page_params will be passed as hidden variables later in the form.
-    $page_params = array('reply'=>$reply, 'forum'=>$forum, 'edit'=>$edit);
+    $page_params = array('reply'=>$reply, 'forum'=>$forum, 'edit'=>$edit, 'approve'=>$approve);
 
     $sitecontext = get_context_instance(CONTEXT_SYSTEM);
 
@@ -78,7 +79,11 @@
             error("Incorrect course module");
         }
 
+        if (!$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id)) {
+            error("Unable to get course module context");
+        }
         $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
+        $canapprove = forum_post_approved($forum);
 
         if (! forum_user_can_post_discussion($forum, $groupid, -1, $cm)) {
             if (has_capability('moodle/legacy:guest', $coursecontext, NULL, false)) {  // User is a guest here!
@@ -137,12 +142,15 @@
         if (! $cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) {
             error("Incorrect cm");
         }
+        if (!$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id)) {
+            error("Unable to get course module context");
+        }
+        $canapprove = forum_post_approved($forum);
 
         // call course_setup to use forced language, MDL-6926 
         course_setup($course->id);
 
         $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
-        $modcontext    = get_context_instance(CONTEXT_MODULE, $cm->id);
 
         if (! forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext)) {
             if (has_capability('moodle/legacy:guest', $coursecontext, NULL, false)) {  // User is a guest here!
@@ -427,7 +435,32 @@
         }
         print_footer($course);
         die;
-    } else {
+    } 
+    else if (!empty($approve)) {  // User is approving a post - this is not yet working
+
+        if (! $post = forum_get_post_full($approve)) {
+            error("Post ID was incorrect");
+        }
+        if (! $discussion = get_record("forum_discussions", "id", $post->discussion)) {
+            error("This post is not part of a discussion! ($edit)");
+        }
+        if (! $forum = get_record("forum", "id", $discussion->forum)) {
+            error("The forum number was incorrect ($discussion->forum)");
+        }
+        if (! $course = get_record("course", "id", $discussion->course)) {
+            error("The course number was incorrect ($discussion->course)");
+        }
+        if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) {
+            error('Could not get the course module for the forum instance.');
+        } else {
+            $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+        }
+        if (has_capability('mod/forum:approvepost', $modcontext)) {
+            $post->approve = 1;
+        }
+        // update_record('forum_posts',$post);        
+    }    
+    else {
         error("No operation specified");
 
     }
@@ -532,6 +565,7 @@
             $message = '';
             $addpost=$fromform;
             $addpost->forum=$forum->id;
+            $addpost->approved = forum_post_approved($forum);
             if ($fromform->id = forum_add_new_post($addpost, $message)) {
 
                 $timemessage = 2;
@@ -723,7 +757,7 @@
         }
     }
 
-    if ($USER->id != $post->userid) {   // Not the original author, so add a message to the end
+    if (($USER->id != $post->userid) and (!$approve)){   // Not the original author, so add a message to the end
         $data->date = userdate($post->modified);
         if ($post->format == FORMAT_HTML) {
             $data->name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$USER->id.'&course='.$post->course.'">'.
Index: mod/forum/rate_ajax.js
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/rate_ajax.js,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 rate_ajax.js
--- mod/forum/rate_ajax.js	6 Apr 2009 03:44:13 -0000	1.1.2.5
+++ mod/forum/rate_ajax.js	1 Jan 2010 03:53:14 -0000
@@ -83,7 +83,14 @@
     };
 
     /** Here goes the request **/
-    var url = rate_ajax_config.wwwroot +  '/mod/forum/rate_ajax.php?postid=' + menu.name + '&rate=' + menu.value + '&sesskey=' + rate_ajax_config.sesskey;
+    var ratinginfo = new Array();
+    var ratingname = menu.name;
+    ratinginfo = ratingname.split('_');
+    var ratingtype = ratinginfo[1];
+    var ratingid = ratinginfo[0];
+    if (menu.namestatus != 'Ok') {
+    }
+    var url = rate_ajax_config.wwwroot +  '/mod/forum/rate_ajax.php?postid=' + ratingid + '&rate=' + menu.value + '&ratetype=' + ratingtype + '&sesskey=' + rate_ajax_config.sesskey;
     YAHOO.util.Connect.asyncRequest('GET', url, callback, null);
 
     /** Start animation **/
Index: mod/forum/rate.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/rate.php,v
retrieving revision 1.24.2.5
diff -u -r1.24.2.5 rate.php
--- mod/forum/rate.php	21 Nov 2009 15:33:34 -0000	1.24.2.5
+++ mod/forum/rate.php	1 Jan 2010 03:53:14 -0000
@@ -29,7 +29,7 @@
         error("Guests are not allowed to rate entries.");
     }
 
-    if (!$forum->assessed) {
+    if ((!$forum->assessed) and (!$forum->approve)) {
         error("Rating of items not allowed!");
     }
 
@@ -44,6 +44,20 @@
         $scale_values = make_grades_menu($forum->scale);
 
         foreach ((array)$data as $postid => $rating) {
+            $ratingpos = strpos($postid,'_rating');
+            $approvedpos = strpos($postid,'_approved');
+            $ratingval=-1;
+            $approvedval=-1;
+            
+            if ($ratingpos) {
+                $postid = substr($postid,0,$ratingpos);
+                $ratingval = $rating;
+            } 
+            if ($approvedpos) {
+                $postid = substr($postid,0,$approvedpos);
+                $approvedval = $rating;
+            }
+            
             if (!is_numeric($postid)) {
                 continue;
             }
@@ -67,38 +81,52 @@
             }
 
         /// Check rate is valid for for that forum scale values
-            if (!array_key_exists($rating, $scale_values) && $rating != FORUM_UNSET_POST_RATING) {
-                print_error('invalidrate', 'forum', '', $rating);
-            }
+            if ($ratingpos) {
+                if (!array_key_exists($rating, $scale_values) && $rating != FORUM_UNSET_POST_RATING) {
+                    print_error('invalidrate', 'forum', '', $rating);
+                }
+            
+                if ($rating == FORUM_UNSET_POST_RATING) {
+                    delete_records('forum_ratings', 'post', $postid, 'userid', $USER->id);
+                    forum_update_grades($forum, $post->userid);
 
-            if ($rating == FORUM_UNSET_POST_RATING) {
-                delete_records('forum_ratings', 'post', $postid, 'userid', $USER->id);
-                forum_update_grades($forum, $post->userid);
-
-            } 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 ($post->id = $rating)");
+                } 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 ($post->id = $rating)");
+                        }
+                        forum_update_grades($forum, $post->userid);
                     }
-                    forum_update_grades($forum, $post->userid);
-                }
 
-            } else {
-                $newrating = new object();
-                $newrating->userid = $USER->id;
-                $newrating->time   = time();
-                $newrating->post   = $post->id;
-                $newrating->rating = $rating;
+                } else {
+                    $newrating = new object();
+                    $newrating->userid = $USER->id;
+                    $newrating->time   = time();
+                    $newrating->post   = $post->id;
+                    $newrating->rating = $rating;
 
-                if (! insert_record('forum_ratings', $newrating)) {
-                    error("Could not insert a new rating ($postid = $rating)");
+                    if (! insert_record('forum_ratings', $newrating)) {
+                        error("Could not insert a new rating ($postid = $rating)");
+                    }
+                    forum_update_grades($forum, $post->userid);
+                }
+            }
+            
+            if ($approvedpos) {
+            
+                if ($post->approved != $rating) {
+                    $post->approved = $rating;
+                    $strapproved = ($post->approved == 1) ? get_string('approve','forum') : get_string('unapprove','forum');
+                    $discussionurl = "discuss.php?d=$post->discussion#p$post->id&parent=$post->id"; 
+                    add_to_log($course->id, "forum", "update post approval", "$discussionurl", $strapproved, $cm->id); 
+                    update_record('forum_posts',$post);
                 }
-                forum_update_grades($forum, $post->userid);
             }
         }
-
+        
+       
         if ($forum->type == 'single' or !$discussionid) {
             redirect("$CFG->wwwroot/mod/forum/view.php?id=$cm->id", get_string('ratingssaved', 'forum'));
         } else {
Index: mod/forum/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/lib.php,v
retrieving revision 1.609.2.100
diff -u -r1.609.2.100 lib.php
--- mod/forum/lib.php	23 Nov 2009 05:09:04 -0000	1.609.2.100
+++ mod/forum/lib.php	1 Jan 2010 03:53:14 -0000
@@ -26,6 +26,41 @@
 define ('FORUM_AGGREGATE_MIN', 4);
 define ('FORUM_AGGREGATE_SUM', 5);
 
+/// check for installation of patch
+global $CFG;
+$cfg_forum = get_config('patch/forum');
+
+
+    if (!isset($cfg_forum->version) or (!$cfg_forum->version=2009032200)) { // the patch has not been installed, modify tables and create capability
+        $result = true;
+        require_once($CFG->libdir.'/xmldb/classes/XMLDBConstants.php');
+        require_once($CFG->libdir.'/xmldb/classes/XMLDBObject.class.php');
+        require_once($CFG->libdir.'/xmldb/classes/XMLDBTable.class.php');
+        require_once($CFG->libdir.'/xmldb/classes/XMLDBField.class.php');
+        require_once($CFG->libdir.'/ddllib.php'); // Install/upgrade related db functions
+        
+        $table  = new XMLDBTable('forum');
+        $field = new XMLDBField('approve');
+        $field->setAttributes(XMLDB_TYPE_INTEGER, 2, TRUE, TRUE, null, null, null, 0, 'blockperiod');
+        
+        $table2  = new XMLDBTable('forum_posts');
+        $field2 = new XMLDBField('approved');
+        $field2->setAttributes(XMLDB_TYPE_INTEGER, 2, TRUE, TRUE, null, null, null, 0,'mailnow');
+        
+        $result = $result && add_field($table, $field);
+        $result = $result && add_field($table2, $field2);
+        $result = $result && update_capabilities('mod/forum');
+        
+        if (!$result) { // if something goes wrong
+            error($result);
+            die;
+        } else {
+            set_config('version',2009032200,'patch/forum');
+            echo 'Forum patch tables successfully installed';
+        }
+    }
+
+
 /// STANDARD FUNCTIONS ///////////////////////////////////////////////////////////
 
 /**
@@ -61,7 +96,7 @@
         $discussion->name     = $forum->name;
         $discussion->intro    = $forum->intro;
         $discussion->assessed = $forum->assessed;
-        $discussion->format   = $forum->type;
+        $discussion->format =  ($forum->approve) ? $discussion->format   = -1 : $discussion->format   = $forum->type;
         $discussion->mailnow  = false;
         $discussion->groupid  = -1;
 
@@ -1887,6 +1922,19 @@
 }
 
 /**
+ * Returns a list of ratings for all posts in discussion
+ * @param object $discussion
+ * @return array of ratings or false
+ */
+function forum_get_all_discussion_approvals($discussion) {
+    global $CFG;
+    return get_records_sql("SELECT p.id, p.userid, p.approved
+                              FROM {$CFG->prefix}forum_posts p
+                             WHERE p.discussion = $discussion->id
+                             ORDER BY p.id ASC");
+}
+
+/**
  * Returns a list of ratings for one specific user for all posts in discussion
  * @global object $CFG
  * @param object $discussions the discussions for which we return all ratings
@@ -1942,6 +1990,7 @@
  * @param int $starttime - posts created after this time
  * @param int $endtime - posts created before this
  * @param int $now - used for timed discussions only
+ * added p.approved to WHERE clause so that unapproved posts will not be mailed out
  */
 function forum_get_unmailed_posts($starttime, $endtime, $now=null) {
     global $CFG;
@@ -1960,6 +2009,7 @@
                                    JOIN {$CFG->prefix}forum_discussions d ON d.id = p.discussion
                              WHERE p.mailed = 0
                                    AND p.created >= $starttime
+                                   AND p.approved = 1
                                    AND (p.created < $endtime OR p.mailnow = 1)
                                    $timedsql
                           ORDER BY p.modified ASC");
@@ -2353,7 +2403,7 @@
         $forumsort = "d.timemodified DESC";
     }
     if (empty($fullpost)) {
-        $postdata = "p.id,p.subject,p.modified,p.discussion,p.userid";
+        $postdata = "p.id,p.subject,p.modified,p.discussion,p.userid,p.approved";
     } else {
         $postdata = "p.*";
     }
@@ -2794,7 +2844,7 @@
 
     global $USER, $CFG;
 
-    static $stredit, $strdelete, $strreply, $strparent, $strprune;
+    static $stredit, $strdelete, $strreply, $strparent, $strprune, $strapprove;
     static $strpruneheading, $displaymode;
     static $strmarkread, $strmarkunread;
 
@@ -2816,6 +2866,7 @@
         $cm->cache->caps['mod/forum:deleteownpost']    = has_capability('mod/forum:deleteownpost', $modcontext);
         $cm->cache->caps['mod/forum:deleteanypost']    = has_capability('mod/forum:deleteanypost', $modcontext);
         $cm->cache->caps['mod/forum:viewanyrating']    = has_capability('mod/forum:viewanyrating', $modcontext);
+        $cm->cache->caps['mod/forum:approvepost']    = has_capability('mod/forum:approvepost', $modcontext);
     }
 
     if (!isset($cm->uservisible)) {
@@ -2856,6 +2907,7 @@
         $stredit         = get_string('edit', 'forum');
         $strdelete       = get_string('delete', 'forum');
         $strreply        = get_string('reply', 'forum');
+        $strapprove    = get_string('approve','forum');
         $strparent       = get_string('parent', 'forum');
         $strpruneheading = get_string('pruneheading', 'forum');
         $strprune        = get_string('prune', 'forum');
@@ -2866,7 +2918,7 @@
     }
 
     $read_style = '';
-    // ignore trackign status if not tracked or tracked param missing
+    // ignore tracking status if not tracked or tracked param missing
     if ($istracked) {
         if (is_null($post_read)) {
             debugging('fetching post_read info');
@@ -3044,6 +3096,7 @@
 // Ratings
 
     $ratingsmenuused = false;
+    $approvalmenuused = false;
     if (!empty($ratings) and isloggedin()) {
         echo '<div class="ratings">';
         $useratings = true;
@@ -3100,6 +3153,22 @@
         echo '</div>';
     }
 
+// Approval
+
+    
+    if (isloggedin()) {
+        echo '<div class="ratings">';
+        $mypost = ($USER->id == $post->userid);
+        $canapprove = $cm->cache->caps['mod/forum:approvepost'];
+        if ($canapprove and !$mypost) {
+                // echo '<span class="forumpostapprovaltext">' .
+                echo     forum_print_approval_menu($post->id, $post->userid, $post->approved);
+               //      '</span>';
+                     $approvalmenuused = true;
+            } 
+            echo '</div>'; 
+        }
+
 // Link to post if required
 
     if ($link) {
@@ -3123,7 +3192,7 @@
         forum_tp_mark_post_read($USER->id, $post, $forum->id);
     }
 
-    return $ratingsmenuused;
+    return ($ratingsmenuused or $approvalmenuused);
 }
 
 
@@ -3162,9 +3231,12 @@
     } else {
         $rowcount = ($rowcount + 1) % 2;
     }
-
-    $post->subject = format_string($post->subject,true);
-
+    $usercansee = forum_user_can_see_post($forum, $discussion, $post, NULL, $cm);
+    if ($post->approved || $usercansee) {
+        $post->subject = format_string($post->subject,true);
+    } else {
+        $post->subject = get_string('forumsubjecthidden','forum');
+    }
     echo "\n\n";
     echo '<tr class="discussion r'.$rowcount.'">';
 
@@ -3181,15 +3253,23 @@
     $postuser->imagealt = $post->imagealt;
     $postuser->picture = $post->picture;
 
-    echo '<td class="picture">';
-    print_user_picture($postuser, $forum->course);
-    echo "</td>\n";
-
-    // User name
-    $fullname = fullname($post, has_capability('moodle/site:viewfullnames', $modcontext));
-    echo '<td class="author">';
-    echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->userid.'&amp;course='.$forum->course.'">'.$fullname.'</a>';
-    echo "</td>\n";
+    if ($post->approved || $usercansee) {
+        echo '<td class="picture">';
+        print_user_picture($postuser, $forum->course);
+        echo "</td>\n";
+        // User name
+        $fullname = fullname($post, has_capability('moodle/site:viewfullnames', $modcontext));
+        echo '<td class="author">';
+        echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->userid.'&amp;course='.$forum->course.'">'.$fullname.'</a>';
+        echo "</td>\n";
+    } else {
+        echo '<td class="picture">';
+        echo "</td>\n";
+        echo '<td class="author">';
+        print_string('forumauthorhidden','forum');
+        echo "</td>\n";
+        
+    }
 
     // Group picture
     if ($group !== -1) {  // Groups are active - group is a group data object or NULL
@@ -3245,10 +3325,14 @@
     $usermodified->id        = $post->usermodified;
     $usermodified->firstname = $post->umfirstname;
     $usermodified->lastname  = $post->umlastname;
+    if ($post->approved || $usercansee) {
     echo '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$post->usermodified.'&amp;course='.$forum->course.'">'.
          fullname($usermodified).'</a><br />';
     echo '<a href="'.$CFG->wwwroot.'/mod/forum/discuss.php?d='.$post->discussion.$parenturl.'">'.
           userdate($usedate, $datestring).'</a>';
+    } else {
+        echo  print_string('forumauthorhidden','forum');
+    }
     echo "</td>\n";
 
     echo "</tr>\n\n";
@@ -3619,6 +3703,22 @@
 }
 
 /**
+ * Print the menu of approval options 
+ * If the post has already been - set that value.
+ */
+function forum_print_approval_menu($postid, $userid, $approved) {
+
+    static $strapprove;
+    if (empty($strapprove)) {
+        $strapprove = get_string('approve', 'forum');
+    }
+    $options[0] = get_string('unapprove','forum');
+    $options[1] = get_string('approve','forum');
+    choose_from_menu($options, $postid.'_approved', $approved, '', '', $approved, false, false, 0, '', false, false, 'forumpostratingmenu');
+}
+
+
+/**
  * Print the menu of ratings as part of a larger form.
  * If the post has already been - set that value.
  * Scale is an array of ratings
@@ -3639,7 +3739,7 @@
         $strrate = get_string("rate", "forum");
     }
     $scale = array(FORUM_UNSET_POST_RATING => $strrate.'...') + $scale;
-    choose_from_menu($scale, $postid, $myrating, '', '', '0', false, false, 0, '', false, false, 'forumpostratingmenu');
+    choose_from_menu($scale, $postid.'_rating', $myrating, '', '', '0', false, false, 0, '', false, false, 'forumpostratingmenu');
 }
 
 /**
@@ -3941,8 +4041,13 @@
     global $USER, $CFG;
 
     $forum = get_record('forum', 'id', $post->forum);
-
+    if (!$cm = get_coursemodule_from_instance("forum", $forum->id, $forum->course)) {
+            error('Could not get the course module for the forum instance.');
+        }
+    $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
     $post->modified = time();
+    $post->approved = forum_post_approved($forum);
 
     $updatediscussion = new object();
     $updatediscussion->id           = $post->discussion;
@@ -4001,7 +4106,10 @@
     $post->course      = $forum->course; // speedup
     $post->format      = $discussion->format;
     $post->mailnow     = $discussion->mailnow;
+    $post_approved = forum_post_approved($forum);
+    $post->approved = $post_approved;
 
+    
     if (! $post->id = insert_record("forum_posts", $post) ) {
         return 0;
     }
@@ -4677,6 +4785,24 @@
             return false;
         }
     }
+    
+    if  ($post->userid<>$user->id) {
+        if (isset($cm->cache->caps['mod/forum:approvepost'])) {
+            if (!$cm->cache->caps['mod/forum:approvepost']) {
+                    if ($post->approved==0) {
+                        return false;
+                    }
+                }
+            } else {
+            $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+            if (!has_capability('mod/forum:approvepost', $modcontext, $user->id)) { 
+                if ($post->approved==0) {
+                    return false;
+                }
+            }
+        }
+    }
+
 
     if (isset($cm->uservisible)) {
         if (!$cm->uservisible) {
@@ -5021,39 +5147,49 @@
     $ratings = NULL;
     $ratingsmenuused = false;
     $ratingsformused = false;
-    if ($forum->assessed and isloggedin()) {
-        if ($scale = make_grades_menu($forum->scale)) {
-            $ratings =new object();
-            $ratings->scale = $scale;
-            $ratings->assesstimestart = $forum->assesstimestart;
-            $ratings->assesstimefinish = $forum->assesstimefinish;
-            $ratings->allow = $canrate;
-
-            if ($ratings->allow) {
-                echo '<form id="form" method="post" action="rate.php">';
-                echo '<div class="ratingform">';
-                echo '<input type="hidden" name="forumid" value="'.$forum->id.'" />';
-                echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-                $ratingsformused = true;
-            }
-
-            // preload all ratings - one query only and minimal memory
-            $cm->cache->ratings = array();
-            $cm->cache->myratings = array();
-            if ($postratings = forum_get_all_discussion_ratings($discussion)) {
-                foreach ($postratings as $pr) {
-                    if (!isset($cm->cache->ratings[$pr->postid])) {
-                        $cm->cache->ratings[$pr->postid] = array();
+    if (($forum->assessed or $forum->approve) and isloggedin()) {
+        if ($forum->assessed) {
+            if ($scale = make_grades_menu($forum->scale)) {
+                $ratings =new object();
+                $ratings->scale = $scale;
+                $ratings->assesstimestart = $forum->assesstimestart;
+                $ratings->assesstimefinish = $forum->assesstimefinish;
+                $ratings->allow = $canrate;
+
+                // preload all ratings - one query only and minimal memory
+                $cm->cache->ratings = array();
+                $cm->cache->myratings = array();
+                if ($postratings = forum_get_all_discussion_ratings($discussion)) {
+                    foreach ($postratings as $pr) {
+                        if (!isset($cm->cache->ratings[$pr->postid])) {
+                            $cm->cache->ratings[$pr->postid] = array();
+                        }
+                        $cm->cache->ratings[$pr->postid][$pr->id] = $pr->rating;
+                        if ($pr->userid == $USER->id) {
+                            $cm->cache->myratings[$pr->postid] = $pr->rating;
+                        }
                     }
-                    $cm->cache->ratings[$pr->postid][$pr->id] = $pr->rating;
-                    if ($pr->userid == $USER->id) {
-                        $cm->cache->myratings[$pr->postid] = $pr->rating;
+                    unset($postratings);
+                }
+
+                // preload all approvals - not sure this really gets used but for starters I'll include it -ab
+                if ($postapprovals = forum_get_all_discussion_approvals($discussion)) { //get all approvals for discussion
+                    foreach ($postapprovals as $pa) {
+                        if (!isset($cm->cache->approved[$pa->id])) {
+                            $cm->cache->approved[$pa->id] = array();
+                        }
+                        $cm->cache->approved[$pa->id] = $pa->approved;
                     }
+                    unset($postapprovals);
                 }
-                unset($postratings);
             }
         }
-
+        if ($forum->approve or $ratings->allow ) {
+            echo '<form id="form" method="post" action="rate.php">';
+            echo '<div class="ratingform">';
+            echo '<input type="hidden" name="forumid" value="'.$forum->id.'" />';
+            $ratingsformused = true;
+        }
     }
 
     $post->forum = $forum->id;   // Add the forum id to the post object, later used by forum_print_post
@@ -5090,10 +5226,13 @@
             break;
     }
 
-    if ($ratingsformused) {
-        if ($ratingsmenuused) {
+            
+    if (($ratingsformused) or ($forum->approve)) { //if ratings and approve
+        if ($ratingsmenuused)  {
             echo '<div class="ratingsubmit">';
             echo '<input type="submit" id="forumpostratingsubmit" value="'.get_string('sendinratings', 'forum').'" />';
+            
+            
             if (ajaxenabled() && !empty($CFG->forum_ajaxrating)) { /// AJAX enabled, standard submission form
                 $rate_ajax_config_settings = array("pixpath"=>$CFG->pixpath, "wwwroot"=>$CFG->wwwroot, "sesskey"=>sesskey());
                 echo "<script type=\"text/javascript\">//<![CDATA[\n".
@@ -6392,7 +6531,7 @@
  *
  */
 function forum_get_post_actions() {
-    return array('add discussion','add post','delete discussion','delete post','move discussion','prune post','update post');
+    return array('add discussion','add post','delete discussion','delete post','move discussion','prune post','update post','approve post');
 }
 
 /**
@@ -6931,4 +7070,29 @@
     return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/site:trustcontent');
 }
 
+/**
+ * Returns true if the post is approved by default (i.e. forum approval not required or the user has the capability to approve posts)
+ * @param $forum        - a forum object with the same attributes as a record from the forum database table
+ * @return boolean      - is the forum post approved
+ */
+function forum_post_approved($forum) {
+
+        if (! $cm = get_coursemodule_from_instance("forum", $forum->id, $forum->course)) {
+            error("Unable to get course module instance");
+        }
+        if (!$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id)) {
+            error("Unable to get course module context");
+        }
+        $canapprove = has_capability('mod/forum:approvepost',$modcontext);
+
+    if ($forum->approve) { // if the forum requires approval
+                return $canapprove;
+            } else { // if the forum does not require approval then the post is automatically approved
+                return 1;
+            }
+}
+
+function forum_approve_post($post) {
+    
+}
 ?>
Index: mod/forum/rate_ajax.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/rate_ajax.php,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 rate_ajax.php
--- mod/forum/rate_ajax.php	3 Jun 2009 19:59:16 -0000	1.1.2.3
+++ mod/forum/rate_ajax.php	1 Jan 2010 03:53:14 -0000
@@ -59,6 +59,7 @@
 /// Check required params
     $postid = required_param('postid', PARAM_INT); // The postid to rate
     $rate   = required_param('rate', PARAM_INT); // The rate to apply
+    $ratetype = required_param('ratetype', PARAM_ALPHA); //either rating or approved
 
 /// Check postid is valid
     if (!$post = get_record_sql("SELECT p.*,
@@ -87,7 +88,7 @@
     }
 
 /// Check forum can be rated
-    if (!$forum->assessed) {
+    if (!$forum->assessed && (!$forum->approve)) {
         print_error('norate', 'forum');
     }
 
@@ -95,63 +96,71 @@
     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     require_capability('mod/forum:rate', $context);
 
-/// Check timed ratings
-    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
-            print_error('norate', 'forum');
-        }
-    }
-
-/// Calculate scale values
-    $scale_values = make_grades_menu($forum->scale);
-
-/// Check rate is valid for for that forum scale values
-    if (!array_key_exists($rate, $scale_values) && $rate != FORUM_UNSET_POST_RATING) {
-        print_error('invalidrate', 'forum');
-    }
-
-/// Everything ready, process rate
-
-/// Deleting rate
-    if ($rate == FORUM_UNSET_POST_RATING) {
-        delete_records('forum_ratings', 'post', $postid, 'userid', $USER->id);
-
-/// Updating rate
-    } else if ($oldrating = get_record('forum_ratings', 'userid', $USER->id, 'post', $post->id)) {
-        if ($rate != $oldrating->rating) {
-            $oldrating->rating = $rate;
-            $oldrating->time   = time();
-            if (!update_record('forum_ratings', $oldrating)) {
-                error("Could not update an old rating ($post->id = $rate)");
+    if ($ratetype == 'rating') {
+    /// Check timed ratings
+        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
+                print_error('norate', 'forum');
             }
         }
+    /// Calculate scale values
+        $scale_values = make_grades_menu($forum->scale);
 
-/// Inserting rate
-    } else {
-        $newrating = new object();
-        $newrating->userid = $USER->id;
-        $newrating->time   = time();
-        $newrating->post   = $post->id;
-        $newrating->rating = $rate;
-
-        if (!insert_record('forum_ratings', $newrating)) {
-            print_error('cannotinsertrate', 'error', '', (object)array('id'=>$postid, 'rating'=>$rate));
+    /// Check rate is valid for for that forum scale values
+        if (!array_key_exists($rate, $scale_values) && $rate != FORUM_UNSET_POST_RATING) {
+            print_error('invalidrate', 'forum');
+        
+    /// Everything ready, process rate
+    /// Deleting rate
+        if ($rate == FORUM_UNSET_POST_RATING) {
+            delete_records('forum_ratings', 'post', $postid, 'userid', $USER->id);
+
+    /// Updating rate
+        } else if ($oldrating = get_record('forum_ratings', 'userid', $USER->id, 'post', $post->id) and ($ratetype =='rating')) {
+            if ($rate != $oldrating->rating) {
+                $oldrating->rating = $rate;
+                $oldrating->time   = time();
+                if (!update_record('forum_ratings', $oldrating)) {
+                    print_error('cannotupdaterate', 'error', '', (object)array('id'=>$post->id, 'rating'=>$rate));
+                }
+            }
+ 
+    /// Inserting rate
+        } else {
+            if ($ratetype=='rating') {
+                $newrating = new object();
+                $newrating->userid = $USER->id;
+                $newrating->time   = time();
+                $newrating->post   = $post->id;
+                $newrating->rating = $rate;
+
+                if (!insert_record('forum_ratings', $newrating)) {
+                    print_error('cannotinsertrate', 'error', '', (object)array('id'=>$postid, 'rating'=>$rate));
+                }
+            }
         }
-    }
-
-/// Update grades
     forum_update_grades($forum, $post->userid);
-
+    }
 /// Check user can see any rate
     $canviewanyrating = has_capability('mod/forum:viewanyrating', $context);
 
 /// Decide if rates info is displayed
     $rateinfo = '';
-    if ($canviewanyrating) {
-        $rateinfo = forum_print_ratings($postid, $scale_values, $forum->assessed, true, NULL, true);
+    if ($canviewanyrating && ($ratetype == 'rating')) {
+            $rateinfo = forum_print_ratings($postid, $scale_values, $forum->assessed, true, NULL, true);
     }
 
+    if (($post->approved != $rate) && ($ratetype =='approved')) { //if approval status has changed
+        $post->approved = $rate;
+        $strapproved = ($post->approved == 1) ? get_string('approve','forum') : get_string('unapprove','forum');
+        $discussionurl = "discuss.php?d=$post->discussion#p$post->id&parent=$post->id"; 
+        add_to_log($course->id, "forum", "update post approval", "$discussionurl", $strapproved, $cm->id); 
+        if (!update_record('forum_posts',$post)) {
+            print_error('cannotupdateapproval', 'error', '', (object)array('id'=>$post->id, 'rating'=>$rate));
+        }
+    }
+    
 /// Calculate response
     $response['status']  = 'Ok';
     $response['message'] = $rateinfo;
Index: mod/forum/mod_form.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/mod_form.php,v
retrieving revision 1.23.2.6
diff -u -r1.23.2.6 mod_form.php
--- mod/forum/mod_form.php	26 Jul 2008 15:17:05 -0000	1.23.2.6
+++ mod/forum/mod_form.php	1 Jan 2010 03:53:14 -0000
@@ -41,6 +41,14 @@
         $mform->setHelpButton('forcesubscribe', array('subscription2', get_string('forcesubscribeq', 'forum'), 'forum'));
 
         $options = array();
+        $options[0] = get_string('no');
+        $options[1] = get_string('yes');
+        $mform->addElement('select', 'approve', get_string('requireapprovalq', 'forum'), $options);
+        $mform->setHelpButton('approve', array('approve', get_string('requireapprovalq', 'forum'), 'forum'));
+        $mform->setDefault('approve',0);
+        
+
+        $options = array();
         $options[FORUM_TRACKING_OPTIONAL] = get_string('trackingoptional', 'forum');
         $options[FORUM_TRACKING_OFF] = get_string('trackingoff', 'forum');
         $options[FORUM_TRACKING_ON] = get_string('trackingon', 'forum');
Index: mod/forum/db/access.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/db/access.php,v
retrieving revision 1.15.2.1
diff -u -r1.15.2.1 access.php
--- mod/forum/db/access.php	23 Jul 2008 16:09:14 -0000	1.15.2.1
+++ mod/forum/db/access.php	1 Jan 2010 03:53:14 -0000
@@ -182,6 +182,17 @@
         )
     ),
 
+    'mod/forum:approvepost' => array(
+
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_MODULE,
+        'legacy' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    ),
+    
     'mod/forum:splitdiscussions' => array(
 
         'captype' => 'read',
Index: mod/forum/patch_forum_approveposts.txt
===================================================================
RCS file: mod/forum/patch_forum_approveposts.txt
diff -N mod/forum/patch_forum_approveposts.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mod/forum/patch_forum_approveposts.txt	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+This file serves as a README.txt file for the Forum Approve Posts patch contributed by Anthony Borrow (anthony@moodle.org).
+
+DESCRIPTION - The Forum Approve Posts patch is designed to enable the ability for a teacher or other user with the mod/forum:approvepost capability to approve posts before they are visible to other users or emailed to subscribers. 
+
+USAGE 
+
+1) When creating the forum, the teacher indicates that the forum will require approval.
+2) The teacher then reviews the forums and clicks on the Approve link to approve individual posts.
+
+INSTALLATION
+
+1) Apply the patch file to your Moodle installation (see http://docs.moodle.org/en/Development:How_to_apply_a_patch)
+2) Login as the system adminstrator and go to any page that requires the /mod/forum/lib.php file
+3) The modified /mod/forum/lib.php file will check to see if the patch has been installed and if not it will begin to add the approve field to the forum table and the approved field to the forum_post table and create the mod/forum:approvepost capability. After installation, a message indicating that the patch has been successfully installed will be displayed.
+
+TODO
+
+This patch is currently being developed in response to http://tracker.moodle.org/browse/CONTRIB-1085. Please create new issues in the tracker for any suggestions, bug reports, improvements, etc. 
+
+KNOWN ISSUES
+
+For a listing of current issues with the patch please see: http://tracker.moodle.org/browse/CONTRIB/component/10440

