Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Condition main class.
19
 *
20
 * @package availability_group
21
 * @copyright 2014 The Open University
22
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace availability_group;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
/**
30
 * Condition main class.
31
 *
32
 * @package availability_group
33
 * @copyright 2014 The Open University
34
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class condition extends \core_availability\condition {
37
    /** @var array Array from group id => name */
38
    protected static $groupnames = array();
39
 
40
    /** @var int ID of group that this condition requires, or 0 = any group */
41
    protected $groupid;
42
 
43
    /**
44
     * Constructor.
45
     *
46
     * @param \stdClass $structure Data structure from JSON decode
47
     * @throws \coding_exception If invalid data structure.
48
     */
49
    public function __construct($structure) {
50
        // Get group id.
51
        if (!property_exists($structure, 'id')) {
52
            $this->groupid = 0;
53
        } else if (is_int($structure->id)) {
54
            $this->groupid = $structure->id;
55
        } else {
56
            throw new \coding_exception('Invalid ->id for group condition');
57
        }
58
    }
59
 
60
    public function save() {
61
        $result = (object)array('type' => 'group');
62
        if ($this->groupid) {
63
            $result->id = $this->groupid;
64
        }
65
        return $result;
66
    }
67
 
68
    public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
69
        $course = $info->get_course();
70
        $context = \context_course::instance($course->id);
71
        $allow = true;
72
        if (!has_capability('moodle/site:accessallgroups', $context, $userid)) {
73
            // Get all groups the user belongs to.
74
            $groups = $info->get_groups(0, $userid);
75
            if ($this->groupid) {
76
                $allow = in_array($this->groupid, $groups);
77
            } else {
78
                // No specific group. Allow if they belong to any group at all.
79
                $allow = $groups ? true : false;
80
            }
81
 
82
            // The NOT condition applies before accessallgroups (i.e. if you
83
            // set something to be available to those NOT in group X,
84
            // people with accessallgroups can still access it even if
85
            // they are in group X).
86
            if ($not) {
87
                $allow = !$allow;
88
            }
89
        }
90
        return $allow;
91
    }
92
 
93
    public function get_description($full, $not, \core_availability\info $info) {
94
        global $DB;
95
 
96
        if ($this->groupid) {
97
            // Need to get the name for the group. Unfortunately this requires
98
            // a database query. To save queries, get all groups for course at
99
            // once in a static cache.
100
            $course = $info->get_course();
101
            if (!array_key_exists($this->groupid, self::$groupnames)) {
102
                $coursegroups = $DB->get_records(
103
                        'groups', array('courseid' => $course->id), '', 'id, name');
104
                foreach ($coursegroups as $rec) {
105
                    self::$groupnames[$rec->id] = $rec->name;
106
                }
107
            }
108
 
109
            // If it still doesn't exist, it must have been misplaced.
110
            if (!array_key_exists($this->groupid, self::$groupnames)) {
111
                $name = get_string('missing', 'availability_group');
112
            } else {
113
                // Not safe to call format_string here; use the special function to call it later.
114
                $name = self::description_format_string(self::$groupnames[$this->groupid]);
115
            }
116
        } else {
117
            return get_string($not ? 'requires_notanygroup' : 'requires_anygroup',
118
                    'availability_group');
119
        }
120
 
121
        return get_string($not ? 'requires_notgroup' : 'requires_group',
122
                'availability_group', $name);
123
    }
124
 
125
    protected function get_debug_string() {
126
        return $this->groupid ? '#' . $this->groupid : 'any';
127
    }
128
 
129
    /**
130
     * Include this condition only if we are including groups in restore, or
131
     * if it's a generic 'same activity' one.
132
     *
133
     * @param int $restoreid The restore Id.
134
     * @param int $courseid The ID of the course.
135
     * @param base_logger $logger The logger being used.
136
     * @param string $name Name of item being restored.
137
     * @param base_task $task The task being performed.
138
     *
139
     * @return Integer groupid
140
     */
141
    public function include_after_restore($restoreid, $courseid, \base_logger $logger,
142
            $name, \base_task $task) {
143
        return !$this->groupid || $task->get_setting_value('groups');
144
    }
145
 
146
    public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name) {
147
        global $DB;
148
        if (!$this->groupid) {
149
            return false;
150
        }
151
        $rec = \restore_dbops::get_backup_ids_record($restoreid, 'group', $this->groupid);
152
        if (!$rec || !$rec->newitemid) {
153
            // If we are on the same course (e.g. duplicate) then we can just
154
            // use the existing one.
155
            if ($DB->record_exists('groups',
156
                    array('id' => $this->groupid, 'courseid' => $courseid))) {
157
                return false;
158
            }
159
            // Otherwise it's a warning.
160
            $this->groupid = -1;
161
            $logger->process('Restored item (' . $name .
162
                    ') has availability condition on group that was not restored',
163
                    \backup::LOG_WARNING);
164
        } else {
165
            $this->groupid = (int)$rec->newitemid;
166
        }
167
        return true;
168
    }
