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
 * Class exposing the api for the cohortroles tool.
19
 *
20
 * @package    tool_cohortroles
21
 * @copyright  2015 Damyon Wiese
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace tool_cohortroles;
25
 
26
use stdClass;
27
use context_system;
28
use core_competency\invalid_persistent_exception;
29
 
30
/**
31
 * Class for doing things with cohort roles.
32
 *
33
 * @copyright  2015 Damyon Wiese
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class api {
37
 
38
    /**
39
     * Create a cohort role assignment from a record containing all the data for the class.
40
     *
41
     * Requires moodle/role:manage capability at the system context.
42
     *
43
     * @param stdClass $record Record containing all the data for an instance of the class.
44
     * @return competency
45
     */
46
    public static function create_cohort_role_assignment(stdClass $record) {
47
        $cohortroleassignment = new cohort_role_assignment(0, $record);
48
        $context = context_system::instance();
49
 
50
        // First we do a permissions check.
51
        require_capability('moodle/role:manage', $context);
52
 
53
        // Validate before we check for existing records.
54
        if (!$cohortroleassignment->is_valid()) {
55
            throw new invalid_persistent_exception($cohortroleassignment->get_errors());
56
        }
57
 
58
        $existing = cohort_role_assignment::get_record((array) $record);
59
        if (!empty($existing)) {
60
            return false;
61
        } else {
62
            // OK - all set.
63
            $cohortroleassignment->create();
64
        }
65
        return $cohortroleassignment;
66
    }
67
 
68
    /**
69
     * Delete a cohort role assignment by id.
70
     *
71
     * Requires moodle/role:manage capability at the system context.
72
     *
73
     * @param int $id The record to delete. This will also remove this role from the user for all users in the system.
74
     * @return boolean
75
     */
76
    public static function delete_cohort_role_assignment($id) {
77
        $cohortroleassignment = new cohort_role_assignment($id);
78
        $context = context_system::instance();
79
 
80
        // First we do a permissions check.
81
        require_capability('moodle/role:manage', $context);
82
 
83
        // OK - all set.
84
        return $cohortroleassignment->delete();
85
    }
86
 
87
    /**
88
     * Perform a search based on the provided filters and return a paginated list of records.
89
     *
90
     * Requires moodle/role:manage capability at the system context.
91
     *
92
     * @param string $sort The column to sort on
93
     * @param string $order ('ASC' or 'DESC')
94
     * @param int $skip Number of records to skip (pagination)
95
     * @param int $limit Max of records to return (pagination)
96
     * @return array of cohort_role_assignment
97
     */
98
    public static function list_cohort_role_assignments($sort = '', $order = 'ASC', $skip = 0, $limit = 0) {
99
        $context = context_system::instance();
100
 
101
        // First we do a permissions check.
102
        require_capability('moodle/role:manage', $context);
103
 
104
        // OK - all set.
105
        return cohort_role_assignment::get_records(array(), $sort, $order, $skip, $limit);
106
    }
107
 
108
    /**
109
     * Perform a search based on the provided filters and return a paginated list of records.
110
     *
111
     * Requires moodle/role:manage capability at system context.
112
     *
113
     * @return int
114
     */
115
    public static function count_cohort_role_assignments() {
116
        $context = context_system::instance();
117
 
118
        // First we do a permissions check.
119
        require_capability('moodle/role:manage', $context);
120
 
121
        // OK - all set.
122
        return cohort_role_assignment::count_records();
123
    }
124
 
125
    /**
126
     * Sync all roles - adding and deleting role assignments as required.
127
     *
128
     * Slow. Should only be called from a background task.
129
     *
130
     * Requires moodle/role:manage capability at the system context.
131
     *
132
     * @return array('rolesadded' => array of (useridassignedto, useridassignedover, roleid),
133
     *               'rolesremoved' => array of (useridassignedto, useridassignedover, roleid))
134
     */
