Passed
Push — MOODLE_30_STABLE ( 189151 )
by Roberto
16:21 queued 12s
created

lib.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
 * This file contains the relationship API functions used to interact with the data
19
 * and other Moodle hooks
20
 *
21
 * @package local_relationship
22
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
25
defined('MOODLE_INTERNAL') || die();
26
27
function local_relationship_extend_settings_navigation(navigation_node $navigation) {
28
    global $PAGE;
29
30
    if (is_a($PAGE->context, 'context_coursecat') && has_capability('local/relationship:manage', $PAGE->context)) {
31
        $category_node = $navigation->get('categorysettings');
32
        if ($category_node) {
33
            $category_node->add(
34
                    get_string('pluginname', 'local_relationship'),
35
                    new moodle_url('/local/relationship/index.php', array('contextid' => $PAGE->context->id)),
36
                    navigation_node::TYPE_SETTING,
37
                    null,
38
                    null,
39
                    new pix_icon('relationship', '', 'local_relationship')
40
            );
41
        }
42
    }
43
}
44
45
function local_relationship_cron() {
46
    relationship_uniformly_distribute_members();
47
48
    return true;
49
}
50
51
52
//
53
// TODO: Refactory to "relationship class"
54
//
55
56
function relationship_uniformly_distribute_members($relationshipid = null) {
57
    global $DB;
58
59
    $params = array();
60
    $cond = '';
61
    if (!empty($relationshipid)) {
62
        $params['id'] = $relationshipid;
63
        $cond = 'WHERE rl.id = :id';
64
    }
65
66
    $sql = "SELECT DISTINCT rc.*
67
              FROM {relationship} rl
68
              JOIN {relationship_cohorts} rc
69
                ON (rc.relationshipid = rl.id AND rc.uniformdistribution = 1)
70
              JOIN {relationship_groups} rg
71
                ON (rg.relationshipid = rl.id AND rc.uniformdistribution = 1)
72
              {$cond}";
73
    $rcs = $DB->get_records_sql($sql, $params);
74
    foreach ($rcs AS $rc) {
75
        $params = array('relationshipid' => $rc->relationshipid, 'relationshipcohortid' => $rc->id);
76
        $sql = " SELECT cm.userid
77
                   FROM {relationship_cohorts} rc
78
                   JOIN {cohort} ch
79
                     ON (ch.id = rc.cohortid)
80
                   JOIN {cohort_members} cm
81
                     ON (cm.cohortid = ch.id)
82
              LEFT JOIN {relationship_members} rm
83
                     ON (rm.relationshipcohortid = rc.id AND rm.userid = cm.userid)
84
                  WHERE rc.id = :relationshipcohortid
85
                    AND ISNULL(rm.userid)";
86
        $users = $DB->get_records_sql($sql, $params);
87
88
        relationship_uniformly_distribute_users($rc, array_keys($users));
89
    }
90
}
91
92
function relationship_uniformly_distribute_users($relationshipcohort, $userids) {
93
    global $DB;
94
95
    if (empty($userids)) {
96
        return;
97
    }
98
    $sql = "SELECT rg.id, rg.userlimit, count(DISTINCT rm.userid) as count
99
              FROM {relationship_cohorts} rc
100
              JOIN {relationship_groups} rg
101
                ON (rg.relationshipid = rc.relationshipid AND rg.uniformdistribution = 1)
102
         LEFT JOIN {relationship_members} rm
103
                ON (rm.relationshipgroupid = rg.id AND rm.relationshipcohortid = rc.id)
104
             WHERE rc.id = :relationshipcohortid
105
          GROUP BY rg.id";
106
    $groups = $DB->get_records_sql($sql, array('relationshipcohortid' => $relationshipcohort->id));
107
    if (!empty($groups)) {
108
        foreach ($userids AS $userid) {
109
            $min = 99999999;
110
            $gmin = 0;
111
            foreach ($groups AS $grpid => $grp) {
112
                if ($grp->count < $min && ($grp->userlimit == 0 || $grp->count < $grp->userlimit)) {
113
                    $min = $grp->count;
114
                    $gmin = $grpid;
115
                }
116
            }
117
            if ($gmin == 0) {
118
                break; // there is no group to add member
119
            } else {
120
                relationship_add_member($gmin, $relationshipcohort->id, $userid);
121
                $groups[$gmin]->count++;
122
            }
123
        }
124
    }
125
}
126
127
/**
128
 * Add relationship member
129
 *
130
 * @param $relationshipgroupid
131
 * @param $relationshipcohortid
132
 * @param $userid
133
 * @return int|bool relationship_members id of added member or false if any error occours
134
 * @throws coding_exception
135
 */
