Passed
Push — master ( 5aefc8...6314bf )
by Roberto
06:06 queued 05:14
created

lib.php (4 issues)

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 = core_tag_tag::get_item_tags_array('relationship', '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
0 ignored issues
show
Should the return type not be 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...
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 boolean|integer?

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
    $cohorts = $DB->get_records('relationship_cohorts', array('relationshipid' => $relationship->id));
322
323
    if(count($cohorts) == 0) {
324
325
        $relationshipgroups = $DB->get_records('relationship_groups', array('relationshipid' => $relationship->id));
326
        foreach ($relationshipgroups AS $g) {
327
            relationship_delete_group($g);
328
        }
329
330
        try {
331
            $transaction = $DB->start_delegated_transaction();
332
333
334
335
            $DB->delete_records('relationship_cohorts', array('relationshipid' => $relationship->id));
336
337
            $tags = core_tag_tag::get_item_tags_array('relationship', 'relationship', $relationship->id);
338
            if (count($tags) > 0) {
339
                tag_delete(array_keys($tags));
340
            }
341
342
            $DB->delete_records('relationship', array('id' => $relationship->id));
343
344
            $transaction->allow_commit();
345
        } catch (Exception $e) {
346
            $transaction->rollback($e);
347
348
            return false;
349
        }
350
351
        $event = \local_relationship\event\relationship_deleted::create(array(
352
            'context' => context::instance_by_id($relationship->contextid),
353
            'objectid' => $relationship->id,
354
        ));
355
        $event->add_record_snapshot('relationship', $relationship);
356
        $event->trigger();
357
358
        return true;
359
    } else {
360
        return -1;
361
    }
362
}
363
364
//
365
// Relationship Cohorts
366
//
367
368
/**
369
 * Cohorts related to a relationship
370
 *
371
 * @param $relationshipid
372
 * @param bool $full load full cohort and roles data
373
 * @return array
374
 * @throws coding_exception
375
 */
376
function relationship_get_cohorts($relationshipid, $full = true) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
377
    global $DB;
378
379
    $cohorts = $DB->get_records('relationship_cohorts', array('relationshipid' => $relationshipid));
380
    if ($full) {
381
        foreach ($cohorts AS $ch) {
382
            $ch->cohort = $DB->get_record('cohort', array('id' => $ch->cohortid));
383
            if ($role = $DB->get_record('role', array('id' => $ch->roleid))) {
384
                $ch->role_name = role_get_name($role);
385
            } else {
386
                $ch->role_name = false;
387
            }
388
        }
389
    }
390
391
    return $cohorts;
392
}
393
394
/**
395
 * Get a specific relationshipcohort by ID
396
 *
397
 * @param $relationshipcohortid
398
 * @param bool $full load full cohort and roles data
399
 * @return mixed
400
 * @throws coding_exception
401
 */
402
function relationship_get_cohort($relationshipcohortid, $full = true) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
403
    global $DB;
404
405
    $cohort = $DB->get_record('relationship_cohorts', array('id' => $relationshipcohortid), '*', MUST_EXIST);
406
    if ($full) {
407
        $cohort->cohort = $DB->get_record('cohort', array('id' => $cohort->cohortid));
408
        if ($role = $DB->get_record('role', array('id' => $cohort->roleid))) {
409
            $cohort->role_name = role_get_name($role);
410
        } else {
411
            $cohort->role_name = false;
412
        }
413
    }
414
415
    return $cohort;
416
}
417
418
/**
419
 * Add a relationshipcohort
420
 *
421
 * @param $relationshipcohort
422
 * @return bool|int
423
 */
424
function relationship_add_cohort($relationshipcohort) {
425
    global $DB;
426
427
    if (!isset($relationshipcohort->timecreated)) {
428
        $relationshipcohort->timecreated = time();
429
    }
430
    if (!isset($relationshipcohort->timemodified)) {
431
        $relationshipcohort->timemodified = $relationshipcohort->timecreated;
432
    }
433
434
    $relationshipcohort->id = $DB->insert_record('relationship_cohorts', $relationshipcohort);
435
436
    return $relationshipcohort->id;
437
}
438
439
/**
440
 * Update a specific relationshipcohort
441
 *
442
 * @param $relationshipcohort
443
 * @return bool
444
 */
445
function relationship_update_cohort($relationshipcohort) {
446
    global $DB;
447
448
    $relationshipcohort->timemodified = time();
449
450
    return $DB->update_record('relationship_cohorts', $relationshipcohort);
451
}
452
453
/**
454
 * Delete a specific relationshipcohort
455
 *
456
 * @param $relationshipcohort
457
 * @return bool
458
 */
