From e101286f8b543328ab4176f7885ab7ca9de16c19 Mon Sep 17 00:00:00 2001
From: Nathan Mares <nathan@catalyst-au.net>
Date: Fri, 13 Jul 2012 15:58:20 +1000
Subject: [PATCH 1/2] Only show activities in course completion status that a
 user has access to

---
 lib/completion/completion_criteria.php          |    6 +++++
 lib/completion/completion_criteria_activity.php |   25 +++++++++++++++++++++++
 lib/completionlib.php                           |    2 +
 3 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/lib/completion/completion_criteria.php b/lib/completion/completion_criteria.php
index 31f5187..8b05ee2 100644
--- a/lib/completion/completion_criteria.php
+++ b/lib/completion/completion_criteria.php
@@ -254,4 +254,10 @@ abstract class completion_criteria extends data_object {
 
         return $review !== $completion->is_complete();
     }
+
+
+    /* Return true if this criteria applies to the given user */
+    public function is_applicable($user) {
+        return true;
+    }
 }
diff --git a/lib/completion/completion_criteria_activity.php b/lib/completion/completion_criteria_activity.php
index 375c966..bdd0cc0 100644
--- a/lib/completion/completion_criteria_activity.php
+++ b/lib/completion/completion_criteria_activity.php
@@ -286,4 +286,29 @@ class completion_criteria_activity extends completion_criteria {
 
         return $details;
     }
+
+
+    /* Return true if this criteria applies to the given user */
+    public function is_applicable($userid) {
+        global $CFG, $DB;
+        //stolen from lib/modinfolib.php...
+        $cm = $DB->get_record('course_modules', array('id' => $this->moduleinstance));
+        $course = $DB->get_record('course', array('id' => $this->course));
+        $modcontext = get_context_instance(CONTEXT_MODULE, $this->moduleinstance);
+
+        // Check group membership. The grouping option makes the activity
+        // completely invisible as it does not apply to the user at all.
+        if (!empty($CFG->enablegroupmembersonly) and !empty($cm->groupmembersonly)
+                and !has_capability('moodle/site:accessallgroups', $modcontext, $userid)) {
+            // If the activity has 'group members only' and you don't have accessallgroups...
+            $modinfo = new course_modinfo($course, $userid);
+            $groups = $modinfo->get_groups($cm->groupingid);
+            if (empty($groups)) {
+                // ...and you don't belong to a group, then set it so you can't see/access it
+                return false;
+            }
+        }
+
+        return true;
+    }
 }
diff --git a/lib/completionlib.php b/lib/completionlib.php
index 4df3bc0..5c4d969 100644
--- a/lib/completionlib.php
+++ b/lib/completionlib.php
@@ -298,6 +298,8 @@ class completion_info {
         $completions = array();
 
         foreach ($criterion as $criteria) {
+            if (!$criteria->is_applicable($user_id)) continue;
+
             $params = array(
                 'course'        => $this->course_id,
                 'userid'        => $user_id,
-- 
1.7.5.4


From 6e80cb852e26828524ff640f1f7f7d35342d3376 Mon Sep 17 00:00:00 2001
From: Nathan Mares <nathan@catalyst-au.net>
Date: Mon, 16 Jul 2012 11:38:59 +1000
Subject: [PATCH 2/2] Make course completion calculate completion status
 calculate status correctly when using
 enablegroupmembersonly setting.

---
 lib/completion/cron.php        |   32 ++++++++++++++++++++++++++++++--
 pix/i/completion-manual-na.png |  Bin 0 -> 254 bytes
 report/completion/index.php    |    2 +-
 3 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 pix/i/completion-manual-na.png

diff --git a/lib/completion/cron.php b/lib/completion/cron.php
index 3645c06..22db7355 100644
--- a/lib/completion/cron.php
+++ b/lib/completion/cron.php
@@ -226,7 +226,7 @@ function completion_cron_criteria() {
  * Aggregate each user's criteria completions
  */
 function completion_cron_completions() {
-    global $DB;
+    global $DB, $CFG;
 
     if (debugging()) {
         mtrace('Aggregating completions');
@@ -235,6 +235,32 @@ function completion_cron_completions() {
     // Save time started
     $timestarted = time();
 
+    if ($CFG->enablegroupmembersonly) {
+        $joinsql = 'LEFT JOIN {modules} m
+             ON m.name = cr.module
+            LEFT JOIN {course_modules} cm
+             ON cm.id = cr.moduleinstance
+            AND cm.module = m.id
+            LEFT JOIN {groupings} gp
+             ON gp.id = cm.groupingid
+            LEFT JOIN {groupings_groups} gg
+             ON gg.groupingid = gp.id
+            LEFT JOIN {groups} g
+             ON g.id = gg.groupid
+            LEFT JOIN {groups_members} gm
+             ON gm.groupid = g.id
+            AND gm.userid = crc.userid';
+
+        $wheresql = 'AND (cm.groupmembersonly = 0
+            OR (cm.groupmembersonly = 1
+                AND gm.id IS NOT NULL
+            ))';
+
+    } else {
+        $joinsql = '';
+        $wheresql = '';
+    }
+
     // Grab all criteria and their associated criteria completions
     $sql = '
         SELECT DISTINCT
@@ -255,11 +281,13 @@ function completion_cron_completions() {
             {course_completion_crit_compl} cc
          ON cc.criteriaid = cr.id
         AND crc.userid = cc.userid
+        ' . $joinsql . '
         WHERE
             c.enablecompletion = 1
         AND crc.timecompleted IS NULL
         AND crc.reaggregate > 0
-        AND crc.reaggregate < :timestarted
+        AND crc.reaggregate <= :timestarted
+        ' . $wheresql . '
         ORDER BY
             course,
             userid
diff --git a/pix/i/completion-manual-na.png b/pix/i/completion-manual-na.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ef5c3a5cc6b0501fc5703b459b9399e68b06d07
GIT binary patch
diff --git a/report/completion/index.php b/report/completion/index.php
index 2b81884..c33f499 100644
--- a/report/completion/index.php
+++ b/report/completion/index.php
@@ -592,7 +592,7 @@ foreach ($progress as $user) {
 
             // Work out how it corresponds to an icon
             switch($state) {
-                case COMPLETION_INCOMPLETE : $completiontype='n'; break;
+                case COMPLETION_INCOMPLETE : $completiontype=($criterion->is_applicable($user->id) ? 'n' : 'na'); break;
                 case COMPLETION_COMPLETE : $completiontype='y'; break;
                 case COMPLETION_COMPLETE_PASS : $completiontype='pass'; break;
                 case COMPLETION_COMPLETE_FAIL : $completiontype='fail'; break;
-- 
1.7.5.4