136
function relationship_add_member($relationshipgroupid, $relationshipcohortid, $userid) {
137
    global $DB;
138
139
    $params = array('relationshipgroupid' => $relationshipgroupid, 'userid' => $userid, 'relationshipcohortid' => $relationshipcohortid);
140
    if ($DB->record_exists('relationship_members', $params)) {
141
        // No duplicates!
142
        return false;
143
    }
144
145
    $relationshipgroup = $DB->get_record('relationship_groups', array('id' => $relationshipgroupid), '*', MUST_EXIST);
146
    $relationshipcohort = $DB->get_record('relationship_cohorts', array('id' => $relationshipcohortid), '*', MUST_EXIST);
147
    $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
148
149
    $record = new stdClass();
150
    $record->relationshipgroupid = $relationshipgroupid;
151
    $record->relationshipcohortid = $relationshipcohortid;
152
    $record->userid = $userid;
153
    $record->timeadded = time();
154
155
    $result = $DB->insert_record('relationship_members', $record);
156
157
    if ($result) {
158
        $record->id = $result;
159
160
        $event = \local_relationship\event\relationshipgroup_member_added::create(array(
161
                'context' => context::instance_by_id($relationship->contextid),
162
                'objectid' => $relationshipgroupid,
163
                'relateduserid' => $userid,
164
                'other' => $relationshipcohort->roleid,
165
        ));
166
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
167
        $event->add_record_snapshot('relationship', $relationship);
168
        $event->trigger();
169
170
        return $record->id;
171
    }
172
173
    return false;
174
}
175
176
/**
177
 * Remove member from a relationship
178
 *
179
 * @param int $relationshipgroupid
180
 * @param int $relationshipcohortid
181
 * @param int $userid
182
 * @return bool
183
 * @throws coding_exception
184
 */
185
function relationship_remove_member($relationshipgroupid, $relationshipcohortid, $userid) {
186
    global $DB;
187
188
    $params = array('relationshipgroupid' => $relationshipgroupid, 'userid' => $userid, 'relationshipcohortid' => $relationshipcohortid);
189
    $result = $DB->delete_records('relationship_members', $params);
190
191
    if ($result) {
192
        $relationshipgroup = $DB->get_record('relationship_groups', array('id' => $relationshipgroupid), '*', MUST_EXIST);
193
        $relationshipcohort = $DB->get_record('relationship_cohorts', array('id' => $relationshipcohortid), '*', MUST_EXIST);
194
        $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
195
196
        $event = \local_relationship\event\relationshipgroup_member_removed::create(array(
197
                'context' => context::instance_by_id($relationship->contextid),
198
                'objectid' => $relationshipgroupid,
199
                'relateduserid' => $userid,
200
                'other' => $relationshipcohort->roleid,
201
        ));
202
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
203
        $event->add_record_snapshot('relationship', $relationship);
204
        $event->trigger();
205
206
        return true;
207
    }
208
209
    return false;
210
}
211
212
/**
213
 * @param $relationshipid
214
 * @return stdClass $relationship
215
 */