459
function relationship_delete_cohort($relationshipcohort) {
460
    global $DB;
461
    $members = $DB->get_records('relationship_members', array('relationshipcohortid' => $relationshipcohort->id));
462
    foreach ($members as $m) {
463
        relationship_remove_member($m->relationshipgroupid, $m->relationshipcohortid, $m->userid);
464
    }
465
466
    return $DB->delete_records('relationship_cohorts', array('id' => $relationshipcohort->id));
467
}
468
469
//
470
// Relationship Groups
471
//
472
473
/**
474
 * Get groups from a relationship
475
 * @param $relationshipid
476
 * @return array
477
 */
478
function relationship_get_groups($relationshipid) {
479
    global $DB;
480
481
    $sql = "SELECT rg.*, (SELECT count(*)
482
                            FROM {relationship_members}
483
                           WHERE relationshipgroupid = rg.id) as size
484
              FROM {relationship_groups} rg
485
             WHERE rg.relationshipid = :relationshipid
486
          GROUP BY rg.id
487
          ORDER BY name";
488
489
    return $DB->get_records_sql($sql, array('relationshipid' => $relationshipid));
490
}
491
492
/**
493
 * Add a relationshipgroup
494
 *
495
 * @param $relationshipgroup
496
 * @return bool|int
497
 * @throws coding_exception
498
 */
499
function relationship_add_group($relationshipgroup) {
500
    global $DB;
501
502
    $relationshipgroup->name = trim($relationshipgroup->name);
503
    if (!isset($relationshipgroup->timecreated)) {
504
        $relationshipgroup->timecreated = time();
505
    }
506
    if (!isset($relationshipgroup->timemodified)) {
507
        $relationshipgroup->timemodified = $relationshipgroup->timecreated;
508
    }
509
510
    $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
511
    $result = $DB->insert_record('relationship_groups', $relationshipgroup);
512
513
    if ($result) {
514
        $relationshipgroup->id = $result;
515
516
        $event = \local_relationship\event\relationshipgroup_created::create(array(
517
                'context' => context::instance_by_id($relationship->contextid),
518
                'objectid' => $relationshipgroup->id,
519
        ));
520
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
521
        $event->add_record_snapshot('relationship', $relationship);
522
        $event->trigger();
523
    }
524
525
    return $result;
526
}
527
528
/**
529
 * Update a relationshipgroup
530
 *
531
 * @param $relationshipgroup
532
 * @return bool
533
 * @throws coding_exception
534
 */
535
function relationship_update_group($relationshipgroup) {
536
    global $DB;
537
538
    $relationshipgroup->timemodified = time();
539
    if (isset($relationshipgroup->name)) {
540
        $relationshipgroup->name = trim($relationshipgroup->name);
541
    }
542
    $result = $DB->update_record('relationship_groups', $relationshipgroup);
543
544
    if ($result) {
545
        $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
546
547
        $event = \local_relationship\event\relationshipgroup_updated::create(array(
548
                'context' => context::instance_by_id($relationship->contextid),
549
                'objectid' => $relationshipgroup->id,
550
        ));
551
        $event->add_record_snapshot('relationship_groups', $relationshipgroup);
552
        $event->add_record_snapshot('relationship', $relationship);
553
        $event->trigger();
554
    }
555
556
    return $result;
557
}
558
559
/**
560
 * @param $relationshipgroup
561
 * @return bool
562
 * @throws coding_exception
563
 * @throws dml_transaction_exception
564
 */
565
function relationship_delete_group($relationshipgroup) {
566
    global $DB;
567
568
    try {
569
        $transaction = $DB->start_delegated_transaction();
570
571
        $relationship = $DB->get_record('relationship', array('id' => $relationshipgroup->relationshipid), '*', MUST_EXIST);
572
        $DB->delete_records('relationship_members', array('relationshipgroupid' => $relationshipgroup->id));
573
        $DB->delete_records('relationship_groups', array('id' => $relationshipgroup->id));
574
575
        $transaction->allow_commit();
576
    } catch (Exception $e) {
577
        $transaction->rollback($e);
578
579
        return false;
580
    }
581
582
    $event = \local_relationship\event\relationshipgroup_deleted::create(array(
583
            'context' => context::instance_by_id($relationship->contextid),
584
            'objectid' => $relationshipgroup->id,
585
    ));
586
    $event->add_record_snapshot('relationship_groups', $relationshipgroup);
587
    $event->add_record_snapshot('relationship', $relationship);
588
    $event->trigger();
589
590
    return true;
591
}
592