169
 
170
    public function update_dependency_id($table, $oldid, $newid) {
171
        if ($table === 'groups' && (int)$this->groupid === (int)$oldid) {
172
            $this->groupid = $newid;
173
            return true;
174
        } else {
175
            return false;
176
        }
177
    }
178
 
179
    /**
180
     * Wipes the static cache used to store grouping names.
181
     */
182
    public static function wipe_static_cache() {
183
        self::$groupnames = array();
184
    }
185
 
186
    public function is_applied_to_user_lists() {
187
        // Group conditions are assumed to be 'permanent', so they affect the
188
        // display of user lists for activities.
189
        return true;
190
    }
191
 
192
    public function filter_user_list(array $users, $not, \core_availability\info $info,
193
            \core_availability\capability_checker $checker) {
194
        global $CFG, $DB;
195
 
196
        // If the array is empty already, just return it.
197
        if (!$users) {
198
            return $users;
199
        }
200
 
201
        require_once($CFG->libdir . '/grouplib.php');
202
        $course = $info->get_course();
203
 
204
        // List users for this course who match the condition.
205
        if ($this->groupid) {
206
            $groupusers = groups_get_members($this->groupid, 'u.id', 'u.id ASC');
207
        } else {
208
            $groupusers = $DB->get_records_sql("
209
                    SELECT DISTINCT gm.userid
210
                      FROM {groups} g
211
                      JOIN {groups_members} gm ON gm.groupid = g.id
212
                     WHERE g.courseid = ?", array($course->id));
213
        }
214
 
215
        // List users who have access all groups.
216
        $aagusers = $checker->get_users_by_capability('moodle/site:accessallgroups');
217
 
218
        // Filter the user list.
219
        $result = array();
220
        foreach ($users as $id => $user) {
221
            // Always include users with access all groups.
222
            if (array_key_exists($id, $aagusers)) {
223
                $result[$id] = $user;
224
                continue;
225
            }
226
            // Other users are included or not based on group membership.
227
            $allow = array_key_exists($id, $groupusers);
228
            if ($not) {
229
                $allow = !$allow;
230
            }
231
            if ($allow) {
232
                $result[$id] = $user;
233
            }
234
        }
235
        return $result;
236
    }
237
 
238
    /**
239
     * Returns a JSON object which corresponds to a condition of this type.
240
     *
241
     * Intended for unit testing, as normally the JSON values are constructed
242
     * by JavaScript code.
243
     *
244
     * @param int $groupid Required group id (0 = any group)
245
     * @return stdClass Object representing condition
246
     */
247
    public static function get_json($groupid = 0) {
248
        $result = (object)array('type' => 'group');
249
        // Id is only included if set.
250
        if ($groupid) {
251
            $result->id = (int)$groupid;
252
        }
253
        return $result;
254
    }
255
 
256
    public function get_user_list_sql($not, \core_availability\info $info, $onlyactive) {
257
        global $DB;
258
 
259
        // Get enrolled users with access all groups. These always are allowed.
260
        list($aagsql, $aagparams) = get_enrolled_sql(
261
                $info->get_context(), 'moodle/site:accessallgroups', 0, $onlyactive);
262
 
263
        // Get all enrolled users.
264
        list ($enrolsql, $enrolparams) =
265
                get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
266
 
267
        // Condition for specified or any group.
268
        $matchparams = array();
269
        if ($this->groupid) {
270
            $matchsql = "SELECT 1
271
                           FROM {groups_members} gm
272
                          WHERE gm.userid = userids.id
273
                                AND gm.groupid = " .
274
                    self::unique_sql_parameter($matchparams, $this->groupid);
275
        } else {
276
            $matchsql = "SELECT 1
277
                           FROM {groups_members} gm
278
                           JOIN {groups} g ON g.id = gm.groupid
279
                          WHERE gm.userid = userids.id
280
                                AND g.courseid = " .
281
                    self::unique_sql_parameter($matchparams, $info->get_course()->id);
282
        }
283
 
284
        // Overall query combines all this.
285
        $condition = $not ? 'NOT' : '';
286
        $sql = "SELECT userids.id
287
                  FROM ($enrolsql) userids
288
                 WHERE (userids.id IN ($aagsql)) OR $condition EXISTS ($matchsql)";
289
        return array($sql, array_merge($enrolparams, $aagparams, $matchparams));
290
    }
291
}