### 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.17
diff -u -r1.154.2.17 post.php
--- mod/forum/post.php	14 Jan 2009 04:55:10 -0000	1.154.2.17
+++ mod/forum/post.php	1 Apr 2009 07:03:13 -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);
 
@@ -77,8 +78,11 @@
         if (! $cm = get_coursemodule_from_instance("forum", $forum->id, $course->id)) {
             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 +141,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 +434,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 +564,8 @@
             $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/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/mod/forum/lib.php,v
retrieving revision 1.609.2.90
diff -u -r1.609.2.90 lib.php
--- mod/forum/lib.php	20 Mar 2009 13:38:27 -0000	1.609.2.90
+++ mod/forum/lib.php	1 Apr 2009 07:03:13 -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;
 
@@ -2764,7 +2799,7 @@
 
     global $USER, $CFG;
 
-    static $stredit, $strdelete, $strreply, $strparent, $strprune;
+    static $stredit, $strdelete, $strreply, $strparent, $strprune, $strapprove;
     static $strpruneheading, $displaymode;
     static $strmarkread, $strmarkunread;
 
@@ -2786,6 +2821,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)) {
@@ -2826,6 +2862,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');
@@ -3005,6 +3042,10 @@
     if ($reply) {
         $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?reply='.$post->id.'">'.$strreply.'</a>';
     }
+    
+    if (($post->approved==0) and ($cm->cache->caps['mod/forum:approvepost'])) {
+        $commands[] = '<a href="'.$CFG->wwwroot.'/mod/forum/post.php?approve='.$post->id.'">'.$strapprove.'</a>';
+    }
 
     echo '<div class="commands">';
     echo implode(' | ', $commands);
@@ -3899,8 +3940,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;
@@ -3959,7 +4005,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;
     }
@@ -4592,20 +4641,20 @@
 
     // retrieve objects (yuk)
     if (is_numeric($forum)) {
-        debugging('missinf full forum', DEBUG_DEVELOPER);
+        debugging('missing full forum', DEBUG_DEVELOPER);
         if (!$forum = get_record('forum','id',$forum)) {
             return false;
         }
     }
 
     if (is_numeric($discussion)) {
-        debugging('missinf full discussion', DEBUG_DEVELOPER);
+        debugging('missing full discussion', DEBUG_DEVELOPER);
         if (!$discussion = get_record('forum_discussions','id',$discussion)) {
             return false;
         }
     }
     if (is_numeric($post)) {
-        debugging('missinf full post', DEBUG_DEVELOPER);
+        debugging('missing full post', DEBUG_DEVELOPER);
         if (!$post = get_record('forum_posts','id',$post)) {
             return false;
         }
@@ -4635,6 +4684,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) {
@@ -6349,7 +6416,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');
 }
 
 /**
@@ -6888,4 +6955,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/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 Apr 2009 07:03:13 -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: lang/en_utf8/forum.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/forum.php,v
retrieving revision 1.21.4.15
diff -u -r1.21.4.15 forum.php
--- lang/en_utf8/forum.php	30 Jan 2009 11:30:21 -0000	1.21.4.15
+++ lang/en_utf8/forum.php	1 Apr 2009 07:03:12 -0000
@@ -23,6 +23,7 @@
 $string['allsubscribe'] = 'Subscribe to all forums';
 $string['allunsubscribe'] = 'Unsubscribe from all forums';
 $string['anyfile'] = 'Any file';
+$string['approve'] = 'Approve';
 $string['attachment'] = 'Attachment';
 $string['blockafter'] = 'Post threshold for blocking';
 $string['blockperiod'] = 'Time period for blocking';
@@ -89,9 +90,10 @@
 $string['forcesubscribeq'] = 'Force everyone to be subscribed?';
 $string['forum'] = 'Forum';
 $string['forum:addnews'] = 'Add news';
+$string['forum:approvepost'] = 'Approve posts';
 $string['forumauthorhidden'] = 'Author (hidden)';
 $string['forumblockingalmosttoomanyposts'] = 'You are approaching the posting threshold. You have posted $a->numposts times in the last $a->blockperiod and the limit is $a->blockafter posts.';
-$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion yet.';
+$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because it has not yet been approved or you have not posted in the discussion.';
 $string['forum:createattachment'] = 'Create attachments';
 $string['forum:deleteanypost'] = 'Delete any posts (anytime)';
 $string['forum:deleteownpost'] = 'Delete own posts (within deadline)';
@@ -230,6 +232,7 @@
 $string['reply'] = 'Reply';
 $string['replyforum'] = 'Reply to forum';
 $string['replytouser'] = 'Use email address in reply';
+$string['requireapprovalq'] = 'Require approval?';
 $string['resetforumsall'] = 'Delete all posts';
 $string['resetforums'] = 'Delete posts from';
 $string['resetsubscriptions'] = 'Delete all forum subscriptions';
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 Apr 2009 07:03:13 -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,18 @@
+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. Suggestions and comments are welcome in the tracker. 
