Index: admin/settings/security.php
===================================================================
RCS file: /cvsroot/moodle/moodle/admin/settings/security.php,v
retrieving revision 1.29
diff -u -a -w -b -B -r1.29 security.php
--- admin/settings/security.php	22 Jul 2008 04:07:59 -0000	1.29
+++ admin/settings/security.php	17 Aug 2008 22:32:05 -0000
@@ -46,6 +46,7 @@
                                                                                                                                               1 => get_string('personalblogs','blog'),
                                                                                                                                               0 => get_string('disableblogs','blog'))));
     $temp->add(new admin_setting_configcheckbox('usetags', get_string('usetags','admin'),get_string('configusetags', 'admin'),'1'));
+    $temp->add(new admin_setting_configcheckbox('useassoc', get_string('useassoc','admin'),get_string('configuseassoc', 'admin'),'1'));
     $temp->add(new admin_setting_configcheckbox('keeptagnamecase', get_string('keeptagnamecase','admin'),get_string('configkeeptagnamecase', 'admin'),'1'));
     $temp->add(new admin_setting_configcheckbox('cronclionly', get_string('cronclionly', 'admin'), get_string('configcronclionly', 'admin'), 0));
     $temp->add(new admin_setting_configpasswordunmask('cronremotepassword', get_string('cronremotepassword', 'admin'), get_string('configcronremotepassword', 'admin'), ''));
Index: blocks/blog_menu/block_blog_menu.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/blog_menu/block_blog_menu.php,v
retrieving revision 1.18
diff -u -a -w -b -B -r1.18 block_blog_menu.php
--- blocks/blog_menu/block_blog_menu.php	2 May 2008 04:37:04 -0000	1.18
+++ blocks/blog_menu/block_blog_menu.php	17 Aug 2008 22:32:05 -0000
@@ -1,6 +1,7 @@
 <?php //$Id: block_blog_menu.php,v 1.18 2008/05/02 04:37:04 dongsheng Exp $
 
 require_once($CFG->dirroot .'/blog/lib.php');
+require_once($CFG->dirroot .'/course/lib.php');
 
 class block_blog_menu extends block_base {
 
@@ -11,7 +12,7 @@
     }
 
     function get_content() {
-        global $CFG, $USER, $COURSE;
+        global $CFG, $USER, $COURSE, $DB, $PAGE;
 
         if (empty($CFG->bloglevel)) {
             $this->content->text = '';
@@ -39,22 +40,54 @@
 
         $this->content = new stdClass;
         $this->content->footer = '';
-        if (empty($this->instance) /*|| empty($CFG->blog_version)*/) {
+        if (empty($this->instance)) {
             // Either we're being asked for content without
             // an associated instance of the Blog module has never been installed.
             $this->content->text = $output;
             return $this->content;
         }
 
-        //if ( blog_isLoggedIn() && !isguest() ) {
-            $courseviewlink = '';
+        //discover context for pre-loaded associations
+        $basefilters = array();
+        if(!empty($COURSE)) $courseid = $COURSE->id;
+        switch($PAGE->get_type()) {
+            case PAGE_COURSE_VIEW:
+                $courseid = $PAGE->courserecord->id;
+                $basefilters['courseid'] = $courseid;
+                break;
+            case PAGE_BLOG_VIEW:
+                $basefilters = $PAGE->filters;
+                if(!empty($PAGE->filters['course']))
+                    $courseid = $PAGE->filters['course'];
+                if(!empty($PAGE->filters['mod']))
+                    $modid = $PAGE->filters['mod'];
+                if(!empty($PAGE->filters['user']))
+                    $userid = $PAGE->filters['user'];
+                if(!empty($PAGE->filters['group']))
+                    $groupid = $PAGE->filters['group'];
+                if(!empty($PAGE->filters['tag']))
+                    $tagid = $PAGE->filters['tag'];
+                break;
+        }
+       
             $addentrylink = '';
-            $coursearg = '';
+        $blogprefslink = '';
+        $myviewlink = '';
+        $siteviewlink = '';
+        $courseviewlink = '';
+        $modviewlink = '';
+        $groupviewlink = '';
+        $userviewlink = '';
+        $tagviewlink = '';
+        $coursepopuplink = '';
+        $modpopuplink = '';
+        $grouppopuplink = '';
+        $userspopuplink = '';
 
+        //create basic blog preference links
+        $coursearg = '';
             $sitecontext = get_context_instance(CONTEXT_SYSTEM);
-
-            if ($COURSE->id != SITEID) {
-
+        if ($courseid != SITEID) {
                 $incoursecontext = true;
                 $curcontext = get_context_instance(CONTEXT_COURSE, $COURSE->id);
             } else {
@@ -61,23 +94,13 @@
                 $incoursecontext = false;
                 $curcontext = $sitecontext;
             }
-
             $canviewblogs = has_capability('moodle/blog:view', $curcontext);
-
-            /// Accessibility: markup as a list.
-
             if ( (isloggedin() && !isguest()) && $incoursecontext
                     && $CFG->bloglevel >= BLOG_COURSE_LEVEL && $canviewblogs) {
-
-                $coursearg = '&amp;courseid='.$COURSE->id;
-                // a course is specified
-
-                $courseviewlink = '<li><a href="'. $CFG->wwwroot .'/blog/index.php?filtertype=course&amp;filterselect='. $COURSE->id .'">';
-                $courseviewlink .= get_string('viewcourseentries', 'blog') ."</a></li>\n";
+             $coursearg = '&amp;courseid='.$courseid;
+             if(!empty($modid)) $coursearg .= '&amp;modid='.$modid;
             }
-
             $blogmodon = false;
-
             if ( (isloggedin() && !isguest())
                         && (!$blogmodon || ($blogmodon && $coursearg != ''))
                         && $CFG->bloglevel >= BLOG_USER_LEVEL ) {
@@ -81,42 +104,180 @@
             if ( (isloggedin() && !isguest())
                         && (!$blogmodon || ($blogmodon && $coursearg != ''))
                         && $CFG->bloglevel >= BLOG_USER_LEVEL ) {
-
-                // show Add entry link
+            // create the Add entry link
                 if (has_capability('moodle/blog:create', $sitecontext)) {
                     $addentrylink = '<li><a href="'. $CFG->wwwroot. '/blog/edit.php?action=add'
                                    .$coursearg.'">'.get_string('addnewentry', 'blog') ."</a></li>\n";
                 }
-                // show View my entries link
-                $addentrylink .= '<li><a href="'. $CFG->wwwroot .'/blog/index.php?userid='.
-                                 $userBlog->userid.'">'.get_string('viewmyentries', 'blog').
-                                 "</a></li>\n";
-
-                // show link to manage blog prefs
-                $addentrylink .= '<li><a href="'. $CFG->wwwroot. '/blog/preferences.php?userid='.
+            // create the link to manage blog prefs
+            $blogprefslink = '<li><a href="'. $CFG->wwwroot. '/blog/preferences.php?userid='.
                                  $userBlog->userid . $coursearg .'">'.
                                  get_string('blogpreferences', 'blog')."</a></li>\n";
-
-                $output = $addentrylink;
-                $output .= $courseviewlink;
+            // create the View my entries link
+            $myviewlink = '<li><a href="'.blog_get_blogs_url(array('user'=>$USER->id)).'">'.
+                          //'<img src="'.$CFG->pixpath.'/i/user.gif" class="icon" alt="" />'.fullname($USER).
+                          get_string('viewmyentries', 'blog').
+                          "</a></li>\n";
             }
 
-            // show View site entries link
+        // create the View site entries link
             if ($CFG->bloglevel >= BLOG_SITE_LEVEL && $canviewblogs) {
-                $output .= '<li><a href="'. $CFG->wwwroot .'/blog/index.php?filtertype=site&amp;">';
-                $output .= get_string('viewsiteentries', 'blog')."</a></li>\n";
+            $siteviewlink .= '<li><a href="'.blog_get_blogs_url(array()).'">'.
+                             get_string('viewsiteentries', 'blog').
+                             //$DB->get_field('course', 'shortname', array('format'=>'site')).
+                             "</a></li>\n";
+            }
+
+        //create 'view blogs for course' link
+        if($incoursecontext and (!empty($modid) or !empty($userid) or !empty($tagid) or !empty($groupid) or 
+                                 $PAGE->get_type() == PAGE_COURSE_VIEW)
+           and $CFG->bloglevel >= BLOG_COURSE_LEVEL and $canviewblogs) {
+            $courseviewlink = '<li><a href="'. blog_get_blogs_url(array('course'=>$courseid)) .'">'
+                             .'<img src="'.$CFG->pixpath.'/i/course.gif" class="icon" alt="" />'.
+                              $DB->get_field('course', 'shortname', array('id'=>$courseid)) ."</a></li>\n";
+        }        
+
+        //create 'view blogs for user' link
+        if(!empty($userid) and $userid != $USER->id and (!empty($modid) or !empty($courseid) or !empty($tagid) or !empty($groupid))
+           and  $canviewblogs) {
+            $userviewlink = '<li><a href="'. blog_get_blogs_url(array('user'=>$userid)) .'">'.
+                            '<img src="'.$CFG->pixpath.'/i/user.gif" class="icon" alt="" />'. 
+                            $DB->get_field('user', 'username', array('id'=>$userid)).
+                            "</a></li>\n";
+        }
+
+        //create 'view blogs for mod' link
+        if(!empty($modid) and (!empty($groupid) or !empty($userid) or !empty($tagid))
+           and $CFG->bloglevel >= BLOG_COURSE_LEVEL and $canviewblogs) {
+           $filtercontext = get_context_instance(CONTEXT_MODULE, $modid);
+           $modinfo = $DB->get_record('course_modules', array('id' => $filtercontext->instanceid));
+           $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module));
+           $modviewlink = '<li><a href="'. blog_get_blogs_url(array('mod'=>$modid)) .'">'.
+                          '<img src="'.$CFG->wwwroot.'/mod/'.$modname.'/icon.gif" border=0 alt="">'.
+                          $DB->get_field($modname, 'name', array('id' => $modinfo->instance)).
+                          "</a></li>\n";
+        }
+
+        //create 'view blogs for group' link
+        if(!empty($groupid) and (!empty($modid) or !empty($tagid) or !empty($userid))
+           and $CFG->bloglevel >= BLOG_GROUP_LEVEL and $canviewblogs) {
+            $groupviewlink = '<li><a href="'. blog_get_blogs_url(array('group'=>$groupid)) .'">'.
+                             '<img src="'.$CFG->pixpath.'/i/group.gif" class="icon" alt="" />'.
+                             $DB->get_field('groups', 'name', array('id'=>$groupid)) ."</a></li>\n";
+        }
+
+        //create 'view blogs for tag' link
+        if(!empty($tagid) && (!empty($modid) or !empty($userid) or !empty($courseid) or !empty($groupid)) and $canviewblogs) {
+            $tagviewlink = '<li>'.get_string('tag', 'tag').': <a href="'. blog_get_blogs_url(array('tag'=>$tagid)) .'">'.
+                           $DB->get_field('tag', 'name', array('id'=>$tagid))."</a></li>\n";
+        }
+
+        //create 'view blogs for this site's courses' link
+        if($canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+            $courseoptions = array();
+            if(!empty($courseid)) {
+                if($courseid != SITEID) {
+                    $newfilters = $basefilters;
+                    unset($newfilters['course']);
+                    unset($newfilters['mod']);
+                    unset($newfilters['group']);
+                    $courseoptions = array(blog_get_blogs_url($newfilters) => 'none');
+                }
+            }
+                    
+            foreach($DB->get_records('course', array()) as $course) {
+                if($course->id != SITEID) {
+                    $newfilters = $basefilters;
+                    if(!empty($courseid)) {
+                        if($course->id != $courseid) {
+                            unset($newfilters['mod']);
+                        }
+                    }
+                    $newfilters['course'] = $course->id;
+                    $courseoptions[blog_get_blogs_url($newfilters)] = $course->shortname;
+                } 
+            }
+            $coursepopuplink = '<li>'.popup_form('', $courseoptions, 'view_course_blogs', blog_get_blogs_url($basefilters), 
+                                                 get_string('course'),'', '', true) . "</li>\n";
+        } 
+
+        //create 'view blogs for this course's mods' link
+        if(!empty($courseid) and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+            $modnames = array();
+            $modnamesplural = array();
+            $modnamesused = array();
+            $modoptions = array();
+            if(!empty($modid)) {
+                $newfilters = $basefilters;
+                unset($newfilters['mod']);
+                $modoptions = array(blog_get_blogs_url($newfilters) => 'none');
+            }
+            get_all_mods($courseid, $mods, $modnames, $modnamesplural, $modnamesused);
+            foreach($mods as $i => $mod) {
+                $newfilters = $basefilters;
+                $newfilters['mod'] = $mod->id;
+                $modoptions[blog_get_blogs_url($newfilters)] = $DB->get_field($mod->modname, 'name', array('id' => $mod->instance));
+            }
+            $modpopuplink = '<li>'.popup_form('', $modoptions, 'view_mod_blogs', blog_get_blogs_url($basefilters), 
+                                              get_string('resource').'/'.get_string('activity'),
+                                              '', '', true)."</li>\n";
+        }
+
+        //create 'view blogs for this course's groups link
+        if($incoursecontext and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+            $groupoptions = array();
+            if(!empty($groupid)) {
+                $newfilters = $basefilters;
+                unset($newfilters['group']);
+                $groupoptions = array(blog_get_blogs_url($newfilters) => 'none');
+            }
+                
+            foreach($DB->get_records('groups', array('courseid'=>$courseid)) as $group) {
+                $newfilters = $basefilters;
+                $newfilters['group'] = $group->id;
+                $groupoptions[blog_get_blogs_url($newfilters)] = $group->name;
+            }
+            $grouppopuplink = '<li>'.popup_form('', $groupoptions, 'view_group_blogs', blog_get_blogs_url($basefilters), 
+                                                get_string('group'),'', '', true)."</li>\n";
+        }
+
+        //create 'view blogs for this course/group's users link
+        if(!empty($courseid) and $canviewblogs and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+            $useroptions = array();
+            if(!empty($userid)) {
+                $newfilters = $basefilters;
+                unset($newfilters['user']);
+                $useroptions = array(blog_get_blogs_url($newfilters) => 'none');
+            }
+            if(!empty($groupid)) {
+                $members = $DB->get_records('groups_members', array('groupid'=>$groupid));
+            } else {
+                $coursecontext = get_context_instance(CONTEXT_COURSE, $courseid);
+                $members = $DB->get_records('role_assignments', array('contextid'=>$coursecontext->id));
+            }
+            foreach($members as $member) {
+                $newfilters = $basefilters;
+                $newfilters['user'] = $member->userid;
+                $useroptions[blog_get_blogs_url($newfilters)] = $DB->get_field('user', 'username', array('id'=>$member->userid));
+            }
+            $userspopuplink = '<li>'.popup_form('', $useroptions, 'view_user_blogs', blog_get_blogs_url($basefilters), 
+                                                get_string('user'),'', '', true)."</li>\n";
+                                             
             }
 
-            // took out tag management interface/link, should use tag/manage.php
 
-            // show Help with blogging link
-            //$output .= '<li><a href="'. $CFG->wwwroot .'/help.php?module=blog&amp;file=user.html">';
-            //$output .= get_string('helpblogging', 'blog') ."</a></li>\n";
-        //} else {
-        //    $output = ''; //guest users and users who are not logged in do not get menus
-        //}
+        $this->content->text = 
+            '<ul class="list">' . 
+            $addentrylink.$blogprefslink.$myviewlink.$siteviewlink.
+            ($courseviewlink||$modviewlink||$groupviewlink||$userviewlink||$tagviewlink ?
+                ('<ul class="list">'.get_string('viewblogsfor', 'blog')).
+                $courseviewlink.$modviewlink.$groupviewlink.$userviewlink.$tagviewlink.
+                '</ul>' : '').
+            ($coursepopuplink||$modpopuplink||$grouppopuplink||$userspopuplink ?
+                '<ul class="list">'.get_string('filterblogsby', 'blog').
+                $coursepopuplink.$modpopuplink.$grouppopuplink.$userspopuplink.'</ul>' : '').
+            "</ul>\n";
 
-        $this->content->text = '<ul class="list">'. $output ."</ul>\n";
         return $this->content;
     }
 }
Index: blocks/blog_tags/block_blog_tags.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blocks/blog_tags/block_blog_tags.php,v
retrieving revision 1.38
diff -u -a -w -b -B -r1.38 block_blog_tags.php
--- blocks/blog_tags/block_blog_tags.php	17 Jul 2008 04:22:41 -0000	1.38
+++ blocks/blog_tags/block_blog_tags.php	17 Aug 2008 22:32:05 -0000
@@ -158,7 +158,7 @@
                     break;
                 }
 