216
function relationship_get_relationship($relationshipid) {
217
    global $DB;
218
219
    $relationship = $DB->get_record('relationship', array('id' => $relationshipid), '*', MUST_EXIST);
220
    $relationship->tags = tag_get_tags_array('relationship', $relationshipid);
221
222
    return $relationship;
223
}
224
225
/**
226
 * Add new relationship.
227
 *
228
 * @param stdClass $relationship
229
 * @return int|bool new relationship id or false if any error occours
230
 * @throws coding_exception
231
 */
232
function relationship_add_relationship($relationship) {
233
    global $DB;
234
235
    if (!isset($relationship->name)) {
236
        throw new coding_exception('Missing relationship name in relationship_add_relationship().');
237
    }
238
    $relationship->name = trim($relationship->name);
239
240
    if (!isset($relationship->idnumber)) {
241
        $relationship->idnumber = null;
242
    }
243
244
    if (!isset($relationship->description)) {
245
        $relationship->description = '';
246
    }
247
248
    if (!isset($relationship->descriptionformat)) {
249
        $relationship->descriptionformat = FORMAT_HTML;
250
    }
251
252
    if (empty($relationship->component)) {
253
        $relationship->component = '';
254
    }
255
256
    if (!isset($relationship->timecreated)) {
257
        $relationship->timecreated = time();
258
    }
259
260
    if (!isset($relationship->timemodified)) {
261
        $relationship->timemodified = $relationship->timecreated;
262
    }
263
264
    $result = $DB->insert_record('relationship', $relationship);
265
266
    if ($result) {
267
        $relationship->id = $result;
268
        tag_set('relationship', $relationship->id, $relationship->tags);
269
270
        $event = \local_relationship\event\relationship_created::create(array(
271
                'context' => context::instance_by_id($relationship->contextid),
272
                'objectid' => $relationship->id,
273
        ));
274
        $event->add_record_snapshot('relationship', $relationship);
275
        $event->trigger();
276
277
        return $relationship->id;
278
    }
279
280
    return false;
281
}
282
283
/**
284
 * Update existing relationship
285
 *
286
 * @param sstdClass $relationship
287
 * @return void
288
 */
289
function relationship_update_relationship($relationship) {
290
    global $DB;
291
292
    $relationship->timemodified = time();
293
    $result = $DB->update_record('relationship', $relationship);
294
295
    if ($result) {
296
        tag_set('relationship', $relationship->id, $relationship->tags);
297
298
        $event = \local_relationship\event\relationship_updated::create(array(
299
                'context' => context::instance_by_id($relationship->contextid),
300
                'objectid' => $relationship->id,
301
        ));
302
        $event->add_record_snapshot('relationship', $relationship);
303
        $event->trigger();
304
305
        return true;
306
    }
307
308
    return false;
309
}
310
311
/**
312
 * Delete relationship
313
 * @param stdClass $relationship
314
 * @return bool
0 ignored issues
show
Should the return type not be integer|boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
315
 * @throws coding_exception
316
 * @throws dml_transaction_exception
317
 */
318
function relationship_delete_relationship($relationship) {
319
    global $DB;
320
321
    $relationshipgroups = $DB->get_records('relationship_groups', array('relationshipid' => $relationship->id));
322
    foreach ($relationshipgroups AS $g) {
323
        relationship_delete_group($g);
324
    }
325
326
    try {
327
        $transaction = $DB->start_delegated_transaction();
328
329
330
        $cohorts = $DB->get_records('relationship_cohorts', array('relationshipid' => $relationship->id));
331
332
        if(count($cohorts) == 0) {
333
            $DB->delete_records('relationship_cohorts', array('relationshipid' => $relationship->id));
334
335
            $tags = tag_get_tags_array('relationship', $relationship->id);
336
            tag_delete(array_keys($tags));
337
338
            $DB->delete_records('relationship', array('id' => $relationship->id));
339
340
            $transaction->allow_commit();
341
        } else {
342
            return -1;
343
        }
344
    } catch (Exception $e) {
345
        $transaction->rollback($e);
346
347
        return false;
348
    }
349
350
    $event = \local_relationship\event\relationship_deleted::create(array(
351
            'context' => context::instance_by_id($relationship->contextid),
352
            'objectid' => $relationship->id,
353
    ));
354
    $event->add_record_snapshot('relationship', $relationship);
355
    $event->trigger();
356
357
    return true;
358
}
359
360
//
361
// Relationship Cohorts
362
//
363
364
/**
365
 * Cohorts related to a relationship
366
 *
367
 * @param $relationshipid
368
 * @param bool $full load full cohort and roles data
369
 * @return array
370
 * @throws coding_exception
371
 */