135
    public static function sync_all_cohort_roles() {
136
        global $DB;
137
 
138
        $context = context_system::instance();
139
 
140
        // First we do a permissions check.
141
        require_capability('moodle/role:manage', $context);
142
 
143
        // Ok ready to go.
144
        $rolesadded = array();
145
        $rolesremoved = array();
146
 
147
        // Remove any cohort role mappings for roles which have been deleted.
148
        // The role assignments are not a consideration because these will have been removed when the role was.
149
        $DB->delete_records_select('tool_cohortroles', "roleid NOT IN (SELECT id FROM {role})");
150
 
151
        // Get all cohort role assignments and group them by user and role.
152
        $all = cohort_role_assignment::get_records(array(), 'userid, roleid');
153
        // We build an better structure to loop on.
154
        $info = array();
155
        foreach ($all as $cra) {
156
            if (!isset($info[$cra->get('userid')])) {
157
                $info[$cra->get('userid')] = array();
158
            }
159
            if (!isset($info[$cra->get('userid')][$cra->get('roleid')])) {
160
                $info[$cra->get('userid')][$cra->get('roleid')] = array();
161
            }
162
            array_push($info[$cra->get('userid')][$cra->get('roleid')], $cra->get('cohortid'));
163
        }
164
        // Then for each user+role combo - find user context in the cohort without a role assigned.
165
 
166
        foreach ($info as $userid => $roles) {
167
            foreach ($roles as $roleid => $cohorts) {
168
                list($cohortsql, $params) = $DB->get_in_or_equal($cohorts, SQL_PARAMS_NAMED);
169
 
170
                $params['usercontext'] = CONTEXT_USER;
171
                $params['roleid'] = $roleid;
172
                $params['userid'] = $userid;
173
 
174
                $sql = 'SELECT DISTINCT u.id AS userid, ra.id, ctx.id AS contextid
175
                          FROM {user} u
176
                          JOIN {cohort_members} cm ON u.id = cm.userid
177
                          JOIN {context} ctx ON u.id = ctx.instanceid AND ctx.contextlevel = :usercontext
178
                          LEFT JOIN {role_assignments} ra ON ra.contextid = ctx.id
179
                           AND ra.roleid = :roleid
180
                           AND ra.userid = :userid
181
                         WHERE cm.cohortid ' . $cohortsql . '
182
                           AND u.deleted = 0
183
                           AND ra.id IS NULL';
184
 
185
                $toadd = $DB->get_records_sql($sql, $params);
186
 
187
                foreach ($toadd as $add) {
188
                    role_assign($roleid, $userid, $add->contextid, 'tool_cohortroles');
189
                    $rolesadded[] = array(
190
                        'useridassignedto' => $userid,
191
                        'useridassignedover' => $add->userid,
192
                        'roleid' => $roleid
193
                    );
194
                }
195
            }
196
        }
197
 
198
        // And for each user+role combo - find user context not in the cohort with a role assigned.
199
        // If the role was assigned by this component, unassign the role.
200
        foreach ($info as $userid => $roles) {
201
            foreach ($roles as $roleid => $cohorts) {
202
                // Now we are looking for entries NOT in the cohort.
203
                list($cohortsql, $params) = $DB->get_in_or_equal($cohorts, SQL_PARAMS_NAMED);
204
 
205
                $params['usercontext'] = CONTEXT_USER;
206
                $params['roleid'] = $roleid;
207
                $params['userid'] = $userid;
208
                $params['component'] = 'tool_cohortroles';
209
 
210
                $sql = 'SELECT u.id as userid, ra.id, ctx.id AS contextid
211
                          FROM {user} u
212
                          JOIN {context} ctx ON u.id = ctx.instanceid AND ctx.contextlevel = :usercontext
213
                          JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.roleid = :roleid AND ra.userid = :userid
214
                     LEFT JOIN {cohort_members} cm ON u.id = cm.userid
215
                           AND cm.cohortid ' . $cohortsql . '
216
                         WHERE ra.component = :component AND cm.cohortid IS NULL';
217
 
218
                $toremove = $DB->get_records_sql($sql, $params);
219
                foreach ($toremove as $remove) {
220
                    role_unassign($roleid, $userid, $remove->contextid, 'tool_cohortroles');
221
                    $rolesremoved[] = array(
222
                        'useridassignedto' => $userid,
223
                        'useridassignedover' => $remove->userid,
224
                        'roleid' => $roleid
225
                    );
226
                }
227
            }
228
        }
229
 
230
        // Clean the legacy role assignments which are stale.
231
        $paramsclean['usercontext'] = CONTEXT_USER;
232
        $paramsclean['component'] = 'tool_cohortroles';
233
        $sql = 'SELECT DISTINCT(ra.id), ra.roleid, ra.userid, ra.contextid, ctx.instanceid
234
                  FROM {role_assignments} ra
235
                  JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = :usercontext
236
                  JOIN {cohort_members} cm ON cm.userid = ctx.instanceid
237
                  LEFT JOIN {tool_cohortroles} tc ON tc.cohortid = cm.cohortid
238
                    AND tc.userid = ra.userid
239
                    AND tc.roleid = ra.roleid
240
                 WHERE ra.component = :component
241
                   AND tc.id is null';
242
        if ($candidatelegacyassignments = $DB->get_records_sql($sql, $paramsclean)) {
243
            $sql = 'SELECT DISTINCT(ra.id)
244
                  FROM {role_assignments} ra
245
                  JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = :usercontext
246
                  JOIN {cohort_members} cm ON cm.userid = ctx.instanceid
247
                  JOIN {tool_cohortroles} tc ON tc.cohortid = cm.cohortid AND tc.userid = ra.userid
248
                 WHERE ra.component = :component';
249
            if ($currentvalidroleassignments = $DB->get_records_sql($sql, $paramsclean)) {
250
                foreach ($candidatelegacyassignments as $candidate) {
251
                    if (!array_key_exists($candidate->id, $currentvalidroleassignments)) {
252
                        role_unassign($candidate->roleid, $candidate->userid, $candidate->contextid, 'tool_cohortroles');
253
                        $rolesremoved[] = array(
254
                            'useridassignedto' => $candidate->userid,
255
                            'useridassignedover' => $candidate->instanceid,
256
                            'roleid' => $candidate->roleid
257
                        );
258
                    }
259
                }
260
            } else {
261
                foreach ($candidatelegacyassignments as $candidate) {
262
                    role_unassign($candidate->roleid, $candidate->userid, $candidate->contextid, 'tool_cohortroles');
263
                    $rolesremoved[] = array(
264
                        'useridassignedto' => $candidate->userid,
265
                        'useridassignedover' => $candidate->instanceid,
266
                        'roleid' => $candidate->roleid
267
                    );
268
                }
269
            }
270
        }
271
 
272
        return array('rolesadded' => $rolesadded, 'rolesremoved' => $rolesremoved);
273
    }
274
 
275
}