-                $link = $CFG->wwwroot.'/blog/index.php?filtertype='.$filtertype.'&amp;filterselect='.$filterselect.'&amp;tagid='.$tag->id;
+                $link = blog_get_blogs_url(array($filtertype => $filterselect, 'tag'=>$tag->id));
                 $this->content->text .= '<li><a href="'.$link.'" '.
                                         'class="'.$tag->class.'" '.
                                         'title="'.get_string('numberofentries','blog',$tag->ct).'">'.
Index: blog/blogpage.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/blogpage.php,v
retrieving revision 1.17
diff -u -a -w -b -B -r1.17 blogpage.php
--- blog/blogpage.php	27 Jun 2008 03:35:22 -0000	1.17
+++ blog/blogpage.php	17 Aug 2008 22:32:06 -0000
@@ -15,8 +15,7 @@
     var $editing = false;
     var $courserecord = NULL;
     var $courseid = NULL;
-    var $filtertype = NULL;
-    var $filterselect = NULL;
+    var $filters = array();
     var $tagid = NULL;
 
     // Mandatory; should return our identifier.
@@ -59,7 +58,9 @@
         }
         // I need to determine how best to utilize this function. Most init
         // is already done before we get here in blogFilter and blogInfo
-
+        if(!empty($this->filters['course'])) {
+            $this->courseid = $this->filters['course'];     
+        }
         if ($this->courseid == 0 || $this->courseid == 1 || !is_numeric($this->courseid) ) {
             $this->courseid = '';
             $courserecord = NULL;
@@ -118,17 +119,26 @@
             return $array;
         }
 
-        if (!empty($this->courseid)) {
-            $array['courseid'] = $this->courseid;
+        if(!empty($this->filters['course'])) {
+            $array['courseid'] = $this->filters['course'];
+        }
+        if(!empty($this->filters['mod'])) {
+            $array['modid'] = $this->filters['mod'];
+        }
+        if(!empty($this->filters['group'])) {
+            $array['groupid'] = $this->filters['group'];
+        }
+        if(!empty($this->filters['user'])) {
+            $array['userid'] = $this->filters['user'];
         }
-        if (!empty($this->filtertype)) {
-            $array['filtertype'] = $this->filtertype;
+        if(!empty($this->filters['post'])) {
+           $array['postid'] = $this->filters['post'];
         }
-        if (!empty($this->filterselect)) {
-            $array['filterselect'] = $this->filterselect;
+        if(!empty($this->filters['tag'])) {
+            $array['tagid'] = $this->filters['tag'];
         }
-        if (!empty($this->tagid)) {
-            $array['tagid'] = $this->tagid;  
+        if(!empty($this->filters['tagtext'])) {
+            $array['tag'] = $this->filters['tagtext'];
         }
         return $array;
     }
Index: blog/edit.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/edit.php,v
retrieving revision 1.68
diff -u -a -w -b -B -r1.68 edit.php
--- blog/edit.php	31 Jul 2008 22:15:31 -0000	1.68
+++ blog/edit.php	17 Aug 2008 22:32:06 -0000
@@ -7,6 +7,7 @@
 $action   = required_param('action', PARAM_ALPHA);
 $id       = optional_param('id', 0, PARAM_INT);
 $confirm  = optional_param('confirm', 0, PARAM_BOOL);
+$modid = optional_param('modid', 0, PARAM_INT);
 $courseid = optional_param('courseid', 0, PARAM_INT); // needed for user tab - does nothing here
 
 require_login($courseid);
@@ -70,7 +71,39 @@
 }
 
 require_once('edit_form.php');
-$blogeditform = new blog_edit_form(null, compact('existing', 'sitecontext'));
+if(!empty($existing)) {
+    $assignmentdata = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade
+                                                   FROM {assignment} a, {assignment_submissions} as asub WHERE
+                                                   a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\'
+                                                   AND asub.data1 = \''.$existing->id.'\'');
+}
+//add associations
+if(!empty($existing)) {
+    if ($blogassociations = $DB->get_records('blog_association', array('blogid' => $existing->id))) {
+        foreach($blogassociations as $assocrec) {
+            $contextrec = $DB->get_record('context', array('id' => $assocrec->contextid));
+            switch($contextrec->contextlevel) {
+                case CONTEXT_COURSE: 
+                    $existing->courseassoc = $assocrec->contextid;
+                break;
+                case CONTEXT_MODULE: 
+                    $existing->modassoc[] = $assocrec->contextid;
+                break;
+            }
+        }
+    }
+}
+
+if($action == 'add' and $courseid) {  //pre-select the course for associations
+    $context = get_context_instance(CONTEXT_COURSE, $courseid);
+    $existing->courseassoc = $context->id;
+}
+if($action == 'add' and $modid) { //pre-select the mod for associations
+    $context = get_context_instance(CONTEXT_MODULE, $modid);
+    $existing->modassoc = array($context->id);
+} 
+
+$blogeditform = new blog_edit_form(null, compact('existing', 'sitecontext', 'assignmentdata'));
 
 if ($blogeditform->is_cancelled()){
     redirect($returnurl);
@@ -101,6 +134,14 @@
         $post->publishstate = 'site';
         $strformheading = get_string('addnewentry', 'blog');
         $post->action       = $action;
+        if($courseid) {  //pre-select the course for associations
+            $context = get_context_instance(CONTEXT_COURSE, $courseid);
+            $post->courseassoc = $context->id;
+        }
+        if($modid) { //pre-select the mod for associations
+            $context = get_context_instance(CONTEXT_MODULE, $modid);
+            $post->modassoc = array($context->id);
+        } 
     break;
 
     case 'edit':
@@ -109,10 +150,16 @@
         }
         $post->id           = $existing->id;
         $post->subject      = $existing->subject;
+        $post->fakesubject  = $existing->subject;
         $post->summary      = $existing->summary;
+        $post->fakesummary  = $existing->summary;
         $post->publishstate = $existing->publishstate;
         $post->format       = $existing->format;
         $post->action       = $action;
+    if(!empty($existing->courseassoc)) 
+            $post->courseassoc  = $existing->courseassoc;
+    if(!empty($existing->modassoc)) 
+            $post->modassoc     = $existing->modassoc;
         $strformheading = get_string('updateentrywithid', 'blog');
 
         if ($itemptags = tag_get_tags_csv('post', $post->id, TAG_RETURN_TEXT, 'default')) {
@@ -138,6 +185,8 @@
 $navigation = build_navigation($navlinks);
 
 print_header("$SITE->shortname: $strblogs", $SITE->fullname, $navigation,'','',true);
+                    
+
 $blogeditform->set_data($post);
 $blogeditform->display();
 
@@ -153,13 +202,23 @@
 * Delete blog post from database
 */
 function do_delete($post) {
-    global $returnurl, $DB;
+    global $returnurl, $DB, $USER;
+    
+    //check to see if it's part of a submitted blog assignment
+    if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, asub.grade
+                                          FROM {assignment} a, {assignment_submissions} as asub WHERE 
+                                          a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\'
+                                          AND asub.data1 = \''.$post->id.'\'')) {
+        print_error('cantdeleteblogassignment', 'blog', $returnurl);
+    }
 
     blog_delete_attachments($post);
 
     $status = $DB->delete_records('post', array('id'=>$post->id));
     tag_set('post', $post->id, array());
     
+    blog_remove_associations_for_post($post->id);
+        
     add_to_log(SITEID, 'blog', 'delete', 'index.php?userid='. $post->userid, 'deleted blog entry with entry id# '. $post->id);
 
     if (!$status) {
@@ -189,6 +248,9 @@
         }
 
         add_tags_info($post->id);
+        
+        if(!empty($CFG->useassoc)) add_associations($post);
+        
         add_to_log(SITEID, 'blog', 'add', 'index.php?userid='.$post->userid.'&postid='.$post->id, $post->subject);
 
     } else {
@@ -203,8 +265,26 @@
  * @todo complete documenting this function. enable trackback and pingback between entries on the same server
  */
 function do_edit($post, $blogeditform) {
+    
     global $CFG, $USER, $returnurl, $DB;
 
+    //check to see if it is a submitted assignment
+    if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asi.grade, asi.id
+                                          FROM {assignment} a, {assignment_submissions} as asi WHERE 
+                                          a.id = asi.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\'
+                                          AND asi.data1 = \''.$post->id.'\'')) {
+        
+        //email teachers if necessary
+        if($blogassignment->emailteachers) {
+            email_teachers($DB->get_record('assignment_submissions', array('id'=>$blogassignment['id'])));
+        }
+                                            
+    } else {  //only update the attachment and associations if it is not a submitted assignment
+        
+        if(!empty($CFG->useassoc)) add_associations($post);
+    }
+    
+
     $post->lastmodified = time();
 
     if ($blogeditform->get_new_filename('attachment')) {
@@ -235,7 +315,7 @@
 
 /**
  * function to attach tags into a post
- * @param int postid - id of the blog
+ * @param int postid - id of the blog post
  */
 function add_tags_info($postid) {
     
@@ -249,9 +329,30 @@
         }
     }
 
-    $manual_tags = optional_param('ptags', '', PARAM_NOTAGS);
-    $tags = array_merge($tags, explode(',', $manual_tags));
+    $manualtags = optional_param('ptags', '', PARAM_NOTAGS);
+    $tags = array_merge($tags, explode(',', $manualtags));
     
     tag_set('post', $postid, $tags);
 }
+
+/**
+ * function to add all context associations to a post
+ * @param int post - data object processed to include all 'post' fields and extra data from the edit_form object
+ */
+function add_associations($post) {
+    global $DB, $USER;
+    
+    $allowaddcourseassoc = true;
+    blog_remove_associations_for_post($post->id);
+    if(!empty($post->courseassoc)) {
+        blog_add_association($post->id, $post->courseassoc);
+        $allowaddcourseassoc = false;
+    }
+    if(!empty($post->modassoc)) {
+        foreach($post->modassoc as $modid) {
+            blog_add_association($post->id, $modid, $allowaddcourseassoc);  
+            $allowaddcourseassoc = false;   //let the course be added the first time
+        }
+    }
+}
 ?>