372
function relationship_get_cohorts($relationshipid, $full = true) {
373
    global $DB;
374
375
    $cohorts = $DB->get_records('relationship_cohorts', array('relationshipid' => $relationshipid));
376
    if ($full) {
377
        foreach ($cohorts AS $ch) {
378
            $ch->cohort = $DB->get_record('cohort', array('id' => $ch->cohortid));
379
            if ($role = $DB->get_record('role', array('id' => $ch->roleid))) {
380
                $ch->role_name = role_get_name($role);
381
            } else {
382
                $ch->role_name = false;
383
            }
384
        }
385
    }
386
387
    return $cohorts;
388
}
389
390
/**
391
 * Get a specific relationshipcohort by ID
392
 *
393
 * @param $relationshipcohortid
394
 * @param bool $full load full cohort and roles data
395
 * @return mixed
396
 * @throws coding_exception
397
 */
398
function relationship_get_cohort($relationshipcohortid, $full = true) {
399
    global $DB;
400
401
    $cohort = $DB->get_record('relationship_cohorts', array('id' => $relationshipcohortid), '*', MUST_EXIST);
402
    if ($full) {
403
        $cohort->cohort = $DB->get_record('cohort', array('id' => $cohort->cohortid));
404
        if ($role = $DB->get_record('role', array('id' => $cohort->roleid))) {
405
            $cohort->role_name = role_get_name($role);
406
        } else {
407
            $cohort->role_name = false;
408
        }
409
    }
410
411
    return $cohort;
412
}
413
414
/**
415
 * Add a relationshipcohort
416
 *
417
 * @param $relationshipcohort
418
 * @return bool|int
419
 */
420
function relationship_add_cohort($relationshipcohort) {
421
    global $DB;
422
423
    if (!isset($relationshipcohort->timecreated)) {
424
        $relationshipcohort->timecreated = time();
425
    }
426
    if (!isset($relationshipcohort->timemodified)) {
427
        $relationshipcohort->timemodified = $relationshipcohort->timecreated;
428
    }
429
430
    $relationshipcohort->id = $DB->insert_record('relationship_cohorts', $relationshipcohort);
431
432
    return $relationshipcohort->id;
433
}
434
435
/**
436
 * Update a specific relationshipcohort
437
 *
438
 * @param $relationshipcohort
439
 * @return bool
440
 */
441
function relationship_update_cohort($relationshipcohort) {
442
    global $DB;
443
444
    $relationshipcohort->timemodified = time();
445
446
    return $DB->update_record('relationship_cohorts', $relationshipcohort);
447
}
448
449
/**
450
 * Delete a specific relationshipcohort
451
 *
452
 * @param $relationshipcohort
453
 * @return bool
454
 */
455
function relationship_delete_cohort($relationshipcohort) {
456
    global $DB;
457
    $members = $DB->get_records('relationship_members', array('relationshipcohortid' => $relationshipcohort->id));
458
    foreach ($members as $m) {
459
        relationship_remove_member($m->relationshipgroupid, $m->relationshipcohortid, $m->userid);
460
    }
461
462
    return $DB->delete_records('relationship_cohorts', array('id' => $relationshipcohort->id));
463
}
464
465
//
466
// Relationship Groups
467
//
468
469
/**
470
 * Get groups from a relationship
471
 * @param $relationshipid
472
 * @return array
473
 */
474
function relationship_get_groups($relationshipid) {
475
    global $DB;
476
477
    $sql = "SELECT rg.*, (SELECT count(*)
478
                            FROM relationship_members
479
                           WHERE relationshipgroupid = rg.id) as size
480
              FROM {relationship_groups} rg
481
             WHERE rg.relationshipid = :relationshipid
482
          GROUP BY rg.id
483
          ORDER BY name";
484
485
    return $DB->get_records_sql($sql, array('relationshipid' => $relationshipid));
486
}
487
488
/**
489
 * Add a relationshipgroup
490
 *
491
 * @param $relationshipgroup
492
 * @return bool|int
493
 * @throws coding_exception
494
 */
495
function relationship_add_group($relationshipgroup) {
496
    global $DB;
497
498
    $relationshipgroup->name = trim($relationshipgroup->name);
499
    if (!isset($relationshipgroup->timecreated)) {
500
        $relationshipgroup->timecreated = time();
501
    }
502
    if (!isset($relationshipgroup->timemodified)) {
503
        $relationshipgroup->timemodified = $relationshipgroup->timecreated;
504
    }
505
506
    $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
507
    $result = $DB->insert_record('relationship_groups', $relationshipgroup);
508
509
    if ($result) {
510
        $relationshipgroup->id = $result;
511
512
        $event = \local_relationship\event\relationshipgroup_created::create(array(
513
                'context' => context::instance_by_id($relationship->contextid),
514
                'objectid' => $relationshipgroup->id,
515
        ));
516
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
517
        $event->add_record_snapshot('relationship', $relationship);
518
        $event->trigger();
519
    }
520
521
    return $result;
522
}
523
524
/**
525
 * Update a relationshipgroup
526
 *
527
 * @param $relationshipgroup
528
 * @return bool
529
 * @throws coding_exception
530
 */
531
function relationship_update_group($relationshipgroup) {
532
    global $DB;
533
534
    $relationshipgroup->timemodified = time();
535
    if (isset($relationshipgroup->name)) {
536
        $relationshipgroup->name = trim($relationshipgroup->name);
537
    }
538
    $result = $DB->update_record('relationship_groups', $relationshipgroup);
539
540
    if ($result) {
541
        $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
542
543
        $event = \local_relationship\event\relationshipgroup_updated::create(array(
544
                'context' => context::instance_by_id($relationship->contextid),
545
                'objectid' => $relationshipgroup->id,
546
        ));
547
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
548
        $event->add_record_snapshot('relationship', $relationship);
549
        $event->trigger();
550
    }
551
552
    return $result;
553
}
554
555
/**
556
 * @param $relationshipgroup
557
 * @return bool
558
 * @throws coding_exception
559
 * @throws dml_transaction_exception
560
 */
561
function relationship_delete_group($relationshipgroup) {
562
    global $DB;
563
564
    try {
565
        $transaction = $DB->start_delegated_transaction();
566
567
        $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
568
        $DB->delete_records('relationship_members', array('relationshipgroupid' => $relationshipgroup->id));
569
        $DB->delete_records('relationship_groups', array('id' => $relationshipgroup->id));
570
571
        $transaction->allow_commit();
572
    } catch (Exception $e) {
573
        $transaction->rollback($e);
574
575
        return false;
576
    }
577
578
    $event = \local_relationship\event\relationshipgroup_deleted::create(array(
579
            'context' => context::instance_by_id($relationship->contextid),
580
            'objectid' => $relationshipgroup->id,
581
    ));
582
    $event->add_record_snapshot('relationship_groups', $relationshipgroup);
583
    $event->add_record_snapshot('relationship', $relationship);
584
    $event->trigger();
585
586
    return true;
587
}
588