Index: blog/edit_form.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/edit_form.php,v
retrieving revision 1.16
diff -u -a -w -b -B -r1.16 edit_form.php
--- blog/edit_form.php	31 Jul 2008 22:15:31 -0000	1.16
+++ blog/edit_form.php	17 Aug 2008 22:32:06 -0000
@@ -5,19 +5,39 @@
 class blog_edit_form extends moodleform {
 
     function definition() {
-        global $CFG, $COURSE, $USER;
+        global $CFG, $COURSE, $USER, $DB;
 
         $mform    =& $this->_form;
-
-        $post = $this->_customdata['existing'];
+        if(!empty($this->_customdata['assignmentdata'])) {
+            $assignmentdata = $this->_customdata['assignmentdata'];
+        }
+        $existing = $this->_customdata['existing'];
         $sitecontext = $this->_customdata['sitecontext'];
 
+        //determine if content elements should be deactivated for a past due blog assignment
+        $noedit = false;
+        if(!empty($assignmentdata)) {
+            if((time() > $assignmentdata->timedue and $assignmentdata->preventlate) or $assignmentdata->grade != -1) {
+                $noedit = true;
+            }
+        }
+
         $mform->addElement('header', 'general', get_string('general', 'form'));
+        
+        if($noedit) { //show disabled form elements, but provide hidden elements so that the data is transferred
+            $mform->addElement('text', 'fakesubject', get_string('entrytitle', 'blog'), array('size'=>60, 'disabled'=>'disabled'));
+            $mform->addElement('textarea', 'fakesummary', get_string('entrybody', 'blog'), array('rows'=>25, 'cols'=>40, 'disabled'=>'disabled'));
+            $mform->setHelpButton('fakesummary', array('writing', 'richtext'), false, 'editorhelpbutton');
+            $mform->addElement('hidden', 'subject');
+            $mform->addElement('hidden', 'summary');
+        } else {  //insert normal form elements
         $mform->addElement('text', 'subject', get_string('entrytitle', 'blog'), 'size="60"');
+            $mform->addElement('htmleditor', 'summary', get_string('entrybody', 'blog'), array('rows'=>25));
+        }
+        
         $mform->setType('subject', PARAM_TEXT);
         $mform->addRule('subject', get_string('emptytitle', 'blog'), 'required', null, 'client');
 
-        $mform->addElement('htmleditor', 'summary', get_string('entrybody', 'blog'), array('rows'=>25));
         $mform->setType('summary', PARAM_RAW);
         $mform->addRule('summary', get_string('emptybody', 'blog'), 'required', null, 'client');
         $mform->setHelpButton('summary', array('writing', 'richtext'), false, 'editorhelpbutton');
@@ -26,7 +46,21 @@
 
         $mform->addElement('file', 'attachment', get_string('attachment', 'forum'));
 
-        $mform->addElement('select', 'publishstate', get_string('publishto', 'blog'), blog_applicable_publish_states());
+        //disable publishstate options that are not allowed
+        $publishstates = array();
+        $i = 0;
+        foreach(blog_applicable_publish_states() as $state => $desc) {
+            if(!empty($assignmentdata)) {
+                if($i <= $assignmentdata->var2)  { //var2 is the maximum publish state allowed
+                        $publishstates[$state] = $desc;
+                }
+            } else { 
+                $publishstates[$state] = $desc;   //no maximum was set
+            }
+
+            $i++;
+        }
+        $mform->addElement('select', 'publishstate', get_string('publishto', 'blog'), $publishstates);
         $mform->setHelpButton('publishstate', array('publish_state', get_string('publishto', 'blog'), 'blog'));
 
 
@@ -42,6 +76,34 @@
             $mform->setType('ptagsadd', PARAM_NOTAGS);
         }
         
+        $allmodnames = array();
+        if (!empty($CFG->useassoc)) {
+            $mform->addElement('header', 'assochdr', get_string('associations', 'blog'));
+            $courses = get_my_courses($USER->id, 'visible DESC, fullname ASC');
+            $course_names[0] = 'none';
+            if(!empty($courses)) {
+            foreach($courses as $course) {
+                    $course_names[$course->context->id] = $course->fullname;
+                    $modinfo = get_fast_modinfo($course, $USER->id);
+                    $course_context_path = $DB->get_field('context', 'path', array('id' => $course->context->id));
+            
+                    foreach($modinfo->instances as $modname => $instances) {
+                        foreach($instances as $modid => $mod) { 
+                            $mod_context_id = $DB->get_field_select('context', 'id', 
+                                'instanceid = '.$mod->id.' AND ' .
+                                'contextlevel = ' . CONTEXT_MODULE . ' AND ' .
+                                'path LIKE \''.$course_context_path.'/%\'');
+                            $this->modnames[$course->context->id][$mod_context_id] = $modname . ": ".$mod->name;
+                            $allmodnames[$mod_context_id] = $course->shortname . " - " . $modname . ": ".$mod->name;
+                        }
+                    }
+                }
+            }
+            $mform->addElement('select', 'courseassoc', get_string('course'), $course_names, 'onchange="addCourseAssociations()"');
+            $selectassoc = &$mform->addElement('select', 'modassoc', get_string('managemodules'), $allmodnames);
+            $selectassoc->setMultiple(true);
+        }
+        
         $this->add_action_buttons();
 
         $mform->addElement('hidden', 'action');
@@ -55,7 +117,223 @@
         $mform->setType('id', PARAM_INT);
         $mform->setDefault('id', 0);
 
+        if(!empty($assignmentdata)) {   //dont allow associations for blog assignments
+            $courseassoc = $mform->getElement('courseassoc');
+            $modassoc = $mform->getElement('modassoc');
+            $courseassoc->updateAttributes(array('disabled' => 'disabled'));
+            $modassoc->updateAttributes(array('disabled' => 'disabled'));
+    }
+        if($noedit) {  //disable some other fields when editing is not allowed
+            $subject = $mform->getElement('subject');
+            $summary = $mform->getElement('summary');
+            $attachment = $mform->getElement('attachment');
+            $format = $mform->getElement('format');
+            $attachment->updateAttributes(array('disabled' => 'disabled'));
+            $format->updateAttributes(array('disabled' => 'disabled')); 
+        }
+        
+    }
+    
+    
+    
+
+    function validation($data, $files) {
+        global $CFG, $DB, $USER;
+         
+        $errors = array();
+
+        //check to see if it's part of a submitted blog assignment
+        if($blogassignment = $DB->get_record_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade
+                                          FROM {assignment} a, {assignment_submissions} as asub WHERE 
+                                          a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\'
+                                          AND asub.data1 = \''.$data['id'].'\'')) {
+            
+            $original = $DB->get_record('post', array('id' => $data['id']));
+            //don't allow updates of the sumamry, subject, or attachment
+            $changed = ($original->summary != $data['summary'] || 
+                        $original->subject != $data['subject'] || 
+                        !empty($files));
+            
+            
+            //determine numeric value for publish state (for comparison purposes)
+            $postaccess = -1;
+            $i=0;
+            foreach(blog_applicable_publish_states() as $state => $desc) {
+                if($state == $data['publishstate']) {
+                    $postaccess = $i;
+                }
+                $publishstates[$i++] = $state;
+            }
+            
+            //send an error if improper changes are being made
+            if(($changed and time() > $blogassignment->timedue and $blogassignment->preventlate = 1) or 
+                ($changed and $blogassignment->grade != -1) or
+                (time() < $blogassignment->timedue and ($postaccess > $blogassignment->var2 || $postaccess == -1))) {
+                //too late to edit this post
+                if($original->subject != $data['subject']) {
+                    $errors['subject'] = get_string('canteditblogassignment', 'blog');
+                }
+                if($original->summary != $data['summary']) {
+                    $errors['summary'] = get_string('canteditblogassignment', 'blog');
+                }
+                if(!empty($files)) {
+                    $errors['attachment'] = get_string('canteditblogassignment', 'blog');
+                }
+            }
+            
+            //insure the publishto value is within proper constraints
+            
+            if(time() < $blogassignment->timedue and ($postaccess > $blogassignment->var2 || $postaccess == -1)) {
+                $errors['publishto'] = get_string('canteditblogassignment', 'blog');
+            }
+            
+        } else {
+            if(!$data['courseassoc'] && ($data['publishstate'] == 'course' || $data['publishstate'] == 'group')
+                                     && !empty($CFG->useassoc)) {
+                return array('publishstate' => get_string('mustassociatecourse', 'blog'));
+            }
+        }
+
+
+        //validate course association
+        if(!empty($data['courseassoc'])) {
+            $coursecontext = $DB->get_record('context', array('id' => $data['courseassoc'], 'contextlevel' => CONTEXT_COURSE));
+            if($coursecontext)  {    //insure associated course has a valid context id
+                //insure the user has access to this course
+                if(!has_capability('moodle/course:view', $coursecontext, $USER->id)) {
+                    $errors['courseassoc'] = get_string('studentnotallowed', '', fullname($USER, true));
     }
+            } else {
+                $errors['courseassoc'] = get_string('invalidcontextid', 'blog');
+            }
+        }
+
+        //validate mod associations
+        if(!empty($data['modassoc'])) {
+            //insure mods are valid 
+            foreach($data['modassoc'] as $modid) {
+                $modcontext = $DB->get_record('context', array('id' => $modid, 'contextlevel' => CONTEXT_MODULE));
+                if($modcontext) {  //insure associated mod has a valid context id
+                    //get context of the mod's course
+                    $path = split('/', $modcontext->path);
+                    $coursecontext = $DB->get_record('context', array('id' => $path[3]));
+
+                    //insure only one course is associated
+                    if(!empty($data['courseassoc'])) {
+                        if($data['courseassoc'] != $coursecontext->id) {
+                            $errors['modassoc'] = get_string('onlyassociateonecourse', 'blog');
+                        }
+                    } else {
+                        $data['courseassoc'] = $coursecontext->id;
+                    }
+
+                    //insure the user has access to each mod's course
+                    if(!has_capability('moodle/course:view', $coursecontext)) {
+                        $errors['modassoc'] = get_string('studentnotallowed', '', fullname($USER, true));
+                    }
+                } else {
+                    $errors['modassoc'] = get_string('invalidcontextid', 'blog');
+                }
+            }
+        }
+        
+        if($errors) {
+            return $errors;
+        }
+        return true;
+    }
+
+
+
+    function display() {
+        $existing = $this->_customdata['existing'];
+
+        parent::display();
+        
+        //add javascript for the association configuration portion of the form
+?>
+<script type="text/javascript">
+<?php
+        //add function to clear the list of context associations
+?>
+function emptyAssocList() { 
+  var modassoc = document.getElementById('id_modassoc');
+  while(modassoc.length > 0) {
+    modassoc.remove(0);
+  }
+}
+<?php              
+        //add function for adding an element to the list of context associations
+       
+?>
+function addModAssoc(name, id) { 
+  var modassoc = document.getElementById('id_modassoc'); 
+  newoption = document.createElement('option'); 
+  newoption.text = name;
+  newoption.value = id; 
+  try { 
+    modassoc.add(newoption, null);  //standard, broken in IE  
+  } catch(ex) { 
+  modassoc.add(newoption);  
+  }
+} 
+<?php
+        //add function to add associations for a particular course
+?>
+function addCourseAssociations() {
+  var courses = document.getElementById('id_courseassoc'); 
+  var course = courses.options[courses.selectedIndex].value;
+  var modassoc = document.getElementById('id_modassoc'); 
+  var newoption = null;
+  emptyAssocList();
+  switch(course) {
+<?php
+        foreach($this->modnames as $course => $coursemods) {
+?>
+    case '<?php echo addslashes($course)?>': 
+<?php
+            foreach($coursemods as $modid => $modname) {
+?>
+      addModAssoc('<?php echo addslashes($modname)?>', '<?php echo $modid?>');
+<?php
+            }
+?>          
+      break; 
+<?php
+      }
+?>
+  }
+}
+
+function select_initial_course() {
+  var course = document.getElementById('id_courseassoc');
+  var mods = document.getElementById('id_modassoc');
+  var i = 0;
+  var j = 0;
+  emptyAssocList();
+<?php if(!empty($existing->courseassoc)) { ?>
+  for(i=0; i < course.length; i= i+1) {
+    if(course.options[i].value == '<?php echo $existing->courseassoc; ?>') {
+      course.selectedIndex = i;
+      addCourseAssociations();
+      for(j=0; j < mods.length; j=j+1) {
+<?php  if(!empty($existing->modassoc)) foreach($existing->modassoc as $modvalue) { ?>
+        if(mods.options[j].value == '<?php echo $modvalue; ?>') {
+          mods.options[j].selected = true;
+        }
+<?php  } ?>
+      }
+    }
+  }
+<?php } ?>
+}
+
+select_initial_course();
+</script>
+<?php       
+    }
+    
+    
 
     /**
      * This function sets up options of otag select element. This is called from definition and also
Index: blog/footer.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/footer.php,v
retrieving revision 1.7
diff -u -a -w -b -B -r1.7 footer.php
--- blog/footer.php	23 Nov 2007 16:49:52 -0000	1.7
+++ blog/footer.php	17 Aug 2008 22:32:06 -0000
@@ -8,7 +8,7 @@
 
 // The right column
 if (blocks_have_content($pageblocks, BLOCK_POS_RIGHT) || $editing) {
-    echo '<td style="vertical-align: top; width: '. $preferred_width_right .'px;" id="right-column">';
+    echo '<td style="vertical-align: top; width: '. $preferredwidthright .'px;" id="right-column">';
     echo '<!-- Begin right side blocks -->'."\n";
     print_container_start();
     blocks_print_group($PAGE, $pageblocks, BLOCK_POS_RIGHT);
Index: blog/header.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/header.php,v
retrieving revision 1.52
diff -u -a -w -b -B -r1.52 header.php
--- blog/header.php	1 Jun 2008 13:48:13 -0000	1.52
+++ blog/header.php	17 Aug 2008 22:32:06 -0000
@@ -7,6 +7,7 @@
 require_once($CFG->dirroot .'/blog/blogpage.php');
 require_once($CFG->libdir .'/blocklib.php');
 require_once($CFG->dirroot .'/course/lib.php');
+require_once($CFG->dirroot.'/tag/lib.php');
 
 $blockaction = optional_param('blockaction','', PARAM_ALPHA);
 $instanceid  = optional_param('instanceid', 0, PARAM_INT);
@@ -47,9 +48,7 @@
     $PAGE = page_create_object($pagetype, $USER->id);
 }
 $PAGE->courseid     = $courseid;
-$PAGE->filtertype   = $filtertype;
-$PAGE->filterselect = $filterselect;
-$PAGE->tagid        = $tagid;
+$PAGE->filters      = $filters;
 
 $PAGE->init_full(); //init the BlogInfo object and the courserecord object
 
@@ -59,9 +58,9 @@
 }
 
 // Calculate the preferred width for left, right and center (both center positions will use the same)
-$preferred_width_left  = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
+$preferredwidthleft  = bounded_number(BLOCK_L_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]),
                                         BLOCK_L_MAX_WIDTH);
-$preferred_width_right = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
+$preferredwidthright = bounded_number(BLOCK_R_MIN_WIDTH, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]),
                                         BLOCK_R_MAX_WIDTH);
 
 // Display the blocks and allow blocklib to handle any block action requested
@@ -82,17 +81,12 @@
     $missingblocks = blocks_get_missing($PAGE, $pageblocks);
 }
 
-if (!empty($tagid)) {
-    $taginstance = $DB->get_record('tag', array('id'=>$tagid));
-} elseif (!empty($tag)) {
-    $taginstance = tag_id($tag);
-}
-
 /// navigations
 /// site blogs - sitefullname -> blogs -> (?tag)
-/// course blogs - sitefullname -> course fullname ->blogs ->(?tag)
+/// course blogs - sitefullname -> course fullname -> (?participants->user/group) -> blogs -> (?tag)
+/// mod blogs    - sitefullname -> course fullname -> mod name -> (?user/group) -> blogs -> (?tag)
 /// group blogs - sitefullname -> course fullname ->group ->(?tag)
-/// user blogs - sitefullname -> (?coursefullname) -> participants -> blogs -> (?tag)
+/// user blogs   - sitefullname -> (?coursefullname) -> (?mod name) -> participants -> blogs -> (?tag)
 
 $blogstring = get_string('blogs','blog');
 $tagstring = get_string('tag');
@@ -104,146 +98,83 @@
 
 $navlinks = array();
 
-/// This is very messy atm.
 
-    switch ($filtertype) {
-        case 'site':
-            if ($tagid || !empty($tag)) {
-                $navlinks[] = array('name' => $blogstring, 'link' => "index.php?filtertype=site", 'type' => 'misc');
-                $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc');
-                $navigation = build_navigation($navlinks);
-                print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-            } else {
-                $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
-                $navigation = build_navigation($navlinks);
-                print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-            }
-        break;
+//tabs compatibility
+$filtertype = 'site';
+$filterselect = $USER->id;  
 
-        case 'course':
-            if ($tagid || !empty($tag)) {
-                $navlinks[] = array('name' => $blogstring,
-                                    'link' => "index.php?filtertype=course&amp;filterselect=$filterselect",
+if(!empty($courseid)) {
+    $COURSE = $DB->get_record('course', array('id'=>$courseid));
+    if (empty($groupid) and has_capability('moodle/course:viewparticipants', $coursecontext))    {
+        $navlinks[] = array('name' => get_string('participants'),
+            'link' => "$CFG->wwwroot/user/index.php?id=$courseid",
                                     'type' => 'misc');
-                $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc');
-                $navigation = build_navigation($navlinks);
-                print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-            } else {
-                $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
-                $navigation = build_navigation($navlinks);
-                print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
             }
-        break;
 
-        case 'group':
+    //tabs compatibility
+    $filtertype = 'course';
+    $filterselect = $courseid;  
+}
 
-            if ($thisgroup = groups_get_group($filterselect, false)) { //TODO:
-                if ($tagid || !empty($tag)) {
-                    $navlinks[] = array('name' => $thisgroup->name,
-                                        'link' => "$CFG->wwwroot/user/index.php?id=$course->id&amp;group=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => $blogstring,
-                                        'link' => "index.php?filtertype=group&amp;filterselect=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
-                    print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-                } else {
+if(!empty($modid)) { //mod 
+    $cm = $DB->get_record('course_modules', array('id' => $modid));
+    $cm->modname = $DB->get_field('modules', 'name', array('id' => $cm->module));
+    $cm->name = $DB->get_field($cm->modname, 'name', array('id' => $cm->instance));
+    
+    //tabs compatibility
+    $filtertype = 'course';
+    $filterselect = $cm->course;  
+}
+
+if(!empty($groupid)) {
+    if ($thisgroup = groups_get_group($groupid, false)) { //TODO:
                     $navlinks[] = array('name' => $thisgroup->name,
-                                        'link' => "$CFG->wwwroot/user/index.php?id=$course->id&amp;group=$filterselect",
+            'link' => "$CFG->wwwroot/user/index.php?id=$course->id&amp;group=$groupid",
                                         'type' => 'misc');
-                    $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
-                    print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-                }
             } else {
                 print_error('cannotfindgroup');
             }
 
-        break;
-
-        case 'user':
-            $participants = get_string('participants');
-            if (!$user = $DB->get_record('user', array('id'=>$filterselect))) {
-               print_error('invaliduserid');
+    //tabs compatibility
+    $filtertype = 'group';
+    $filterselect = $thisgroup->id;  
             }
 
-            if ($course->id != SITEID) {
-                $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);   // Course context
-                $systemcontext = get_context_instance(CONTEXT_SYSTEM);   // SYSTEM context
-
-                if (has_capability('moodle/course:viewparticipants', $coursecontext) || has_capability('moodle/site:viewparticipants', $systemcontext)) {
-                    $navlinks[] = array('name' => $participants,
-                                        'link' => "$CFG->wwwroot/user/index.php?id=$course->id",
-                                        'type' => 'misc');
-                }
+if(!empty($userid)) {    
+    $user = $DB->get_record('user', array('id'=>$userid));
                 $navlinks[] = array('name' => fullname($user),
-                                    'link' => "$CFG->wwwroot/user/view.php?id=$filterselect&amp;course=$course->id",
-                                    'type' => 'misc');
-
-                if ($tagid || !empty($tag)) {
-                    $navlinks[] = array('name' => $blogstring,
-                                        'link' => "index.php?courseid=$course->id&amp;filtertype=user&amp;filterselect=$filterselect",
+        'link' => "$CFG->wwwroot/user/view.php?id=$userid".(empty($courseid)?'':"&amp;course=$courseid"),
                                         'type' => 'misc');
-                    $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
 
-                } else {
-                    $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
+    //tabs compatibility
+    $filtertype = 'user';
+    $filterselect = $user->id;  
                 }
-                print_header("$course->shortname: $blogstring", $course->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
 
-            } else {
-
-            //in top view
+$navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
 
-                if ($postid) {
-                    $navlinks[] = array('name' => fullname($user),
-                                        'link' => "$CFG->wwwroot/user/view.php?id=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => $blogstring,
-                                        'link' => "index.php?filtertype=user&amp;filterselect=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => format_string($postobject->subject), 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
 
-                } else if ($tagid || !empty($tag)) {
-                    $navlinks[] = array('name' => fullname($user),
-                                        'link' => "$CFG->wwwroot/user/view.php?id=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => $blogstring,
-                                        'link' => "index.php?filtertype=user&amp;filterselect=$filterselect",
+if(!empty($tagid)) {
+    $tagrec = $DB->get_record('tag', array('id'=>$tagid));
+    $navlinks[] = array('name' => $tagrec->name,
+        'link' => "index.php",
                                         'type' => 'misc');
-                    $navlinks[] = array('name' => "$tagstring: $taginstance->name", 'link' => null, 'type' => 'misc');
-                    $navigation = build_navigation($navlinks);
+                }
 
+if(isset($cm)) {
+    $navigation = build_navigation($navlinks, $cm);
                 } else {
-                    $navlinks[] = array('name' => fullname($user),
-                                        'link' => "$CFG->wwwroot/user/view.php?id=$filterselect",
-                                        'type' => 'misc');
-                    $navlinks[] = array('name' => $blogstring, 'link' => null, 'type' => 'misc');
                     $navigation = build_navigation($navlinks);
                 }
-                print_header("$SITE->shortname: $blogstring", $SITE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
-
-            }
-        break;
 
-        default:
-            error ('Error unknown filtertype');
-        break;
-    }
+print_header("$COURSE->shortname: $blogstring", $COURSE->fullname, $navigation,'','',true,$PAGE->get_extra_header_string());
 
 
 // prints the tabs
-if ($filtertype=='user') {
-    $showroles = true;
-} else {
-    $showroles = false;
-}
+$showroles = !empty($userid);
 $currenttab = 'blogs';
 
+$user = $USER;
 require_once($CFG->dirroot .'/user/tabs.php');
 
 
@@ -253,7 +184,7 @@
 
 /// The left column ...
 if (blocks_have_content($pageblocks, BLOCK_POS_LEFT) || $editing) {
-    print '<td style="vertical-align: top; width: '. $preferred_width_left .'px;" id="left-column">' . "\n";
+    print '<td style="vertical-align: top; width: '. $preferredwidthleft .'px;" id="left-column">' . "\n";
     print '<!-- Begin left side blocks -->' . "\n";
     print_container_start();
     blocks_print_group($PAGE, $pageblocks, BLOCK_POS_LEFT);
Index: blog/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/index.php,v
retrieving revision 1.44
diff -u -a -w -b -B -r1.44 index.php
--- blog/index.php	24 Jul 2008 04:59:29 -0000	1.44
+++ blog/index.php	17 Aug 2008 22:32:06 -0000
@@ -13,15 +13,31 @@
 $id           = optional_param('id', 0, PARAM_INT);
 $start        = optional_param('formstart', 0, PARAM_INT);
 $userid       = optional_param('userid', 0, PARAM_INT);
+$postid       = optional_param('postid', 0, PARAM_INT);
+$groupid      = optional_param('groupid', 0, PARAM_INT);
+$modid        = optional_param('modid', 0, PARAM_INT);
 $tag          = optional_param('tag', '', PARAM_NOTAGS);
 $tagid        = optional_param('tagid', 0, PARAM_INT);
-$postid       = optional_param('postid', 0, PARAM_INT);
-$filtertype   = optional_param('filtertype', '', PARAM_ALPHA);
-$filterselect = optional_param('filterselect', 0, PARAM_INT);
-
 $edit         = optional_param('edit', -1, PARAM_BOOL);
 $courseid     = optional_param('courseid', 0, PARAM_INT); // needed for user tabs and course tracking
 
+//correct tagid if a text tag is provided as a param
+if(!empty($tag)) {  //text tag parameter takes precedence
+   if ($tagrec = $DB->get_record_sql("SELECT * FROM {tag} WHERE name LIKE ?", array($tag))) {
+      $tagid = $tagrec->id;
+   } else {
+      unset($tagid);
+   }
+}
+
+//add courseid if modid or groupid is specified
+if(!empty($modid) and empty($courseid)) {
+    $courseid = $DB->get_field('course_modules', 'course', array('id'=>$modid));
+}
+
+if(!empty($groupid) and empty($courseid)) {
+    $courseid = $DB->get_field('groups', 'courseid', array('id'=>$groupid));
+}
 
 if (empty($CFG->bloglevel)) {
     print_error('blogdisable', 'blog');
@@ -35,33 +51,31 @@
     $SESSION->blog_editing_enabled = $edit;
 }
 
-if (empty($filtertype)) {
-    if ($userid) {    // default to user if specified
-        $filtertype = 'user';
-        $filterselect = $userid;
-    } else if (has_capability('moodle/blog:view', $sitecontext) and $CFG->bloglevel > BLOG_USER_LEVEL) {
+if (!$userid and has_capability('moodle/blog:view', $sitecontext) and $CFG->bloglevel > BLOG_USER_LEVEL) {
         if ($postid) {
-            $filtertype = 'user';
             if (!$postobject = $DB->get_record('post', array('module'=>'blog', 'id'=>$postid))) {
                 print_error('nosuchentry', 'blog');
             }
-            $filterselect = $postobject->userid;
-        } else {
-            $filtertype = 'site';
-            $filterselect = '';
+        $userid = $postobject->userid;
         }
-    } else {
+} else if(!$userid) {
         // user might have capability to write blogs, but not read blogs at site level
         // users might enter this url manually without parameters
-        $filtertype = 'user';
-        $filterselect = $USER->id;
-    }
+        $userid = $USER->id;
 }
 /// check access and prepare filters
 
-switch ($filtertype) {
+if(!empty($modid)) {  //check mod access
+    if ($CFG->bloglevel < BLOG_COURSE_LEVEL) {
+        print_error(get_string('nocourseblogs', 'blog'));
+    }
+    if (!$mod = $DB->get_record('course_modules', array('id' => $modid))) {
+        print_error(get_string('invalidmodid', 'blog'));
+    }
+    $courseid = $mod->course;
+}
 
-    case 'site':
+if((empty($courseid) ? true : $courseid == SITEID) and empty($userid)) {  //check site access
         if ($CFG->bloglevel < BLOG_SITE_LEVEL) {
             print_error('siteblogdisable', 'blog');
         }
@@ -71,13 +85,16 @@
         if (!has_capability('moodle/blog:view', $sitecontext)) {
             print_error('cannotviewsiteblog', 'blog');
         }
-    break;
 
-    case 'course':
-        if ($CFG->bloglevel < BLOG_COURSE_LEVEL) {
-            print_error('courseblogdisable', 'blog');
+    $COURSE = $DB->get_record('course', array('format'=>'site'));
+    $courseid = $COURSE->id;
         }
-        if (!$course = $DB->get_record('course', array('id'=>$filterselect))) {
+
+if(!empty($courseid)) {
+//    if ($CFG->bloglevel < BLOG_COURSE_LEVEL) {
+//        print_error('courseblogdisable', 'blog');
+//    }
+    if (!$course = $DB->get_record('course', array('id'=>$courseid))) {
             print_error('invalidcourseid');
         }
         $courseid = $course->id;
@@ -86,40 +103,41 @@
         if (!has_capability('moodle/blog:view', $coursecontext)) {
             print_error('cannotviewcourseblog', 'blog');
         }
-    break;
+} else {
+    $coursecontext = get_context_instance(CONTEXT_COURSE, SITEID);
+}
 
-    case 'group':
+if(!empty($groupid)) {
         if ($CFG->bloglevel < BLOG_GROUP_LEVEL) {
             print_error('groupblogdisable', 'blog');
         }
         
         // fix for MDL-9268
-        if (! $group = groups_get_group($filterselect)) { //TODO:check.
-            print_error('invalidgroupid');
+    if (! $group = groups_get_group($groupid)) { //TODO:check.
+        print_error(get_string('invalidgroupid', 'blog'));
         }
         if (!$course = $DB->get_record('course', array('id'=>$group->courseid))) {
-            print_error('invalidcourseid');
+        print_error(get_string('invalidcourseid', 'blog'));
         }
         $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
         $courseid = $course->id;
         require_login($course);
         if (!has_capability('moodle/blog:view', $coursecontext)) {
-            print_error('cannotviewcourseorgroupblog', 'blog');
+        print_error(get_string('cannotviewcourseorgroupblog', 'blog'));
         }
         if (groups_get_course_groupmode($course) == SEPARATEGROUPS
           and !has_capability('moodle/site:accessallgroups', $coursecontext)) {
-            if (!groups_is_member($filterselect)) {
+        if (!groups_is_member($groupid)) {
                 print_error('notmemberofgroup');
             }
         }
+}
 
-    break;
-
-    case 'user':
+if(!empty($user)) {
         if ($CFG->bloglevel < BLOG_USER_LEVEL) {
             print_error('blogdisable', 'blog');
         }
-        if (!$user = $DB->get_record('user', array('id'=>$filterselect))) {
+    if (!$user = $DB->get_record('user', array('id'=>$userid))) {
             print_error('invaliduserid');
         }
         if ($user->deleted) {
@@ -129,43 +147,51 @@
             die;
         }
 
-        if ($USER->id == $filterselect) {
+    if ($USER->id == $userid) {
             if (!has_capability('moodle/blog:create', $sitecontext)
               and !has_capability('moodle/blog:view', $sitecontext)) {
                 print_error('donothaveblog', 'blog');
             }
         } else {
-            $personalcontext = get_context_instance(CONTEXT_USER, $filterselect);
+        $personalcontext = get_context_instance(CONTEXT_USER, $userid);
             if (!has_capability('moodle/blog:view', $sitecontext) 
               and !has_capability('moodle/user:readuserblogs', $personalcontext)) {
                 print_error('cannotviewuserblog', 'blog');
             }
-            if (!blog_user_can_view_user_post($filterselect)) {
+        if (!blog_user_can_view_user_post($userid)) {
                 print_error('cannotviewcourseblog', 'blog');
             }
         }
-        $userid = $filterselect;
-
-        if (!empty($courseid)) {
-            require_login($courseid);
-        }
-
-    break;
-
-    default:
-        print_error('incorrectblogfilter', 'blog');
-    break;
 }
 
 if (empty($courseid)) {
     $courseid = SITEID;
 }
 
+if(!empty($postid)) { 
+    $filters['post'] = $postid;
+}
+if(!empty($courseid)) {
+    $filters['course'] = $courseid;
+}
+if(!empty($modid)) {
+    $filters['mod'] = $modid;
+}
+if(!empty($groupid)) {
+    $filters['group'] = $groupid;
+}
+if(!empty($userid)) {
+    $filters['user'] = $userid;
+}
+if(!empty($tagid)) {
+    $filters['tag'] = $tagid;
+}
+
 include($CFG->dirroot .'/blog/header.php');
 
-blog_print_html_formatted_entries($postid, $filtertype, $filterselect, $tagid, $tag);
+blog_print_html_formatted_entries($filters);
 
-add_to_log($courseid, 'blog', 'view', 'index.php?filtertype='.$filtertype.'&amp;filterselect='.$filterselect.'&amp;postid='.$postid.'&amp;tagid='.$tagid.'&amp;tag='.$tag, 'view blog entry');
+add_to_log($courseid, 'blog', 'view', blog_get_blogs_url($filters), 'view blog entry');
 
 include($CFG->dirroot .'/blog/footer.php');
 
Index: blog/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/blog/lib.php,v
retrieving revision 1.100
diff -u -a -w -b -B -r1.100 lib.php
--- blog/lib.php	31 Jul 2008 22:15:31 -0000	1.100
+++ blog/lib.php	17 Aug 2008 22:32:07 -0000
@@ -70,9 +70,9 @@
      *
      *   $@param ...
      */
-    function blog_print_html_formatted_entries($postid, $filtertype, $filterselect, $tagid, $tag) {
+    function blog_print_html_formatted_entries($filters) {
 
-        global $CFG, $USER;
+        global $CFG, $USER, $PAGE;
 
         $blogpage  = optional_param('blogpage', 0, PARAM_INT);
         $bloglimit = optional_param('limit', get_user_preferences('blogpagesize', 10), PARAM_INT);
@@ -82,19 +82,26 @@
 
         $morelink = '<br />&nbsp;&nbsp;';
 
-        $totalentries = get_viewable_entry_count($postid, $bloglimit, $start, $filtertype, $filterselect, $tagid, $tag, $sort='created DESC');
-        $blogEntries = blog_fetch_entries($postid, $bloglimit, $start, $filtertype, $filterselect, $tagid, $tag, $sort='created DESC', true);
+        $blogEntries = blog_fetch_entries($filters, $sort='created DESC', $bloglimit, $start);
+        $totalentries = blog_get_viewable_entry_count($filters);
 
-        print_paging_bar($totalentries, $blogpage, $bloglimit, get_baseurl($filtertype, $filterselect), 'blogpage');
+        print_paging_bar($totalentries, $blogpage, $bloglimit, blog_get_blogs_url($filters), 'blogpage');
 
         if ($CFG->enablerssfeeds) {
-            blog_rss_print_link($filtertype, $filterselect, $tag);
+            blog_rss_print_link($filters);
         }
 
         if (has_capability('moodle/blog:create', $sitecontext)) {
             //the user's blog is enabled and they are viewing their own blog
+            $coursearg = '';
+            if(!empty($PAGE->filters['course'])) {
+                $coursearg = '&amp;courseid='.$PAGE->filters['course'];
+                if(!empty($PAGE->filters['mod'])) {
+                    $coursearg .= '&amp;modid='.$PAGE->filters['mod'];
+                }
+            }
             $addlink = '<div class="addbloglink">';
-            $addlink .= '<a href="'.$CFG->wwwroot .'/blog/edit.php?action=add'.'">'. get_string('addnewentry', 'blog').'</a>';
+            $addlink .= '<a href="'.$CFG->wwwroot .'/blog/edit.php?action=add'.$coursearg.'">'. get_string('addnewentry', 'blog').'</a>';
             $addlink .= '</div>';
             echo $addlink;
         }
@@ -103,11 +110,11 @@
 
             $count = 0;
             foreach ($blogEntries as $blogEntry) {
-                blog_print_entry($blogEntry, 'list', $filtertype, $filterselect); //print this entry.
+                blog_print_entry($blogEntry, 'list', $filters); //print this entry.
                 $count++;
             }
 
-            print_paging_bar($totalentries, $blogpage, $bloglimit, get_baseurl($filtertype, $filterselect), 'blogpage');
+            print_paging_bar($totalentries, $blogpage, $bloglimit, blog_get_blogs_url($filters), 'blogpage');
 
             if (!$count) {
                 print '<br /><div style="text-align:center">'. get_string('noentriesyet', 'blog') .'</div><br />';
@@ -140,7 +147,7 @@
      *     in its complete form (eg. archive page). If anything other than 'full'
      *     display the entry in its abbreviated format (eg. index page)
      */
-    function blog_print_entry($blogEntry, $viewtype='full', $filtertype='', $filterselect='', $mode='loud') {
+    function blog_print_entry($blogEntry, $viewtype='full', $filters=array(), $mode='loud') {
         global $USER, $CFG, $COURSE, $ME, $DB;
 
         $template['body'] = format_text($blogEntry->summary, $blogEntry->format);
@@ -170,9 +177,20 @@
 
         $user = $DB->get_record('user', array('id'=>$template['userid']));
 
+        //check to see if the post is unassociated with group/course level access
+        $unassociatedpost = false;
+        if(!empty($CFG->useassoc) && ($blogEntry->publishstate == 'group' || 
+                              $blogEntry->publishstate == 'course')) {
+            if(!$DB->record_exists('blog_association', array('blogid' => $blogEntry->id))) {
+                $unassociatedpost = true;
+            }
+        }
+
         /// Start printing of the blog
 
-        echo '<table cellspacing="0" class="forumpost blogpost blog'.$template['publishstate'].'" width="100%">';
+
+        echo '<table cellspacing="0" class="forumpost blogpost blog'.
+        ($unassociatedpost ? 'draft' : $template['publishstate']).'" width="100%">';
 
         echo '<tr class="header"><td class="picture left">';
         print_user_picture($user, SITEID, $user->picture);
@@ -201,10 +219,43 @@
             $attachedimages = '';
         }
 
+        //retrieve associations in case they're needed early
+        $blog_associations = $DB->get_records('blog_association', array('blogid' => $blogEntry->id));
+        //determine text for publish state
         switch ($template['publishstate']) {
             case 'draft':
                 $blogtype = get_string('publishtonoone', 'blog');
             break;
+            case 'course':
+                if(!empty($CFG->useassoc)) {
+                    $coursename = '';
+                    foreach($blog_associations as $assoc_rec) {  //find the associated course for the publishstate string
+                        $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid));
+                        if($context_rec->contextlevel != CONTEXT_COURSE) { //skip associations with something other than a course
+                            continue;
+                        }
+                        $coursename = $DB->get_field('course', 'shortname', array('id' => $context_rec->instanceid));
+                    }
+                    $blogtype = get_string('publishtocourseassocparam', 'blog', $coursename);
+                } else {
+                    $blogtype = get_string('publishtocourse', 'blog');
+                }
+            break;
+            case 'group':
+                if(!empty($CFG->useassoc)) {
+                    $coursename = '';
+                    foreach($blog_associations as $assoc_rec) {  //find the associated course for the publishstate string
+                        $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid));
+                        if($context_rec->contextlevel != CONTEXT_COURSE) { //skip associations with something other than a course
+                            continue;
+                        }
+                        $coursename = $DB->get_field('course', 'shortname', array('id' => $context_rec->instanceid));
+                    }
+                    $blogtype = get_string('publishtogroupassocparam', 'blog', $coursename);
+                } else {
+                    $blogtype = get_string('publishtogroup', 'blog');
+                }
+            break;
             case 'site':
                 $blogtype = get_string('publishtosite', 'blog');
             break;
@@ -234,13 +285,53 @@
             echo '</div>';
         }
 
+        //add associations
+        if ( !empty($CFG->useassoc) && $blog_associations) {
+            echo '<div clas="tags">';
+            $assoc_str = '';
+            foreach($blog_associations as $assoc_rec) {  //first find and show the associated course
+                $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid));
+                if($context_rec->contextlevel ==  CONTEXT_COURSE) { 
+                        $assoc_str .= '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$context_rec->instanceid.'">';
+                        $assoc_str .= '<img src="'.$CFG->pixpath.'/i/course.gif" border=0  alt="">';
+                        $assoc_str .= $DB->get_field('course', 'shortname', array('id' => $context_rec->instanceid));
+                        $assoc_str .= '</a>';
+                }
+            }
+            foreach($blog_associations as $assoc_rec) {  //now show each mod association
+                $context_rec = $DB->get_record('context', array('id' => $assoc_rec->contextid));
+                if($context_rec->contextlevel ==  CONTEXT_MODULE) {
+                        $modinfo = $DB->get_record('course_modules', array('id' => $context_rec->instanceid));
+                        $modname = $DB->get_field('modules', 'name', array('id' => $modinfo->module));
+                        $assoc_str .= ', ';
+                        $assoc_str .= '<a href="'.$CFG->wwwroot.'/mod/'.$modname.'/view.php?id='.$modinfo->id.'">';
+                        $assoc_str .= '<img src="'.$CFG->wwwroot.'/mod/'.$modname.'/icon.gif" border=0 alt="">';
+                        $assoc_str .= $DB->get_field($modname, 'name', array('id' => $modinfo->instance));
+                        $assoc_str .= '</a>';
+                }
+            }
+            echo get_string('associations', 'blog') . ': '. $assoc_str;
+            
+            echo '</div>';
+        }
+            
+            if($unassociatedpost) {
+                echo '<div class="noticebox">'.get_string('associationunviewable', 'blog').'</div>';
+            }
+
     /// Commands
 
         echo '<div class="commands">';
 
         if (blog_user_can_edit_post($blogEntry)) {
             echo '<a href="'.$CFG->wwwroot.'/blog/edit.php?action=edit&amp;id='.$blogEntry->id.'">'.$stredit.'</a>';
-            echo '| <a href="'.$CFG->wwwroot.'/blog/edit.php?action=delete&amp;id='.$blogEntry->id.'">'.$strdelete.'</a> | ';
+            if(!$DB->record_exists_sql('SELECT a.timedue, a.preventlate, a.emailteachers, a.var2, asub.grade
+                                          FROM {assignment} a, {assignment_submissions} as asub WHERE 
+                                          a.id = asub.assignment AND userid = '.$USER->id.' AND a.assignmenttype = \'blog\'
+                                          AND asub.data1 = \''.$blogEntry->id.'\'')) {
+                echo '| <a href="'.$CFG->wwwroot.'/blog/edit.php?action=delete&amp;id='.$blogEntry->id.'">'.$strdelete.'</a>';
+                echo ' | ';
+            }
         }
 
         echo '<a href="'.$CFG->wwwroot.'/blog/index.php?postid='.$blogEntry->id.'">'.get_string('permalink', 'blog').'</a>';
@@ -338,7 +429,23 @@
             $options = array ( 'draft' => get_string('publishtonoone', 'blog') );
         }
 
-        if ($CFG->bloglevel > BLOG_USER_LEVEL) {
+        if ($CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+            if(!empty($CFG->useassoc)) {
+                $options['group'] = get_string('publishtogroupassoc', 'blog');
+            } else {
+                $options['group'] = get_string('publishtogroup', 'blog');
+            } 
+        }
+
+        if ($CFG->bloglevel >= BLOG_COURSE_LEVEL) {
+            if(!empty($CFG->useassoc)) {
+                $options['course'] = get_string('publishtocourseassoc', 'blog');
+            } else {
+                $options['course'] = get_string('publishtocourse', 'blog');
+            } 
+        } 
+        
+        if ($CFG->bloglevel >= BLOG_SITE_LEVEL) {
             $options['site'] = get_string('publishtosite', 'blog');
         }
 
@@ -462,152 +569,220 @@
 
 
     /**
-     * Main filter function.
+     * Generates an SQL query for retrieving blog entries
+     *  @param array filters an array of filters (filtername => filtervalue) to narrow down results by
+     *  available filters:
+     *    post: id field of a specific post
+     *    course: id of a course that the posts must be associated with
+     *    mod: id of a course module that the posts must be associated with
+     *    user: id of a user who must be the author of a post
+     *    group: id of a group who the author must be a member of, and whose course must be associated with the post
+     *    tag: id of a tag that must be applied to the post
+     *    site: the entire site is searched
+     *  @param string sort field and direction for sorting results from the SQL statement
+     *  @param int userid id of the user fetching the posts (for permissions purposes)
+     *  @return array blog post objects matching the search criteria
      */
-    function blog_fetch_entries($postid='', $fetchlimit=10, $fetchstart='', $filtertype='', $filterselect='', $tagid='', $tag ='', $sort='lastmodified DESC', $limit=true) {
+    function blog_fetch_entries_sql($filters=array(), $sort='lastmodified DESC', $userid = false) {
         global $CFG, $USER, $DB;
 
-        /// the post table will be used for other things too
-        $typesql = "AND p.module = 'blog'";
-
-        /// set the tag id for searching
-        if ($tagid) {
-            $tag = $tagid;
-        } else if ($tag) {
-            if ($tagrec = $DB->get_record_sql("SELECT * FROM {tag} WHERE name LIKE ?", array($tag))) {
-                $tag = $tagrec->id;
-            } else {
-                $tag = -1;    //no records found
-            }
+        if(!$userid) {
+            $userid = $USER->id;
         }
 
-        // If we have specified an ID
-        // Just return 1 entry
+        // The query used to locate blog entries is complicated.  It will be built from the following components:
+        $requiredfields = "p.*,u.firstname,u.lastname,u.email";  // the SELECT clause
+        $tables = array('p' => 'post', 'u' => 'user');   // components of the FROM clause (table_id => table_name) 
+        $conditions = array('u.deleted = 0', 'p.userid = u.id', 'p.module = \'blog\'');  // components of the WHERE clause (conjunction)
 
-        if ($postid) {
-            if ($post = $DB->get_record('post', array('id'=>$postid))) {
 
-                if (blog_user_can_view_user_post($post->userid, $post)) {
+        // build up a clause for permission constraints
 
-                    if ($user = $DB->get_record('user', array('id'=>$post->userid))) {
-                        $post->email = $user->email;
-                        $post->firstname = $user->firstname;
-                        $post->lastname = $user->lastname;
-                    }
-                    $retarray[] = $post;
-                    return $retarray;
+        // fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs
+        // admins can see all blogs regardless of publish states, as described on the help page
+        if (has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_SYSTEM))) {
+            // don't add permission constraints
+        } else if(!empty($filters['user']) && 
+                  has_capability('moodle/user:readuserblogs', 
+                                 get_context_instance(CONTEXT_USER, (empty($filters['user']) ? 0 : $filters['user'])))) {
+            // don't add permission constraints
                 } else {
-                    return null;
+            if (isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM, SITEID), $userid, false)) {
+                $usergroups = '';
+                $usercourses = '';
+                $assocexists = $DB->record_exists('blog_association', array());  //dont check association records if there aren't any
+
+                foreach($DB->get_records('groups_members', array('userid' => $userid)) as $rec) { //find all groups the user is in
+                    $usergroups .= ($usergroups ? ', ' : '') . $rec->groupid;
+                }
+                foreach(get_my_courses($userid) as $course) {  //find all courses the user is in
+                    $usercourses .= ($usercourses ? ', ' : '') . $course->context->id;
                 }
 
-            } else { // bad postid
-                return null;
+                if(!empty($filter['course'])) { //optimization to make searches faster
+                    $filtercontext = get_context_instance(CONTEXT_COURSE, $filter['course']);
+                    if(!in_array($filtercontext->id, $usercourses)) {
+                        return '';
+                    }
+                    if(!empty($filter['group'])) {
+                        if(!in_array($filters['group'], $usergroups)) {
+                            return '';
+                        }
             }
         }
 
-        $params = array();
+                //begin permission sql clause
+                $permissionsql =  '(p.userid = '.$userid.' ';
 
-        if ($tag) {
-            $tagtablesql = ", {tag_instance} ti";
-            $tagquerysql = "AND ti.itemid = p.id AND ti.tagid = :tag AND ti.itemtype = 'post'";
-            $params['tag'] = $tag;
-        } else {
-            $tagtablesql = '';
-            $tagquerysql = '';
+                if($CFG->bloglevel >= BLOG_SITE_LEVEL) { // add permission to view site-level posts
+                    $permissionsql .= ' OR p.publishstate = \'site\' '; 
         }
 
-        if (isloggedin() && !has_capability('moodle/legacy:guest', get_context_instance(CONTEXT_SYSTEM), $USER->id, false)) {
-            $permissionsql = "AND (p.publishstate = 'site' OR p.publishstate = 'public' OR p.userid = :userid)";
-            $params['userid'] = $USER->id;
-        } else {
-            $permissionsql = "AND p.publishstate = 'public'";
+                if($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { // add permission to view global posts
+                    $permissionsql .= ' OR p.publishstate = \'public\' ';
         }
 
-        // fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs
-        // admins can see all blogs regardless of publish states, as described on the help page
-        if (has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_SYSTEM))) {
-            $permissionsql = '';
-        } else if ($filtertype=='user' && has_capability('moodle/user:readuserblogs', get_context_instance(CONTEXT_USER, $filterselect))) {
-            $permissionsql = '';
+                if(empty($CFG->useassoc)) {  //permission rules when associations are not activated...
+                    // insure viewer shares *any* course/group with the poster
+                    if($usergroups and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+                        $tables['gm'] = 'groups_members';
+                        $permissionsql .= ' OR (p.publishstate IN (\'group\', \'course\', \'public\', \'site\') '.
+                                          '     AND gm.userid = p.userid AND gm.groupid IN ('.$usergroups.'))';
+                    }
+                    if($usercourses and $CFG->bloglevel >= BLOG_COURSE_LEVEL) {
+                        $tables['ra'] = 'role_assignments';
+                        $permissionsql .= ' OR (p.publishstate IN (\'course\', \'public\', \'site\') '.
+                                          '     AND p.userid = ra.userid AND ra.contextid IN ('.$usercourses.'))';
+                    }
+                } else if($assocexists) { // permission rules when associations are activated...
+                    // insure viewer has access to the associated course (if course or group level access is used)
+                    if($usercourses and $CFG->bloglevel >= BLOG_COURSE_LEVEL) { 
+                        $tables['ba'] = 'blog_association';
+                        $permissionsql .=' OR (p.publishstate = \'course\' AND p.id = ba.blogid AND ba.contextid IN ('.$usercourses.'))';
+                    }
+                    if($usergroups and $CFG->bloglevel >= BLOG_GROUP_LEVEL) {
+                        $tables['gma'] = 'groups_members';
+                        $tables['gmb'] = 'groups_members';
+                        $tables['ba'] = 'blog_association';
+                        $permissionsql .= ' OR (p.publishstate = \'group\' AND p.id = ba.blogid AND ba.contextid IN ('.$usercourses.')
+                                        AND gma.groupid = gmb.groupid AND gma.userid = '.$userid.' AND gmb.userid = p.userid) ';
+                    }
+                }
+                $permissionsql .= ') ';   //close permissions sql clause
+            } else {  // default is access to public posts
+                $permissionsql = "p.publishstate = 'public'";
+            }
+            $conditions[] = $permissionsql;  //add permission constraints
         }
-        /****************************************
-         * depending on the type, there are 4   *
-         * different possible sqls              *
-         ****************************************/
 
-        $requiredfields = "p.*, u.firstname,u.lastname,u.email";
 
-        if ($filtertype == 'course' && $filterselect == SITEID) {  // Really a site
-            $filtertype = 'site';
+        // If a specific post id is specified, return a simple query with the permission sql
+        if (!empty($filters['post'])) {
+            $conditions[] = 'p.id = '.$filters['post'];
+
+            $tablessql = '';  // build up the FROM clause
+            foreach($tables as $tablename => $table) {
+                $tablessql .= ($tablessql ? ', ' : '').'{'.$table.'} '.$tablename;
         }
 
-        switch ($filtertype) {
+            return 'SELECT '.$requiredfields.' FROM '.$tablessql.' WHERE '.implode(' AND ', $conditions).' GROUP BY p.id ORDER BY '. $sort;
+        }
 
-            case 'site':
+        //add conditions for tag filter
+        if (!empty($filters['tag'])) {
+            $tables['ti'] = 'tag_instance'; 
+            $conditions[] = 'ti.itemid = p.id';
+            $conditions[] = 'ti.tagid = '.$filters['tag'];
+            $conditions[] = 'ti.itemtype = \'post\'';
+        }
 
-                $SQL = "SELECT $requiredfields
-                          FROM {post} p, {user} u $tagtablesql
-                         WHERE p.userid = u.id $tagquerysql
-                               AND u.deleted = 0
-                               $permissionsql $typesql";
+        //fix course filter if the course is really the site
+        if (!empty($filters['course'])) {
+            if($filters['course'] == SITEID) {  // Really a site
+                $filters['site'] = true;
+                unset($filters['course']);
+            }
+        }
 
-            break;
+        if(!empty($filters['site'])) {  //view posts for the whole site
+            //no constraints to add in this case
+        }
 
-            case 'course':
-                // all users with a role assigned
-                $context = get_context_instance(CONTEXT_COURSE, $filterselect);
+        if(!empty($filters['mod'])) {  //only view posts associated with a particular mod
+            $context = get_context_instance(CONTEXT_MODULE, $filters['mod']);
+            $tables['bamod'] = 'blog_association';     
+            $conditions[] = 'p.id = bamod.blogid';
+            $conditions[] = 'bamod.contextid = '.$context->id;
+        }
+
+        if(!empty($filters['course'])) {  // view posts for all members of a course
+            $tables['ra'] = 'role_assignments';
+            $context = get_context_instance(CONTEXT_COURSE, $filters['course']);
 
                 // MDL-10037, hidden users' blogs should not appear
-                if (has_capability('moodle/role:viewhiddenassigns', $context)) {
-                    $hiddensql = '';
-                } else {
-                    $hiddensql = 'AND ra.hidden = 0';
+            if (!has_capability('moodle/role:viewhiddenassigns', $context)) {
+                $conditions[] = 'ra.hidden = 0';
                 }
 
-                $SQL = "SELECT $requiredfields
-                          FROM {post} p, {user} u, {role_assignments} ra $tagtablesql
-                         WHERE p.userid = ra.userid $tagquerysql
-                               AND ra.contextid ".get_related_contexts_string($context)."
-                               AND u.id = p.userid
-                               AND u.deleted = 0
-                               $hiddensql $permissionsql $typesql";
-
-            break;
+            $conditions[] = 'p.userid = ra.userid';
+            $conditions[] = 'ra.contextid '.get_related_contexts_string($context);
+            if(!empty($CFG->useassoc) && empty($filters['mod'])) {  // only show blog entries associated with this course
+                $tables['ba'] = 'blog_association';     
+                $conditions[] = 'p.id = ba.blogid';
+                $conditions[] = 'ba.contextid = '.$context->id;
+            } 
+        }
 
-            case 'group':
+        if(!empty($filters['group'])) {  // view posts for all members of a group
+            $tables['gm'] = 'groups_members';
+            $conditions[] = 'p.userid = gm.userid';
+            $conditions[] = 'gm.groupid = '.$filters['group'];
+            if(!empty($CFG->useassoc)) {  // only show blog entries associated with this course
+                $tables['ba'] = 'blog_association';     
+                $course_context = get_context_instance(CONTEXT_COURSE, $DB->get_field('groups', 'courseid', array('id' => $filters['group'])));
+                $conditions[] = 'gm.groupid = '.$filters['group'];
+                $conditions[] = 'ba.contextid = '.$course_context->id;
+                $conditions[] = 'ba.blogid = p.id';
+            }
+        }
 
-                $SQL = "SELECT $requiredfields
-                          FROM {post} p, {user} u, {groups_members} gm $tagtablesql
-                         WHERE p.userid = gm.userid AND u.id = p.userid $tagquerysql
-                               AND gm.groupid = :groupid
-                               AND u.deleted = 0
-                               $permissionsql $typesql";
-                $params['groupid'] = $filterselect;
-            break;
+        if(!empty($filters['user'])) {  // view posts for a single user
+            $conditions[] = 'u.id = '.$filters['user'];
+        }
 
-            case 'user':
+        $tablessql = '';  // build up the FROM clause
+        foreach($tables as $tablename => $table) {
+            $tablessql .= ($tablessql ? ', ' : '').'{'.$table.'} '.$tablename;
+        }
 
-                $SQL = "SELECT $requiredfields
-                          FROM {post} p, {user} u $tagtablesql
-                         WHERE p.userid = u.id $tagquerysql
-                               AND u.id = :uid
-                               AND u.deleted = 0
-                               $permissionsql $typesql";
-               $params['uid'] = $filterselect;
-            break;
+        return 'SELECT '.$requiredfields.' FROM '.$tablessql.' WHERE '.implode(' AND ', $conditions).' GROUP BY p.id ORDER BY '. $sort;
         }
 
-        $limitfrom = 0;
-        $limitnum = 0;
+    /**
+     * retrieves a set of blog posts matching the search criteria provided
+     *  @param array filters an array of filters (filtername => filtervalue) to narrow down results by
+     *  available filters:
+     *    post: id field of a specific post
+     *    course: id of a course that the posts must be associated with
+     *    mod: id of a course module that the posts must be associated with
+     *    user: id of a user who must be the author of a post
+     *    group: id of a group who the author must be a member of, and whose course must be associated with the post
+     *    tag: id of a tag that must be applied to the post
+     *    site: the entire site is searched
+     *  @param string sort field and direction for sorting results from the SQL statement
+     *  @param int fetchlimit the maximum number of blog entries to return
+     *  @param int fetchstart the number of results to skip
+     *  @return array blog post objects matching the search criteria
+     */
+    function blog_fetch_entries($filters=array(), $sort='lastmodified DESC', $fetchlimit=0, $fetchstart=0) {
+        global $DB;
 
-        if ($fetchstart !== '' && $limit) {
-            $limitfrom = $fetchstart;
-            $limitnum = $fetchlimit;
+        $SQL = blog_fetch_entries_sql($filters, $sort);
+        if(!$SQL) {
+            return array();
         }
 
-        $orderby = "ORDER BY $sort";
-
-        $records = $DB->get_records_sql("$SQL $orderby", $params, $limitfrom, $limitnum);
+        $records = $DB->get_records_sql($SQL, array(), $fetchstart, $fetchlimit);
 
         if (empty($records)) {
             return array();
@@ -616,64 +791,59 @@
         return $records;
     }
 
-
     /**
-     * get the count of viewable entries, easiest way is to count blog_fetch_entries
-     * this is used for print_paging_bar
-     * this is not ideal, but because of the UNION in the sql in blog_fetch_entries,
-     * it is hard to use $DB->count_records_sql
+     * retrieves the number of blog posts matching the search criteria provided
+     *  @param array filters an array of filters (filtername => filtervalue) to narrow down results by
+     *  available filters:
+     *    post: id field of a specific post
+     *    course: id of a course that the posts must be associated with
+     *    mod: id of a course module that the posts must be associated with
+     *    user: id of a user who must be the author of a post
+     *    group: id of a group who the author must be a member of, and whose course must be associated with the post
+     *    tag: id of a tag that must be applied to the post
+     *    site: the entire site is searched
+     *  @return int the number of entries matching the search criteria
      */
-    function get_viewable_entry_count($postid='', $fetchlimit=10,
-                $fetchstart='', $filtertype='', $filterselect='', $tagid='',
-                $tag ='', $sort='lastmodified DESC') {
-
-        $blogEntries = blog_fetch_entries($postid, $fetchlimit,
-                $fetchstart, $filtertype, $filterselect, $tagid, $tag,
-                $sort='lastmodified DESC', false);
-
-        return count($blogEntries);
-    }
-
-
-    /// Find the base url from $_GET variables, for print_paging_bar
-    function get_baseurl($filtertype, $filterselect) {
-
-        $getcopy  = $_GET;
-
-        unset($getcopy['blogpage']);
-
-        $strippedurl = strip_querystring(qualified_me());
-        if(!empty($getcopy)) {
-            $first = false;
-            $querystring = '';
-            foreach($getcopy as $var => $val) {
-                if(!$first) {
-                    $first = true;
-                    if ($var != 'filterselect' && $var != 'filtertype') {
-                        $querystring .= '?'.$var.'='.$val;
-                        $hasparam = true;
-                    } else {
-                        $querystring .= '?';
-                    }
-                } else {
-                    if ($var != 'filterselect' && $var != 'filtertype') {
-                    $querystring .= '&amp;'.$var.'='.$val;
-                    $hasparam = true;
-                    }
-                }
-            }
-            if (isset($hasparam)) {
-                $querystring .= '&amp;';
-            } else {
-                $querystring = '?';
-            }
-        } else {
-            $querystring = '?';
+    function blog_get_viewable_entry_count($filters=array()) {
+        global $DB;
+        $SQL = blog_fetch_entries_sql($filters);
+
+        //cut out the select statement and the group by and order by statements:
+        $chunks = split('(FROM)|(GROUP)', $SQL);  //the middle chunk (id: 1) is the one we want
+        //the following groups all rows together, since all 'module' values will be 'blog'
+        $SQL = 'SELECT p.id FROM ' . $chunks[1] . ' GROUP BY p.id';  
+        if(!$SQL) {
+            return 0;
+        }
+        //count records relys on GROUP, and since we're already using GROUP to narrow down results, 
+        //we cant use count_records here.  Instead, we'll only retrieve something small (the id), and 
+        //just count the results.  There may be a more elegant solution for this.  
+        return count($DB->get_records_sql($SQL));
         }
 
-        return strip_querystring(qualified_me()) . $querystring. 'filtertype='.
-                $filtertype.'&amp;filterselect='.$filterselect.'&amp;';
-
+    /**
+     * generates the url of the page displaying entries matching the search criteria
+     *  @param array filters an array of filters (filtername => filtervalue) to narrow down results by
+     *  available filters:
+     *    post: id field of a specific post
+     *    course: id of a course that the posts must be associated with
+     *    mod: id of a course module that the posts must be associated with
+     *    user: id of a user who must be the author of a post
+     *    group: id of a group who the author must be a member of, and whose course must be associated with the post
+     *    tag: id of a tag that must be applied to the post
+     *    site: the entire site is searched
+     *  @return string the url of the page displaying entries matching the search criteria
+     */
+    function blog_get_blogs_url($filters) {
+        global $CFG;
+        return $CFG->wwwroot.'/blog/index.php?'.
+            (empty($filters['course']) ? '' : 'courseid='.$filters['course'].'&amp;').
+            (empty($filters['mod']) ? '' : 'modid='.$filters['mod'].'&amp;').
+            (empty($filters['group']) ? '' : 'groupid='.$filters['group'].'&amp;').
+            (empty($filters['user']) ? '' : 'userid='.$filters['user'].'&amp;').
+            (empty($filters['post']) ? '' : 'postid='.$filters['post'].'&amp;').
+            (empty($filters['tag']) ? '' : 'tagid='.$filters['tag'].'&amp;').
+            (empty($filters['tagtext']) ? '' : 'tag='.$filters['tagtext']);
     }
 
     /**
@@ -687,4 +857,40 @@
                                        FROM {post}
                                       WHERE module = 'blog' AND courseid = 0");
     }
+    
+
+    /**
+     * add a single association for a blog entry
+     * @param int blogid - id of blog entry
+     * @param int contextid - id of context to associate with the blog entry
+     */
+    function blog_add_association($blogid, $contextid) {
+        global $DB;
+    
+        $assoc_object = new StdClass;
+        $assoc_object->contextid = $contextid;
+        $assoc_object->blogid = $blogid;
+        $DB->insert_record('blog_association', $assoc_object);
+    }
+
+    /**
+     * remove all associations for a blog post
+     * @param int blogid - id of the blog post
+     */
+    function blog_remove_associations_for_post($blogid) {
+        global $DB;
+        $DB->delete_records('blog_association', array('blogid' => $blogid));
+    }
+
+    /** 
+     * remove all associations for the blog posts of a particular user
+     * @param int userid - id of user whose blog associations will be deleted
+     */
+    function blog_remove_associations_for_user($userid) {
+         global $DB;
+         foreach(blog_fetch_entries(array('user' => $userid), 'lasmodified DESC') as $post) {
+             blog_remove_associations_for_post($post->id);
+         }
+     }
+
 ?>
Index: course/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/course/lib.php,v
retrieving revision 1.612
diff -u -a -w -b -B -r1.612 lib.php
--- course/lib.php	8 Aug 2008 05:25:54 -0000	1.612
+++ course/lib.php	17 Aug 2008 22:32:09 -0000
@@ -2355,6 +2355,7 @@
 function delete_course_module($id) {
     global $CFG, $DB;
     require_once($CFG->libdir.'/gradelib.php');
+    require_once($CFG->dirroot.'/blog/lib.php');
 
     if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) {
         return true;
@@ -2374,7 +2375,9 @@
         }
 
     }
-    return $DB->delete_records('course_modules', array('id'=>$cm->id));
+    $context = get_context_instance(CONTEXT_MODULE, $id);
+    return $DB->delete_records('course_modules', array('id'=>$cm->id)) &&
+           $DB->delete_records('blog_association', array('contextid'=>$context->id));
 }
 
 function delete_mod_from_section($mod, $section) {
Index: lang/en_utf8/admin.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/admin.php,v
retrieving revision 1.219
diff -u -a -w -b -B -r1.219 admin.php
--- lang/en_utf8/admin.php	16 Aug 2008 12:16:02 -0000	1.219
+++ lang/en_utf8/admin.php	17 Aug 2008 22:32:11 -0000
@@ -782,6 +782,8 @@
 $string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.<br /><em>PHP cURL extension is highly recommended.</em>';
 $string['xmlrpcrecommended'] = 'Installing the optional xmlrpc extension is useful for Moodle Networking functionality.';
 $string['xmlstrictheaders'] = 'XML strict headers';
+$string['useassoc'] = 'Enable associations';
+$string['configuseassoc'] = 'Should users be able to organize their blog by associating entries with courses and course modules?';
 $string['ziprequired'] = 'The Zip PHP extension is now required by Moodle, info-ZIP binaries or PclZip library are not used anymore.';
 
 ?>
Index: lang/en_utf8/assignment.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/assignment.php,v
retrieving revision 1.28
diff -u -a -w -b -B -r1.28 assignment.php
--- lang/en_utf8/assignment.php	11 Aug 2008 15:31:55 -0000	1.28
+++ lang/en_utf8/assignment.php	17 Aug 2008 22:32:11 -0000
@@ -132,6 +132,7 @@
 $string['typeonline'] = 'Online text';
 $string['typeupload'] = 'Advanced uploading of files';
 $string['typeuploadsingle'] = 'Upload a single file';
+$string['typeblog'] = 'Blog post';
 $string['unfinalize'] = 'Revert to draft';
 $string['unfinalizeerror'] = 'An error occurred and that submission could not be reverted to draft';
 $string['uploadbadname'] = 'This filename contained strange characters and couldn\'t be uploaded';
@@ -146,5 +147,6 @@
 $string['viewfeedback'] = 'View assignment grades and feedback';
 $string['viewsubmissions'] = 'View $a submitted assignments';
 $string['yoursubmission'] = 'Your submission';
-
+$string['maxpublishstate'] = 'Maximum visibility for blog entry before duedate';
+$string['selectblog'] = 'Select which blog entry you wish to submit';
 ?>
Index: lang/en_utf8/blog.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/blog.php,v
retrieving revision 1.26
diff -u -a -w -b -B -r1.26 blog.php
--- lang/en_utf8/blog.php	24 Jul 2008 04:59:29 -0000	1.26
+++ lang/en_utf8/blog.php	17 Aug 2008 22:32:11 -0000
@@ -67,5 +67,21 @@
 $string['viewsiteentries'] = 'View site entries';
 $string['wrongpostid'] = 'Wrong blog post id';
 $string['worldblogs'] = 'The world can read entries set to be world-accessible';
-
+$string['associations'] = 'Associations';
+$string['publishtocourse'] = 'Users sharing a course with you';
+$string['publishtogroup'] = 'Users sharing a group with you';
+$string['publishtocourseassoc'] = 'Members of the associated course';
+$string['publishtocourseassocparam'] = 'Members of $a';
+$string['publishtogroupassoc'] = 'Your group members in the associated course';
+$string['publishtogroupassocparam'] = 'Your group members in $a';
+$string['associationunviewable'] = 'This entry cannot be viewed by others until a course is associated with it or the \'Publish To\' field is changed';
+$string['mustassociatecourse'] = 'If you are publishing to course or group members, you must associate a course with this entry';
+$string['viewuserentries'] = 'View user entries';
+$string['viewmodentries'] = 'View module entries';
+$string['viewgroupentries'] = 'View group entries';
+$string['viewcourseblogs'] = 'View entries for course...';
+$string['viewmodblogs'] = 'View entries for module...';
+$string['viewgroupblogs'] = 'View entries for group...';
+$string['viewblogsfor'] = 'View all entries for...';
+$string['filterblogsby'] = 'Filter entries by...';
 ?>
Index: lib/accesslib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/accesslib.php,v
retrieving revision 1.510
diff -u -a -w -b -B -r1.510 accesslib.php
--- lib/accesslib.php	16 Aug 2008 12:16:05 -0000	1.510
+++ lib/accesslib.php	17 Aug 2008 22:32:16 -0000
@@ -2099,7 +2099,8 @@
     if ($context = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) {
         $result = $DB->delete_records('role_assignments', array('contextid'=>$context->id)) &&
                   $DB->delete_records('role_capabilities', array('contextid'=>$context->id)) &&
-                  $DB->delete_records('context', array('id'=>$context->id));
+                  $DB->delete_records('context', array('id'=>$context->id)) &&
+                  $DB->delete_records('blog_association', array('contextid'=>$context->id));
 
         // do not mark dirty contexts if parents unknown
         if (!is_null($context->path) and $context->depth > 0) {
Index: lib/db/install.xml
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/install.xml,v
retrieving revision 1.166
diff -u -a -w -b -B -r1.166 install.xml
--- lib/db/install.xml	15 Aug 2008 11:15:08 -0000	1.166
+++ lib/db/install.xml	17 Aug 2008 22:32:25 -0000
@@ -4,7 +4,21 @@
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
   <TABLES>
-    <TABLE NAME="config" COMMENT="Moodle configuration variables" NEXT="config_plugins">
+    <TABLE NAME="blog_association" COMMENT="associates blog posts with contexts" NEXT="config">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="contextid"/>
+        <FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="context to be associated with a blog entry" PREVIOUS="id" NEXT="blogid"/>
+        <FIELD NAME="blogid" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="blog entry being associated" PREVIOUS="contextid"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="contextidindex" UNIQUE="false" FIELDS="contextid" NEXT="blogidindex"/>
+        <INDEX NAME="blogidindex" UNIQUE="false" FIELDS="blogid" PREVIOUS="contextidindex"/>
+      </INDEXES>
+    </TABLE>
+    <TABLE NAME="config" COMMENT="Moodle configuration variables" PREVIOUS="blog_association" NEXT="config_plugins">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="name"/>
         <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="value"/>
@@ -717,7 +731,7 @@
         <FIELD NAME="rating" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="uniquehash" NEXT="format"/>
         <FIELD NAME="format" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="rating" NEXT="attachment"/>
         <FIELD NAME="attachment" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="attachment" PREVIOUS="format" NEXT="publishstate"/>
-        <FIELD NAME="publishstate" TYPE="char" LENGTH="20" NOTNULL="true" DEFAULT="draft" SEQUENCE="false" ENUM="true" ENUMVALUES="'draft', 'site', 'public'" PREVIOUS="attachment" NEXT="lastmodified"/>
+        <FIELD NAME="publishstate" TYPE="char" LENGTH="20" NOTNULL="true" DEFAULT="draft" SEQUENCE="false" ENUM="true" ENUMVALUES="'draft', 'site', 'public', 'group', 'course'" PREVIOUS="attachment" NEXT="lastmodified"/>
         <FIELD NAME="lastmodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="publishstate" NEXT="created"/>
         <FIELD NAME="created" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="lastmodified" NEXT="usermodified"/>
         <FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="created"/>
Index: lib/db/upgrade.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/upgrade.php,v
retrieving revision 1.228
diff -u -a -w -b -B -r1.228 upgrade.php
--- lib/db/upgrade.php	16 Aug 2008 12:16:08 -0000	1.228
+++ lib/db/upgrade.php	17 Aug 2008 22:32:25 -0000
@@ -620,6 +620,40 @@
         $dbman->change_field_type($table, $field);
         upgrade_main_savepoint($result, 2008081500);
     }
+    if ($result && $oldversion < 2008081300) {
+    /// Define table blog_association to be created
+        $table = new xmldb_table('blog_association');
+
+    /// Adding fields to table blog_association
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
+        $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
+        $table->add_field('blogid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
+    /// Adding keys to table blog_association
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $table->add_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
+        $table->add_key('blogid', XMLDB_KEY_FOREIGN, array('blogid'), 'post', array('id'));
+ 
+        if (!$dbman->table_exists($table)) {
+        /// Launch create table for blog_association
+            $dbman->create_table($table);
+        }
+
+
+    /// Main savepoint reached
+        upgrade_main_savepoint($result, 2008081300);
+    }   
+    if ($result && $oldversion < 2008081301) {
+
+    /// Changing list of values (enum) of field publishstate on table post to 'draft', 'site', 'public', 'group', 'course'
+        $table = new xmldb_table('post');
+        $field = new xmldb_field('publishstate', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, XMLDB_ENUM, array('draft', 'site', 'public', 'group', 'course'), 'draft', 'attachment');
+
+    /// Launch change of list of values for field publishstate
+        $dbman->change_field_enum($table, $field);
+
+    /// Main savepoint reached
+        upgrade_main_savepoint($result, 2008081301);
+    }
 
     if ($result && $oldversion < 2008081501) {
         $table = new xmldb_table('question');
Index: tag/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/tag/index.php,v
retrieving revision 1.29
diff -u -a -w -b -B -r1.29 index.php
--- tag/index.php	30 Jun 2008 09:04:09 -0000	1.29
+++ tag/index.php	17 Aug 2008 22:32:31 -0000
@@ -103,7 +103,7 @@
 if (has_capability('moodle/blog:view', $systemcontext)) {  // You have to see blogs obviously
 
     $count = 10;
-    if ($blogs = blog_fetch_entries('', $count, 0, 'site', '', $tag->id)) {
+    if ($blogs = blog_fetch_entries(array('tag'=>$tag->id)), $count) {
 
         print_box_start('generalbox', 'tag-blogs');
         $heading = get_string('relatedblogs', 'tag', $tagname);
@@ -129,7 +129,7 @@
         }
         echo '</ul>';
 
-        echo '<p class="moreblogs"><a href="'.$CFG->wwwroot.'/blog/index.php?filtertype=site&filterselect=0&tagid='.$tag->id.'">'.get_string('seeallblogs', 'tag', $tagname).'</a></p>';
+        echo '<p class="moreblogs"><a href="'.blog_get_blogs_url(array('tag'=>$tag->id)).'">'.get_string('seeallblogs', 'tag', $tagname).'</a></p>';
 
         print_box_end();
     }
Index: user/tabs.php
===================================================================
RCS file: /cvsroot/moodle/moodle/user/tabs.php,v
retrieving revision 1.60
diff -u -a -w -b -B -r1.60 tabs.php
--- user/tabs.php	13 Aug 2008 04:09:13 -0000	1.60
+++ user/tabs.php	17 Aug 2008 22:32:32 -0000
@@ -2,6 +2,9 @@
 /// This file to be included so we can assume config.php has already been included.
 /// We also assume that $user, $course, $currenttab have been set
 
+    require_once($CFG->dirroot.'/blog/lib.php');
+
+
     if (!isset($filtertype)) {
         $filtertype = '';
     }
@@ -39,7 +42,7 @@
                     get_string('participants'));
             }
 
-            $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=site&amp;',
+            $toprow[] = new tabobject('blogs', blog_get_blogs_url(array()),
                 get_string('blogs','blog'));
         }
 
@@ -56,11 +59,11 @@
             get_string('participants'));
 
         if ($CFG->bloglevel >= 3) {
-            $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=course&amp;filterselect='.$filterselect, get_string('blogs','blog'));
+            $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('course'=>$filterselect)), get_string('blogs','blog'));
         }
 
         if (has_capability('moodle/notes:manage', $coursecontext) || has_capability('moodle/notes:view', $coursecontext)) {
-            $toprow[] = new tabobject('notes', $CFG->wwwroot.'/notes/index.php?filtertype=course&amp;filterselect=' . $filterselect, get_string('notes', 'notes'));
+            $toprow[] = new tabobject('notes', blog_get_blogs_url(array('course'=>$filterselect)), get_string('notes', 'notes'));
         }
 
     /**************************************
@@ -77,7 +80,7 @@
                 get_string('participants'));
 
 
-            $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?filtertype=group&amp;filterselect='.$filterselect, get_string('blogs','blog'));
+            $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('group'=>$filterselect)), get_string('blogs','blog'));
         }
 
     /**************************************
@@ -168,7 +171,7 @@
             ) // able to read blogs in site or course context
         ) { //end if
 
-            $toprow[] = new tabobject('blogs', $CFG->wwwroot.'/blog/index.php?userid='.$user->id.'&amp;courseid='.$course->id, get_string('blog', 'blog'));
+            $toprow[] = new tabobject('blogs', blog_get_blogs_url(array('user'=>$user->id,'course'=>$course->id)), get_string('blog', 'blog'));
         }
 
         if (has_capability('moodle/notes:manage', $coursecontext) || has_capability('moodle/notes:view', $coursecontext)) {
Index: mod/assignment/type/blog/assignment.class.php
===================================================================
RCS file: mod/assignment/type/blog/assignment.class.php
diff -N mod/assignment/type/blog/assignment.class.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mod/assignment/type/blog/assignment.class.php	11 Aug 2008 09:11:15 -0000
@@ -0,0 +1,320 @@
+<?php 
+require_once($CFG->dirroot .'/blog/lib.php');
+require_once($CFG->libdir.'/formslib.php');
+
+
+/**
+ * Extend the base assignment class for offline assignments
+ *
+ */
+class assignment_blog extends assignment_base {
+
+    function assignment_blog($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
+        parent::assignment_base($cmid, $assignment, $cm, $course);
+        $this->type = 'blog';
+    }
+
+    function display_lateness($timesubmitted) {
+        return '';
+    }
+
+    function print_student_answer($userid, $return=false){
+        global $CFG, $DB;
+        if (!$submission = $this->get_submission($userid)) {
+            return '';
+        }
+    $post = $DB->get_record('post', array('id' => $submission->data1));
+        $ret = '<b>'.$post->subject.': </b><br>'.shorten_text(format_text($post->summary));
+    $ret .= '<a href="'.$CFG->wwwroot.'/blog/index.php?postid='.$post->id.'" target="_blank">Full Entry</a><br>';
+
+        return $ret;
+    }
+
+
+    function setup_elements(&$mform) {
+        $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
+        //$mform->addElement('select', 'var1', get_string('multiassoc', 'assignment'), $ynoptions);
+        //$mform->setHelpButton('var1', array('multiassoc', get_string('multiassoc', 'assignment'), 'assignment'));
+        //$mform->setDefault('var1', 0);
+        
+        $publishstates = array();
+        $i = 0;
+        foreach(blog_applicable_publish_states() as $state) $publishstates[$i++] = $state; 
+        $mform->addElement('select', 'var2', get_string('maxpublishstate', 'assignment'), $publishstates);
+        $mform->setDefault('var2', 0);
+    }
+
+    function prepare_new_submission($userid) {
+        $submission = new Object;
+        $submission->assignment   = $this->assignment->id;
+        $submission->userid       = $userid;
+        $submission->timecreated  = time(); // needed for offline assignments
+        $submission->timemodified = $submission->timecreated;
+        $submission->numfiles     = 0;
+        $submission->data1        = '';
+        $submission->data2        = '';
+        $submission->grade        = -1;
+        $submission->submissioncomment      = '';
+        $submission->format       = 0;
+        $submission->teacher      = 0;
+        $submission->timemarked   = 0;
+        $submission->mailed       = 0;
+        return $submission;
+    }
+
+    // needed for the timemodified override
+    function process_feedback() {
+        global $CFG, $USER, $DB;
+        require_once($CFG->libdir.'/gradelib.php');
+
+        if (!$feedback = data_submitted()) {      // No incoming data?
+            return false;
+        }
+
+        ///For save and next, we need to know the userid to save, and the userid to go
+        ///We use a new hidden field in the form, and set it to -1. If it's set, we use this
+        ///as the userid to store
+        if ((int)$feedback->saveuserid !== -1){
+            $feedback->userid = $feedback->saveuserid;
+        }
+
+        if (!empty($feedback->cancel)) {          // User hit cancel button
+            return false;
+        }
+
+        $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $feedback->userid);
+
+        // store outcomes if needed
+        $this->process_outcomes($feedback->userid);
+
+        $submission = $this->get_submission($feedback->userid, true);  // Get or make one
+
+        if (!$grading_info->items[0]->grades[$feedback->userid]->locked and
+            !$grading_info->items[0]->grades[$feedback->userid]->overridden) {
+
+            $submission->grade      = $feedback->grade;
+            $submission->submissioncomment    = $feedback->submissioncomment;
+            $submission->format     = $feedback->format;
+            $submission->teacher    = $USER->id;
+            $mailinfo = get_user_preferences('assignment_mailinfo', 0);
+            if (!$mailinfo) {
+                $submission->mailed = 1;       // treat as already mailed
+            } else {
+                $submission->mailed = 0;       // Make sure mail goes out (again, even)
+            }
+            $submission->timemarked = time();
+
+            unset($submission->data1);  // Don't need to update this.
+            unset($submission->data2);  // Don't need to update this.
+
+            if (empty($submission->timemodified)) {   // eg for offline assignments
+                $submission->timemodified = time();
+            }
+
+            if (! $DB->update_record('assignment_submissions', $submission)) {
+                return false;
+            }
+
+            // triger grade event
+            $this->update_grade($submission);
+
+            add_to_log($this->course->id, 'assignment', 'update grades',
+                       'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
+        }
+
+        return $submission;
+
+    }
+
+
+    function view() {
+
+        global $USER, $DB;
+
+        $edit  = optional_param('edit', 0, PARAM_BOOL);
+        $saved = optional_param('saved', 0, PARAM_BOOL);
+
+        $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
+        require_capability('mod/assignment:view', $context);
+
+        $submission = $this->get_submission();
+
+        //Guest can not submit nor edit an assignment (bug: 4604)
+        if (!has_capability('mod/assignment:submit', $context)) {
+            $editable = null;
+        } else {
+            $editable = $this->isopen();
+        }
+        $editmode = ($editable and $edit);
+
+        if ($editmode) {
+            //guest can not edit or submit assignment
+            if (!has_capability('mod/assignment:submit', $context)) {
+                print_error('guestnosubmit', 'assignment');
+            }
+        }
+
+        add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id);
+
+/// prepare form and process submitted data
+        $mform = new mod_assignment_blog_edit_form();
+        if($this->assignment->var1) {  //allow multiple associations
+            $mform->set_multiple_assoc();
+        }
+
+        $defaults = new object();
+       if($submission = $this->get_submission()) {
+            $defaults->selectblog = $submission->data1;
+        }
+        $defaults->id = $this->cm->id;
+
+        $mform->set_data($defaults);
+
+        if ($mform->is_cancelled()) {
+            redirect('view.php?id='.$this->cm->id);
+        }
+
+        if ($data = $mform->get_data()) {      // No incoming data?
+            if ($editable && $this->update_submission($data)) {
+                //TODO fix log actions - needs db upgrade
+                $submission = $this->get_submission();
+                add_to_log($this->course->id, 'assignment', 'upload',
+                        'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
+                $this->email_teachers($submission);
+                //redirect to get updated submission date and word count
+                redirect('view.php?id='.$this->cm->id.'&saved=1');
+            } else {
+                // TODO: add better error message
+                notify(get_string("error")); //submitting not allowed!
+            }
+        }
+
+/// print header, etc. and display form if needed
+        if ($editmode) {
+            $this->view_header(get_string('editmysubmission', 'assignment'));
+        } else {
+            $this->view_header();
+        }
+
+        $this->view_intro();
+
+        $this->view_dates();
+
+        if ($saved) {
+            notify(get_string('submissionsaved', 'assignment'), 'notifysuccess');
+        }
+
+        if (has_capability('mod/assignment:submit', $context)) {
+            print_simple_box_start('center', '70%', '', 0, 'generalbox', 'online');
+            if ($editmode) {
+                $mform->display();
+            } else {
+                if ($submission) {
+                    blog_print_entry($DB->get_record('post', array('id' => $submission->data1)));
+                } else if (!has_capability('mod/assignment:submit', $context)) { //fix for #4604
+                    echo '<div style="text-align:center">'. get_string('guestnosubmit', 'assignment').'</div>';
+                } else if ($this->isopen()) {    //fix for #4206
+                    echo '<div style="text-align:center">'.get_string('emptysubmission', 'assignment').'</div>';
+                }
+            }
+            print_simple_box_end();
+            if (!$editmode && $editable) {
+                echo "<div style='text-align:center'>";
+                print_single_button('view.php', array('id'=>$this->cm->id,'edit'=>'1'),
+                        get_string('editmysubmission', 'assignment'));
+                echo "</div>";
+            }
+
+        }
+
+        $this->view_feedback();
+
+        $this->view_footer();
+    }
+
+
+    function update_submission($data) {
+        global $CFG, $USER, $DB, $COURSE;
+
+        $submission = $this->get_submission($USER->id, true);
+
+        $update = new object();
+        $update->id           = $submission->id;
+        $update->data1        = $data->selectblog;
+        $update->timemodified = time();
+        
+        //enforce access restriction
+        $postaccess = -1;
+        $i=0;
+        $post = $DB->get_record('post', array('id' => $data->selectblog));
+        if(!$post) {
+            print_error('blognotfound', 'blog');
+        }
+        $publishstates = array();
+        foreach(blog_applicable_publish_states() as $state => $desc) {
+            if($state == $post->publishstate) {
+                $postaccess = $i;
+            }
+            $publishstates[$i++] = $state;
+        } 
+
+        if($this->assignment->var2 < $postaccess) {
+            $post->publishstate = $publishstates[$this->assignment->var2];
+            $DB->update_record('post', $post);
+        } 
+        
+        //force the user to have strict associations with this post
+        blog_remove_associations_for_post($post->id);  //remove all existing associations
+        //add assignment association
+        $assignmentmodid = $DB->get_field('modules', 'id', array('name' => 'assignment'));
+        $modcontext = get_context_instance(CONTEXT_MODULE, $DB->get_field('course_modules', 'id', 
+                                           array('module' => $assignmentmodid, 'instance' => $this->assignment->id))); 
+        blog_add_association($post->id, $modcontext->id);
+        //add course association
+        $coursecontext = get_context_instance(CONTEXT_COURSE, $DB->get_field('course_modules', 'course', 
+                                           array('module' => $assignmentmodid, 'instance' => $this->assignment->id))); 
+        blog_add_association($post->id, $coursecontext->id);
+        
+        if (!$DB->update_record('assignment_submissions', $update)) {
+            return false;
+        }
+        
+        $submission = $this->get_submission($USER->id);
+        $this->update_grade($submission);
+        return true;
+    }
+
+
+}
+
+class mod_assignment_blog_edit_form extends moodleform {
+    function definition() {
+        global $USER, $DB;
+        $mform =& $this->_form;
+
+        // visible elements
+        //$mform->addRule('text', get_string('required'), 'required', null, 'client');
+       
+        $blogentries = array();
+        foreach($DB->get_records('post', array('userid' => $USER->id)) as $rec) {
+            $blogentries[$rec->id] = userdate($rec->created) . ' - ' . $rec->summary;
+        }
+  
+        $mform->addElement('select', 'selectblog', get_string('selectblog', 'assignment'), $blogentries); 
+
+        // hidden params
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+
+        // buttons
+        $this->add_action_buttons();
+    }
+    
+    function set_multiple_assoc() {
+        $mform =& $this->_form;
+        $selectblog = $mform->getElement('selectblog');
+        $selectblog->setMultiple(true);
+    }
+}
+
+?>
