Passed
Pull Request — master (#5853)
by
unknown
07:37
created

TrackingCourseLog::getToolNameTable()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 65
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 60
nc 11
nop 1
dl 0
loc 65
rs 6.726
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use ChamiloSession as Session;
7
8
class TrackingCourseLog
9
{
10
    /**
11
     * Counts the item resources and returns the result as a mixed type.
12
     */
13
    public static function countItemResources(): mixed
14
    {
15
        $sessionId = api_get_session_id();
16
        $courseId = api_get_course_int_id();
17
18
        $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
19
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
20
21
        $sql = "SELECT count(tool) AS total_number_of_items
22
                FROM $tableItemProperty track_resource, $tableUser user
23
                WHERE
24
                    track_resource.c_id = $courseId AND
25
                    track_resource.insert_user_id = user.user_id AND
26
                    session_id ".(empty($sessionId) ? ' IS NULL ' : " = $sessionId ");
27
28
        if (isset($_GET['keyword'])) {
29
            $keyword = Database::escape_string(trim($_GET['keyword']));
30
            $sql .= " AND (
31
                        user.username LIKE '%".$keyword."%' OR
32
                        lastedit_type LIKE '%".$keyword."%' OR
33
                        tool LIKE '%".$keyword."%'
34
                    )";
35
        }
36
37
        $sql .= " AND tool IN (
38
                    'document',
39
                    'learnpath',
40
                    'quiz',
41
                    'glossary',
42
                    'link',
43
                    'course_description',
44
                    'announcement',
45
                    'thematic',
46
                    'thematic_advance',
47
                    'thematic_plan'
48
                )";
49
        $res = Database::query($sql);
50
        $obj = Database::fetch_object($res);
51
52
        return $obj->total_number_of_items;
53
    }
54
55
    /**
56
     * Retrieves item resources data with pagination and sorting options.
57
     */
58
    public static function getItemResourcesData($from, $numberOfItems, $column, $direction): array
59
    {
60
        $sessionId = api_get_session_id();
61
        $courseId = api_get_course_int_id();
62
63
        $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
64
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
65
        $tableSession = Database::get_main_table(TABLE_MAIN_SESSION);
66
        $column = (int) $column;
67
        $direction = !in_array(strtolower(trim($direction)), ['asc', 'desc']) ? 'asc' : $direction;
68
69
        $sql = "SELECT
70
                    tool as col0,
71
                    lastedit_type as col1,
72
                    ref as ref,
73
                    user.username as col3,
74
                    insert_date as col6,
75
                    visibility as col7,
76
                    user.user_id as user_id
77
                FROM $tableItemProperty track_resource, $tableUser user
78
                WHERE
79
                  track_resource.c_id = $courseId AND
80
                  track_resource.insert_user_id = user.user_id AND
81
                  session_id ".(empty($sessionId) ? ' IS NULL ' : " = $sessionId ");
82
83
        if (isset($_GET['keyword'])) {
84
            $keyword = Database::escape_string(trim($_GET['keyword']));
85
            $sql .= " AND (
86
                        user.username LIKE '%".$keyword."%' OR
87
                        lastedit_type LIKE '%".$keyword."%' OR
88
                        tool LIKE '%".$keyword."%'
89
                     ) ";
90
        }
91
92
        $sql .= " AND tool IN (
93
                    'document',
94
                    'learnpath',
95
                    'quiz',
96
                    'glossary',
97
                    'link',
98
                    'course_description',
99
                    'announcement',
100
                    'thematic',
101
                    'thematic_advance',
102
                    'thematic_plan'
103
                )";
104
105
        if (0 == $column) {
106
            $column = '0';
107
        }
108
        if ('' != $column && '' != $direction) {
109
            if (2 != $column && 4 != $column) {
110
                $sql .= " ORDER BY col$column $direction";
111
            }
112
        } else {
113
            $sql .= " ORDER BY col6 DESC ";
114
        }
115
116
        $from = intval($from);
117
        if ($from) {
118
            $numberOfItems = intval($numberOfItems);
119
            $sql .= " LIMIT $from, $numberOfItems ";
120
        }
121
122
        $res = Database::query($sql);
123
        $resources = [];
124
        $thematicTools = ['thematic', 'thematic_advance', 'thematic_plan'];
125
        while ($row = Database::fetch_array($res)) {
126
            $ref = $row['ref'];
127
            $tableName = self::getToolNameTable($row['col0']);
128
            $tableTool = Database::get_course_table($tableName['table_name']);
129
130
            $id = $tableName['id_tool'];
131
            $recorset = false;
132
133
            if (in_array($row['col0'], ['thematic_plan', 'thematic_advance'])) {
134
                $tblThematic = Database::get_course_table(TABLE_THEMATIC);
135
                $sql = "SELECT thematic_id FROM $tableTool
136
                        WHERE c_id = $courseId AND id = $ref";
137
                $rsThematic = Database::query($sql);
138
                if (Database::num_rows($rsThematic)) {
139
                    $rowThematic = Database::fetch_array($rsThematic);
140
                    $thematicId = $rowThematic['thematic_id'];
141
142
                    $sql = "SELECT session.id, session.name, user.username
143
                            FROM $tblThematic t, $tableSession session, $tableUser user
144
                            WHERE
145
                              t.c_id = $courseId AND
146
                              t.session_id = session.id AND
147
                              session.id_coach = user.user_id AND
148
                              t.id = $thematicId";
149
                    $recorset = Database::query($sql);
150
                }
151
            } else {
152
                $sql = "SELECT session.id, session.name, user.username
153
                          FROM $tableTool tool, $tableSession session, $tableUser user
154
                          WHERE
155
                              tool.c_id = $courseId AND
156
                              tool.session_id = session.id AND
157
                              session.id_coach = user.user_id AND
158
                              tool.$id = $ref";
159
                $recorset = Database::query($sql);
160
            }
161
162
            if (!empty($recorset)) {
163
                $obj = Database::fetch_object($recorset);
164
165
                $nameSession = '';
166
                $coachName = '';
167
                if (!empty($obj)) {
168
                    $nameSession = $obj->name;
169
                    $coachName = $obj->username;
170
                }
171
172
                $urlTool = api_get_path(WEB_CODE_PATH).$tableName['link_tool'];
173
174
                if ($row['col6'] != 2) {
175
                    if (in_array($row['col0'], $thematicTools)) {
176
                        $expThematicTool = explode('_', $row['col0']);
177
                        $thematicTooltitle = '';
178
                        if (is_array($expThematicTool)) {
179
                            foreach ($expThematicTool as $exp) {
180
                                $thematicTooltitle .= api_ucfirst($exp);
181
                            }
182
                        } else {
183
                            $thematicTooltitle = api_ucfirst($row['col0']);
184
                        }
185
186
                        $row[0] = '<a href="'.$urlTool.'?'.api_get_cidreq().'&action=thematic_details">'.get_lang(
187
                                $thematicTooltitle
188
                            ).'</a>';
189
                    } else {
190
                        $row[0] = '<a href="'.$urlTool.'?'.api_get_cidreq().'">'.get_lang(
191
                                'Tool'.api_ucfirst($row['col0'])
192
                            ).'</a>';
193
                    }
194
                } else {
195
                    $row[0] = api_ucfirst($row['col0']);
196
                }
197
                $row[1] = get_lang($row[1]);
198
                $row[6] = api_convert_and_format_date($row['col6'], null, date_default_timezone_get());
199
                $row[5] = '';
200
                //@todo Improve this code please
201
                switch ($tableName['table_name']) {
202
                    case 'document':
203
                        $sql = "SELECT tool.title as title FROM $tableTool tool
204
                                WHERE c_id = $courseId AND id = $ref";
205
                        $rsDocument = Database::query($sql);
206
                        $objDocument = Database::fetch_object($rsDocument);
207
                        if ($objDocument) {
208
                            $row[5] = $objDocument->title;
209
                        }
210
                        break;
211
                    case 'quiz':
212
                    case 'course_description':
213
                    case 'announcement':
214
                        $sql = "SELECT title FROM $tableTool
215
                                WHERE c_id = $courseId AND id = $ref";
216
                        $rsDocument = Database::query($sql);
217
                        $objDocument = Database::fetch_object($rsDocument);
218
                        if ($objDocument) {
219
                            $row[5] = $objDocument->title;
220
                        }
221
                        break;
222
                    case 'glossary':
223
                        $sql = "SELECT name FROM $tableTool
224
                                WHERE c_id = $courseId AND glossary_id = $ref";
225
                        $rsDocument = Database::query($sql);
226
                        $objDocument = Database::fetch_object($rsDocument);
227
                        if ($objDocument) {
228
                            $row[5] = $objDocument->name;
229
                        }
230
                        break;
231
                    case 'lp':
232
                        $sql = "SELECT name
233
                                FROM $tableTool WHERE c_id = $courseId AND id = $ref";
234
                        $rsDocument = Database::query($sql);
235
                        $objDocument = Database::fetch_object($rsDocument);
236
                        $row[5] = $objDocument->name;
237
                        break;
238
                    case 'thematic_plan':
239
                    case 'thematic':
240
                        $rs = Database::query("SELECT title FROM $tableTool WHERE c_id = $courseId AND id = $ref");
241
                        if (Database::num_rows($rs) > 0) {
242
                            $obj = Database::fetch_object($rs);
243
                            if ($obj) {
244
                                $row[5] = $obj->title;
245
                            }
246
                        }
247
                        break;
248
                    case 'thematic_advance':
249
                        $rs = Database::query("SELECT content FROM $tableTool WHERE c_id = $courseId AND id = $ref");
250
                        if (Database::num_rows($rs) > 0) {
251
                            $obj = Database::fetch_object($rs);
252
                            if ($obj) {
253
                                $row[5] = $obj->content;
254
                            }
255
                        }
256
                        break;
257
                    case 'thematic_plan':
258
                        $rs = Database::query("SELECT title FROM $tableTool WHERE c_id = $courseId AND id = $ref");
259
                        if (Database::num_rows($rs) > 0) {
260
                            $obj = Database::fetch_object($rs);
261
                            if ($obj) {
262
                                $row[5] = $obj->title;
263
                            }
264
                        }
265
                        break;
266
                    default:
267
                        break;
268
                }
269
270
                $row2 = $nameSession;
271
                if (!empty($coachName)) {
272
                    $row2 .= '<br />'.get_lang('Coach').': '.$coachName;
273
                }
274
                $row[2] = $row2;
275
                if (!empty($row['col3'])) {
276
                    $userInfo = api_get_user_info($row['user_id']);
277
                    $row['col3'] = Display::url(
278
                        $row['col3'],
279
                        $userInfo['profile_url']
280
                    );
281
                    $row[3] = $row['col3'];
282
283
                    $ip = Tracking::get_ip_from_user_event(
284
                        $row['user_id'],
285
                        $row['col6'],
286
                        true
287
                    );
288
                    if (empty($ip)) {
289
                        $ip = get_lang('Unknown');
290
                    }
291
                    $row[4] = $ip;
292
                }
293
294
                $resources[] = $row;
295
            }
296
        }
297
298
        return $resources;
299
    }
300
301
    /**
302
     * Retrieves the name and associated table for a given tool.
303
     */
304
    public static function getToolNameTable(string $tool): array
305
    {
306
        $linkTool = '';
307
        $idTool = '';
308
309
        switch ($tool) {
310
            case 'document':
311
                $tableName = TABLE_DOCUMENT;
312
                $linkTool = 'document/document.php';
313
                $idTool = 'id';
314
                break;
315
            case 'learnpath':
316
                $tableName = TABLE_LP_MAIN;
317
                $linkTool = 'lp/lp_controller.php';
318
                $idTool = 'id';
319
                break;
320
            case 'quiz':
321
                $tableName = TABLE_QUIZ_TEST;
322
                $linkTool = 'exercise/exercise.php';
323
                $idTool = 'iid';
324
                break;
325
            case 'glossary':
326
                $tableName = TABLE_GLOSSARY;
327
                $linkTool = 'glossary/index.php';
328
                $idTool = 'glossary_id';
329
                break;
330
            case 'link':
331
                $tableName = TABLE_LINK;
332
                $linkTool = 'link/link.php';
333
                $idTool = 'id';
334
                break;
335
            case 'course_description':
336
                $tableName = TABLE_COURSE_DESCRIPTION;
337
                $linkTool = 'course_description/';
338
                $idTool = 'id';
339
                break;
340
            case 'announcement':
341
                $tableName = TABLE_ANNOUNCEMENT;
342
                $linkTool = 'announcements/announcements.php';
343
                $idTool = 'id';
344
                break;
345
            case 'thematic':
346
                $tableName = TABLE_THEMATIC;
347
                $linkTool = 'course_progress/index.php';
348
                $idTool = 'id';
349
                break;
350
            case 'thematic_advance':
351
                $tableName = TABLE_THEMATIC_ADVANCE;
352
                $linkTool = 'course_progress/index.php';
353
                $idTool = 'id';
354
                break;
355
            case 'thematic_plan':
356
                $tableName = TABLE_THEMATIC_PLAN;
357
                $linkTool = 'course_progress/index.php';
358
                $idTool = 'id';
359
                break;
360
            default:
361
                $tableName = $tool;
362
                break;
363
        }
364
365
        return [
366
            'table_name' => $tableName,
367
            'link_tool' => $linkTool,
368
            'id_tool' => $idTool,
369
        ];
370
    }
371
372
    /**
373
     * Displays additional profile fields, excluding specific fields if provided.
374
     */
375
    public static function displayAdditionalProfileFields(array $exclude = [], $formAction = null): string
376
    {
377
        $formAction = $formAction ?: 'courseLog.php';
378
379
        // getting all the extra profile fields that are defined by the platform administrator
380
        $extraFields = UserManager::get_extra_fields(0, 50);
381
382
        // creating the form
383
        $return = '<form action="'.$formAction.'" method="get" name="additional_profile_field_form"
384
            id="additional_profile_field_form">';
385
        // the select field with the additional user profile fields, this is where we select the field of which we want to see
386
        // the information the users have entered or selected.
387
        $return .= '<div class="form-group">';
388
        $return .= '<select class="chzn-select" name="additional_profile_field[]" multiple>';
389
        $return .= '<option value="-">'.get_lang('SelectFieldToAdd').'</option>';
390
        $extraFieldsToShow = 0;
391
        foreach ($extraFields as $field) {
392
            // exclude extra profile fields by id
393
            if (in_array($field[3], $exclude)) {
394
                continue;
395
            }
396
            // show only extra fields that are visible + and can be filtered, added by J.Montoya
397
            if ($field[6] == 1 && $field[8] == 1) {
398
                if (isset($_GET['additional_profile_field']) && in_array($field[0], $_GET['additional_profile_field'])) {
399
                    $selected = 'selected="selected"';
400
                } else {
401
                    $selected = '';
402
                }
403
                $extraFieldsToShow++;
404
                $return .= '<option value="'.$field[0].'" '.$selected.'>'.$field[3].'</option>';
405
            }
406
        }
407
        $return .= '</select>';
408
        $return .= '</div>';
409
410
        // the form elements for the $_GET parameters (because the form is passed through GET
411
        foreach ($_GET as $key => $value) {
412
            if ($key != 'additional_profile_field') {
413
                $return .= '<input type="hidden" name="'.Security::remove_XSS($key).'" value="'.Security::remove_XSS(
414
                        $value
415
                    ).'" />';
416
            }
417
        }
418
        // the submit button
419
        $return .= '<div class="form-group">';
420
        $return .= '<button class="save btn btn-primary" type="submit">'
421
            .get_lang('AddAdditionalProfileField').'</button>';
422
        $return .= '</div>';
423
        $return .= '</form>';
424
425
        return $extraFieldsToShow > 0 ? $return : '';
426
    }
427
428
    /**
429
     * This function gets all the information of a certrain ($field_id)
430
     * additional profile field for a specific list of users is more efficent
431
     * than get_addtional_profile_information_of_field() function
432
     * It gets the information of all the users so that it can be displayed
433
     * in the sortable table or in the csv or xls export.
434
     *
435
     * @param int $fieldId field id
436
     * @param array $users list of user ids
437
     *
438
     * @author     Julio Montoya <[email protected]>
439
     *
440
     * @since      Nov 2009
441
     *
442
     * @version    1.8.6.2
443
     */
444
    public static function getAdditionalProfileInformationOfFieldByUser($fieldId, $users): array
445
    {
446
        // Database table definition
447
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
448
        $tableUserFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
449
        $extraField = Database::get_main_table(TABLE_EXTRA_FIELD);
450
        $resultExtraField = UserManager::get_extra_field_information($fieldId);
451
        $return = [];
452
        if (!empty($users)) {
453
            if ($resultExtraField['field_type'] == UserManager::USER_FIELD_TYPE_TAG) {
454
                foreach ($users as $user_id) {
455
                    $userResult = UserManager::get_user_tags($user_id, $fieldId);
456
                    $tagList = [];
457
                    foreach ($userResult as $item) {
458
                        $tagList[] = $item['tag'];
459
                    }
460
                    $return[$user_id][] = implode(', ', $tagList);
461
                }
462
            } else {
463
                $newUserArray = [];
464
                foreach ($users as $user_id) {
465
                    $newUserArray[] = "'".$user_id."'";
466
                }
467
                $users = implode(',', $newUserArray);
468
                $extraFieldType = EntityExtraField::USER_FIELD_TYPE;
469
                // Selecting only the necessary information NOT ALL the user list
470
                $sql = "SELECT user.user_id, v.value
471
                        FROM $tableUser user
472
                        INNER JOIN $tableUserFieldValues v
473
                        ON (user.user_id = v.item_id)
474
                        INNER JOIN $extraField f
475
                        ON (f.id = v.field_id)
476
                        WHERE
477
                            f.extra_field_type = $extraFieldType AND
478
                            v.field_id=".intval($fieldId)." AND
479
                            user.user_id IN ($users)";
480
481
                $result = Database::query($sql);
482
                while ($row = Database::fetch_array($result)) {
483
                    // get option value for field type double select by id
484
                    if (!empty($row['value'])) {
485
                        if ($resultExtraField['field_type'] ==
486
                            ExtraField::FIELD_TYPE_DOUBLE_SELECT
487
                        ) {
488
                            $idDoubleSelect = explode(';', $row['value']);
489
                            if (is_array($idDoubleSelect)) {
490
                                $value1 = $resultExtraField['options'][$idDoubleSelect[0]]['option_value'];
491
                                $value2 = $resultExtraField['options'][$idDoubleSelect[1]]['option_value'];
492
                                $row['value'] = ($value1.';'.$value2);
493
                            }
494
                        }
495
496
                        if ($resultExtraField['field_type'] == ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD) {
497
                            $parsedValue = explode('::', $row['value']);
498
499
                            if ($parsedValue) {
500
                                $value1 = $resultExtraField['options'][$parsedValue[0]]['display_text'];
501
                                $value2 = $parsedValue[1];
502
503
                                $row['value'] = "$value1: $value2";
504
                            }
505
                        }
506
507
                        if ($resultExtraField['field_type'] == ExtraField::FIELD_TYPE_TRIPLE_SELECT) {
508
                            [$level1, $level2, $level3] = explode(';', $row['value']);
509
510
                            $row['value'] = $resultExtraField['options'][$level1]['display_text'].' / ';
511
                            $row['value'] .= $resultExtraField['options'][$level2]['display_text'].' / ';
512
                            $row['value'] .= $resultExtraField['options'][$level3]['display_text'];
513
                        }
514
                    }
515
                    // get other value from extra field
516
                    $return[$row['user_id']][] = $row['value'];
517
                }
518
            }
519
        }
520
521
        return $return;
522
    }
523
524
    /**
525
     * Get number of users for sortable with pagination.
526
     */
527
    public static function getNumberOfUsers(array $conditions): int
528
    {
529
        $conditions['get_count'] = true;
530
531
        return self::getUserData(0, 0, 0, '', $conditions);
532
    }
533
534
    /**
535
     * Get data for users list in sortable with pagination.
536
     */
537
    public static function getUserData(
538
        $from,
539
        $numberOfItems,
540
        $column,
541
        $direction,
542
        array $conditions = [],
543
        bool $exerciseToCheckConfig = true,
544
        bool $displaySessionInfo = false,
545
        ?string $courseCode = null,
546
        ?int $sessionId = null,
547
        bool $exportCsv = false,
548
        array $userIds = []
549
    ) {
550
        $includeInvitedUsers = $conditions['include_invited_users'] ?? false;
551
        $getCount = $conditions['get_count'] ?? false;
552
553
        $csvContent = [];
554
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
555
        $tblUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
556
        $accessUrlId = api_get_current_access_url_id();
557
558
        if (!empty($userIds) && is_array($userIds)) {
559
            $userIds = array_map('intval', $userIds);
560
            $conditionUser = " WHERE user.id IN (".implode(',', $userIds).") ";
561
        } else {
562
            $conditionUser = " WHERE user.id = " . (int) $userIds;
563
        }
564
565
        if (!empty($_GET['user_keyword'])) {
566
            $keyword = trim(Database::escape_string($_GET['user_keyword']));
567
            $conditionUser .= " AND (
568
            user.firstname LIKE '%".$keyword."%' OR
569
            user.lastname LIKE '%".$keyword."%'  OR
570
            user.username LIKE '%".$keyword."%'  OR
571
            user.email LIKE '%".$keyword."%'
572
         ) ";
573
        }
574
575
        $urlTable = '';
576
        $urlCondition = '';
577
        if (api_is_multiple_url_enabled()) {
578
            $urlTable = " INNER JOIN $tblUrlRelUser as url_users ON (user.id = url_users.user_id)";
579
            $urlCondition = " AND access_url_id = '$accessUrlId'";
580
        }
581
582
        $invitedUsersCondition = '';
583
        if (!$includeInvitedUsers) {
584
            $invitedUsersCondition = " AND user.status != ".INVITEE;
585
        }
586
587
        $select = '
588
            SELECT user.id as user_id,
589
                user.official_code  as col0,
590
                user.lastname       as col1,
591
                user.firstname      as col2,
592
                user.username       as col3,
593
                user.email          as col4';
594
595
        if ($getCount) {
596
            $select = ' SELECT COUNT(distinct(user.id)) as count ';
597
        }
598
599
        $sqlInjectJoins = '';
600
        $where = 'AND 1 = 1 ';
601
        $sqlInjectWhere = '';
602
        if (!empty($conditions)) {
603
            if (isset($conditions['inject_joins'])) {
604
                $sqlInjectJoins = $conditions['inject_joins'];
605
            }
606
            if (isset($conditions['where'])) {
607
                $where = $conditions['where'];
608
            }
609
            if (isset($conditions['inject_where'])) {
610
                $sqlInjectWhere = $conditions['inject_where'];
611
            }
612
            $injectExtraFields = !empty($conditions['inject_extra_fields']) ? $conditions['inject_extra_fields'] : 1;
613
            $injectExtraFields = rtrim($injectExtraFields, ', ');
614
            if (false === $getCount) {
615
                $select .= " , $injectExtraFields";
616
            }
617
        }
618
619
        $sql = "$select
620
            FROM $tblUser as user
621
            $urlTable
622
            $sqlInjectJoins
623
            $conditionUser
624
            $urlCondition
625
            $invitedUsersCondition
626
            $where
627
            $sqlInjectWhere
628
            ";
629
630
        if (!in_array($direction, ['ASC', 'DESC'])) {
631
            $direction = 'ASC';
632
        }
633
634
        $column = $column <= 2 ? (int) $column : 0;
635
        $from = (int) $from;
636
        $numberOfItems = (int) $numberOfItems;
637
638
        if ($getCount) {
639
            $res = Database::query($sql);
640
            $row = Database::fetch_array($res);
641
642
            return $row['count'];
643
        }
644
645
        $sortByFirstName = api_sort_by_first_name();
646
647
        if ($sortByFirstName) {
648
            if ($column == 1) {
649
                $column = 2;
650
            } elseif ($column == 2) {
651
                $column = 1;
652
            }
653
        }
654
655
        $sql .= " ORDER BY col$column $direction ";
656
        $sql .= " LIMIT $from, $numberOfItems";
657
658
        $res = Database::query($sql);
659
        $users = [];
660
661
        $courseInfo = api_get_course_info($courseCode);
662
        $courseId = $courseInfo['real_id'];
663
664
        $totalSurveys = 0;
665
        $totalExercises = ExerciseLib::get_all_exercises(
666
            $courseInfo,
667
            $sessionId,
668
            false,
669
            null,
670
            false,
671
            3
672
        );
673
674
        if (empty($sessionId)) {
675
            $surveyUserList = [];
676
            $surveyList = SurveyManager::get_surveys($courseCode);
677
            if ($surveyList) {
678
                $totalSurveys = count($surveyList);
679
                foreach ($surveyList as $survey) {
680
                    $userList = SurveyManager::get_people_who_filled_survey(
681
                        $survey['survey_id'],
682
                        false,
683
                        $courseId
684
                    );
685
686
                    foreach ($userList as $user_id) {
687
                        isset($surveyUserList[$user_id]) ? $surveyUserList[$user_id]++ : $surveyUserList[$user_id] = 1;
688
                    }
689
                }
690
            }
691
        }
692
693
        $urlBase = api_get_path(WEB_CODE_PATH).'my_space/myStudents.php?details=true&cid='.$courseId.
694
            '&course='.$courseCode.'&origin=tracking_course&sid='.$sessionId;
695
696
        Session::write('user_id_list', []);
697
        $userIdList = [];
698
699
        if ($exerciseToCheckConfig) {
700
            $addExerciseOption = api_get_setting('exercise.add_exercise_best_attempt_in_report', true);
701
            $exerciseResultsToCheck = [];
702
            if (!empty($addExerciseOption) && isset($addExerciseOption['courses']) &&
703
                isset($addExerciseOption['courses'][$courseCode])
704
            ) {
705
                foreach ($addExerciseOption['courses'][$courseCode] as $exerciseId) {
706
                    $exercise = new Exercise();
707
                    $exercise->read($exerciseId);
708
                    if ($exercise->iid) {
709
                        $exerciseResultsToCheck[] = $exercise;
710
                    }
711
                }
712
            }
713
        }
714
715
        $lpShowMaxProgress = 'true' === api_get_setting('lp.lp_show_max_progress_instead_of_average');
716
        if ('true' === api_get_setting('lp.lp_show_max_progress_or_average_enable_course_level_redefinition')) {
717
            $lpShowProgressCourseSetting = api_get_course_setting('lp_show_max_or_average_progress', $courseInfo, true);
718
            if (in_array($lpShowProgressCourseSetting, ['max', 'average'])) {
719
                $lpShowMaxProgress = ('max' === $lpShowProgressCourseSetting);
720
            }
721
        }
722
723
        while ($user = Database::fetch_array($res, 'ASSOC')) {
724
            $userIdList[] = $user['user_id'];
725
            $user['official_code'] = $user['col0'];
726
            $user['username'] = $user['col3'];
727
            $user['time'] = api_time_to_hms(
728
                Tracking::get_time_spent_on_the_course(
729
                    $user['user_id'],
730
                    $courseId,
731
                    $sessionId
732
                )
733
            );
734
735
            $avgStudentScore = Tracking::get_avg_student_score(
736
                $user['user_id'],
737
                api_get_course_entity($courseId),
738
                [],
739
                api_get_session_entity($sessionId)
740
            );
741
742
            $averageBestScore = Tracking::get_avg_student_score(
743
                $user['user_id'],
744
                api_get_course_entity($courseId),
745
                [],
746
                api_get_session_entity($sessionId),
747
                false,
748
                false,
749
                true
750
            );
751
752
            $avgStudentProgress = Tracking::get_avg_student_progress(
753
                $user['user_id'],
754
                api_get_course_entity($courseId),
755
                [],
756
                api_get_session_entity($sessionId)
757
            );
758
759
            if (empty($avgStudentProgress)) {
760
                $avgStudentProgress = 0;
761
            }
762
            $user['average_progress'] = $avgStudentProgress.'%';
763
764
            $totalUserExercise = Tracking::get_exercise_student_progress(
765
                $totalExercises,
766
                $user['user_id'],
767
                $courseId,
768
                $sessionId
769
            );
770
771
            $user['exercise_progress'] = $totalUserExercise;
772
773
            $totalUserExercise = Tracking::get_exercise_student_average_best_attempt(
774
                $totalExercises,
775
                $user['user_id'],
776
                $courseId,
777
                $sessionId
778
            );
779
780
            $user['exercise_average_best_attempt'] = $totalUserExercise;
781
782
            if (is_numeric($avgStudentScore)) {
783
                $user['student_score'] = $avgStudentScore.'%';
784
            } else {
785
                $user['student_score'] = $avgStudentScore;
786
            }
787
788
            if (is_numeric($averageBestScore)) {
789
                $user['student_score_best'] = $averageBestScore.'%';
790
            } else {
791
                $user['student_score_best'] = $averageBestScore;
792
            }
793
794
            $exerciseResults = [];
795
            if (!empty($exerciseResultsToCheck)) {
796
                foreach ($exerciseResultsToCheck as $exercise) {
797
                    $bestExerciseResult = Event::get_best_attempt_exercise_results_per_user(
798
                        $user['user_id'],
799
                        $exercise->iid,
800
                        $courseId,
801
                        $sessionId,
802
                        false
803
                    );
804
805
                    $best = null;
806
                    if ($bestExerciseResult) {
807
                        $best = $bestExerciseResult['exe_result'] / $bestExerciseResult['exe_weighting'];
808
                        $best = round($best, 2) * 100;
809
                        $best .= '%';
810
                    }
811
                    $exerciseResults['exercise_'.$exercise->iid] = $best;
812
                }
813
            }
814
815
            $user['first_connection'] = Tracking::get_first_connection_date_on_the_course(
816
                $user['user_id'],
817
                $courseId,
818
                $sessionId,
819
                !$exportCsv
820
            );
821
822
            $user['last_connection'] = Tracking::get_last_connection_date_on_the_course(
823
                $user['user_id'],
824
                $courseInfo,
825
                $sessionId,
826
                !$exportCsv
827
            );
828
829
830
            $user['count_assignments'] = Tracking::countStudentPublications(
831
                $courseId,
832
                $sessionId
833
            );
834
835
            $user['count_messages'] = Tracking::countStudentMessages(
836
                $courseId,
837
                $sessionId
838
            );
839
840
841
            $user['lp_finalization_date'] = Tracking::getCourseLpFinalizationDate(
842
                $user['user_id'],
843
                $courseId,
844
                $sessionId,
845
                !$exportCsv
846
            );
847
848
            $user['quiz_finalization_date'] = Tracking::getCourseQuizLastFinalizationDate(
849
                $user['user_id'],
850
                $courseId,
851
                $sessionId,
852
                !$exportCsv
853
            );
854
855
            if ($exportCsv) {
856
                if (!empty($user['first_connection'])) {
857
                    $user['first_connection'] = api_get_local_time($user['first_connection']);
858
                } else {
859
                    $user['first_connection'] = '-';
860
                }
861
                if (!empty($user['last_connection'])) {
862
                    $user['last_connection'] = api_get_local_time($user['last_connection']);
863
                } else {
864
                    $user['last_connection'] = '-';
865
                }
866
                if (!empty($user['lp_finalization_date'])) {
867
                    $user['lp_finalization_date'] = api_get_local_time($user['lp_finalization_date']);
868
                } else {
869
                    $user['lp_finalization_date'] = '-';
870
                }
871
                if (!empty($user['quiz_finalization_date'])) {
872
                    $user['quiz_finalization_date'] = api_get_local_time($user['quiz_finalization_date']);
873
                } else {
874
                    $user['quiz_finalization_date'] = '-';
875
                }
876
            }
877
878
            if (empty($sessionId)) {
879
                $user['survey'] = ($surveyUserList[$user['user_id']] ?? 0).' / '.$totalSurveys;
880
            }
881
882
            $url = $urlBase.'&student='.$user['user_id'];
883
884
            $user['link'] = '<a href="'.$url.'">
885
                        '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
886
                         </a>';
887
888
            // store columns in array $users
889
            $userRow = [];
890
            if ($displaySessionInfo && !empty($sessionId)) {
891
                $sessionInfo = api_get_session_info($sessionId);
892
                $userRow['session_name'] = $sessionInfo['name'];
893
                $userRow['session_startdate'] = $sessionInfo['access_start_date'];
894
                $userRow['session_enddate'] = $sessionInfo['access_end_date'];
895
                $userRow['course_name'] = $courseInfo['name'];
896
            }
897
            $userRow['official_code'] = $user['official_code'];
898
            if ($sortByFirstName) {
899
                $userRow['firstname'] = $user['col2'];
900
                $userRow['lastname'] = $user['col1'];
901
            } else {
902
                $userRow['lastname'] = $user['col1'];
903
                $userRow['firstname'] = $user['col2'];
904
            }
905
            $userRow['username'] = $user['username'];
906
            $userRow['time'] = $user['time'];
907
            $userRow['average_progress'] = $user['average_progress'];
908
            $userRow['exercise_progress'] = $user['exercise_progress'];
909
            $userRow['exercise_average_best_attempt'] = $user['exercise_average_best_attempt'];
910
            $userRow['student_score'] = $user['student_score'];
911
            $userRow['student_score_best'] = $user['student_score_best'];
912
            if (!empty($exerciseResults)) {
913
                foreach ($exerciseResults as $exerciseId => $bestResult) {
914
                    $userRow[$exerciseId] = $bestResult;
915
                }
916
            }
917
918
            $userRow['count_assignments'] = $user['count_assignments'];
919
            $userRow['count_messages'] = $user['count_messages'];
920
921
            $userGroupManager = new UserGroupModel();
922
            if ($exportCsv) {
923
                $userRow['classes'] = implode(
924
                    ',',
925
                    $userGroupManager->getNameListByUser($user['user_id'], UserGroupModel::NORMAL_CLASS)
926
                );
927
            } else {
928
                $userRow['classes'] = $userGroupManager->getLabelsFromNameList(
929
                    $user['user_id'],
930
                    UserGroupModel::NORMAL_CLASS
931
                );
932
            }
933
934
            if (empty($sessionId)) {
935
                $userRow['survey'] = $user['survey'];
936
            } else {
937
                $userSession = SessionManager::getUserSession($user['user_id'], $sessionId);
938
                $userRow['registered_at'] = '';
939
                if ($userSession) {
940
                    $userRow['registered_at'] = api_get_local_time($userSession['registered_at']);
941
                }
942
            }
943
944
            $userRow['first_connection'] = $user['first_connection'];
945
            $userRow['last_connection'] = $user['last_connection'];
946
947
            $userRow['lp_finalization_date'] = $user['lp_finalization_date'];
948
            $userRow['quiz_finalization_date'] = $user['quiz_finalization_date'];
949
950
            // we need to display an additional profile field
951
            if (isset($_GET['additional_profile_field'])) {
952
                $data = Session::read('additional_user_profile_info');
953
954
                $extraFieldInfo = Session::read('extra_field_info');
955
                foreach ($_GET['additional_profile_field'] as $fieldId) {
956
                    if (isset($data[$fieldId]) && isset($data[$fieldId][$user['user_id']])) {
957
                        if (is_array($data[$fieldId][$user['user_id']])) {
958
                            $userRow[$extraFieldInfo[$fieldId]['variable']] = implode(
959
                                ', ',
960
                                $data[$fieldId][$user['user_id']]
961
                            );
962
                        } else {
963
                            $userRow[$extraFieldInfo[$fieldId]['variable']] = $data[$fieldId][$user['user_id']];
964
                        }
965
                    } else {
966
                        $userRow[$extraFieldInfo[$fieldId]['variable']] = '';
967
                    }
968
                }
969
            }
970
971
            $data = Session::read('default_additional_user_profile_info');
972
            $defaultExtraFieldInfo = Session::read('default_extra_field_info');
973
            if (isset($defaultExtraFieldInfo) && isset($data)) {
974
                foreach ($data as $key => $val) {
975
                    if (isset($val[$user['user_id']])) {
976
                        if (is_array($val[$user['user_id']])) {
977
                            $userRow[$defaultExtraFieldInfo[$key]['variable']] = implode(
978
                                ', ',
979
                                $val[$user['user_id']]
980
                            );
981
                        } else {
982
                            $userRow[$defaultExtraFieldInfo[$key]['variable']] = $val[$user['user_id']];
983
                        }
984
                    } else {
985
                        $userRow[$defaultExtraFieldInfo[$key]['variable']] = '';
986
                    }
987
                }
988
            }
989
990
            if (api_get_setting('show_email_addresses') === 'true') {
991
                $userRow['email'] = $user['col4'];
992
            }
993
994
            $userRow['link'] = $user['link'];
995
996
            if ($exportCsv) {
997
                unset($userRow['link']);
998
                $csvContent[] = $userRow;
999
            }
1000
            $users[] = array_values($userRow);
1001
        }
1002
1003
        if ($exportCsv) {
1004
            Session::write('csv_content', $csvContent);
1005
        }
1006
1007
        Session::erase('additional_user_profile_info');
1008
        Session::erase('extra_field_info');
1009
        Session::erase('default_additional_user_profile_info');
1010
        Session::erase('default_extra_field_info');
1011
        Session::write('user_id_list', $userIdList);
1012
1013
        return $users;
1014
    }
1015
1016
    /**
1017
     * Get data for users list in sortable with pagination.
1018
     */
1019
    public static function getTotalTimeReport(
1020
        $from,
1021
        $numberOfItems,
1022
        $column,
1023
        $direction,
1024
        bool $includeInvitedUsers = false
1025
    ): array {
1026
        global $user_ids, $course_code, $export_csv, $session_id;
1027
1028
        $course_code = Database::escape_string($course_code);
1029
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
1030
        $tblUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
1031
        $accessUrlId = api_get_current_access_url_id();
1032
1033
        // get all users data from a course for sortable with limit
1034
        if (is_array($user_ids)) {
1035
            $user_ids = array_map('intval', $user_ids);
1036
            $conditionUser = " WHERE user.user_id IN (".implode(',', $user_ids).") ";
1037
        } else {
1038
            $user_ids = intval($user_ids);
1039
            $conditionUser = " WHERE user.user_id = $user_ids ";
1040
        }
1041
1042
        $urlTable = null;
1043
        $urlCondition = null;
1044
        if (api_is_multiple_url_enabled()) {
1045
            $urlTable = ", ".$tblUrlRelUser." as url_users";
1046
            $urlCondition = " AND user.user_id = url_users.user_id AND access_url_id='$accessUrlId'";
1047
        }
1048
1049
        $invitedUsersCondition = '';
1050
        if (!$includeInvitedUsers) {
1051
            $invitedUsersCondition = " AND user.status != ".INVITEE;
1052
        }
1053
1054
        $sql = "SELECT  user.user_id as user_id,
1055
                    user.official_code  as col0,
1056
                    user.lastname       as col1,
1057
                    user.firstname      as col2,
1058
                    user.username       as col3
1059
                FROM $tblUser as user $urlTable
1060
                $conditionUser $urlCondition $invitedUsersCondition";
1061
1062
        if (!in_array($direction, ['ASC', 'DESC'])) {
1063
            $direction = 'ASC';
1064
        }
1065
1066
        $column = (int) $column;
1067
        $from = (int) $from;
1068
        $numberOfItems = (int) $numberOfItems;
1069
1070
        $sql .= " ORDER BY col$column $direction ";
1071
        $sql .= " LIMIT $from,$numberOfItems";
1072
1073
        $res = Database::query($sql);
1074
        $users = [];
1075
1076
        $sortByFirstName = api_sort_by_first_name();
1077
        $courseInfo = api_get_course_info($course_code);
1078
        $courseId = $courseInfo['real_id'];
1079
1080
        while ($user = Database::fetch_array($res, 'ASSOC')) {
1081
            $user['official_code'] = $user['col0'];
1082
            $user['lastname'] = $user['col1'];
1083
            $user['firstname'] = $user['col2'];
1084
            $user['username'] = $user['col3'];
1085
1086
            $totalCourseTime = Tracking::get_time_spent_on_the_course(
1087
                $user['user_id'],
1088
                $courseId,
1089
                $session_id
1090
            );
1091
1092
            $user['time'] = api_time_to_hms($totalCourseTime);
1093
            $totalLpTime = Tracking::get_time_spent_in_lp(
1094
                $user['user_id'],
1095
                api_get_course_entity($courseId),
1096
                [],
1097
                $session_id
1098
            );
1099
1100
            $warning = '';
1101
            if ($totalLpTime > $totalCourseTime) {
1102
                $warning = '&nbsp;'.Display::label(get_lang('TimeDifference'), 'danger');
1103
            }
1104
1105
            $user['total_lp_time'] = api_time_to_hms($totalLpTime).$warning;
1106
1107
            $user['first_connection'] = Tracking::get_first_connection_date_on_the_course(
1108
                $user['user_id'],
1109
                $courseId,
1110
                $session_id
1111
            );
1112
            $user['last_connection'] = Tracking::get_last_connection_date_on_the_course(
1113
                $user['user_id'],
1114
                $courseInfo,
1115
                $session_id,
1116
                $export_csv === false
1117
            );
1118
1119
            $user['link'] = '<center>
1120
                             <a href="../my_space/myStudents.php?student='.$user['user_id'].'&details=true&cid='.$courseId.'&sid='.$session_id.'&course='.$course_code.'&origin=tracking_course&id_session='.$session_id.'">
1121
                             '.Display::return_icon('2rightarrow.png', get_lang('Details')).'
1122
                             </a>
1123
                         </center>';
1124
1125
            // store columns in array $users
1126
            $userRow = [];
1127
            $userRow['official_code'] = $user['official_code']; //0
1128
            if ($sortByFirstName) {
1129
                $userRow['firstname'] = $user['firstname'];
1130
                $userRow['lastname'] = $user['lastname'];
1131
            } else {
1132
                $userRow['lastname'] = $user['lastname'];
1133
                $userRow['firstname'] = $user['firstname'];
1134
            }
1135
            $userRow['username'] = $user['username'];
1136
            $userRow['time'] = $user['time'];
1137
            $userRow['total_lp_time'] = $user['total_lp_time'];
1138
            $userRow['first_connection'] = $user['first_connection'];
1139
            $userRow['last_connection'] = $user['last_connection'];
1140
1141
            $userRow['link'] = $user['link'];
1142
            $users[] = array_values($userRow);
1143
        }
1144
1145
        return $users;
1146
    }
1147
1148
    /**
1149
     * Determines the remaining actions for a session and returns a string with the results.
1150
     */
1151
    public static function actionsLeft($current, $sessionId = 0): string
1152
    {
1153
        $usersLink = Display::url(
1154
            Display::return_icon('user.png', get_lang('StudentsTracking'), [], ICON_SIZE_MEDIUM),
1155
            'courseLog.php?'.api_get_cidreq(true, false)
1156
        );
1157
1158
        $groupsLink = Display::url(
1159
            Display::return_icon('group.png', get_lang('GroupReporting'), [], ICON_SIZE_MEDIUM),
1160
            'course_log_groups.php?'.api_get_cidreq()
1161
        );
1162
1163
        $resourcesLink = Display::url(
1164
            Display::return_icon('tools.png', get_lang('ResourcesTracking'), [], ICON_SIZE_MEDIUM),
1165
            'course_log_resources.php?'.api_get_cidreq(true, false)
1166
        );
1167
1168
        $courseLink = Display::url(
1169
            Display::return_icon('course.png', get_lang('CourseTracking'), [], ICON_SIZE_MEDIUM),
1170
            'course_log_tools.php?'.api_get_cidreq(true, false)
1171
        );
1172
1173
        $examLink = Display::url(
1174
            Display::return_icon('quiz.png', get_lang('ExamTracking'), [], ICON_SIZE_MEDIUM),
1175
            api_get_path(WEB_CODE_PATH).'tracking/exams.php?'.api_get_cidreq()
1176
        );
1177
1178
        $eventsLink = Display::url(
1179
            Display::return_icon('security.png', get_lang('EventsReport'), [], ICON_SIZE_MEDIUM),
1180
            api_get_path(WEB_CODE_PATH).'tracking/course_log_events.php?'.api_get_cidreq()
1181
        );
1182
1183
        $lpLink = Display::url(
1184
            Display::return_icon('scorms.png', get_lang('CourseLearningPathsGenericStats'), [], ICON_SIZE_MEDIUM),
1185
            api_get_path(WEB_CODE_PATH).'tracking/lp_report.php?'.api_get_cidreq()
1186
        );
1187
1188
        $attendanceLink = '';
1189
        if (!empty($sessionId)) {
1190
            $attendanceLink = Display::url(
1191
                Display::return_icon('attendance_list.png', get_lang('Logins'), [], ICON_SIZE_MEDIUM),
1192
                api_get_path(WEB_CODE_PATH).'attendance/index.php?'.api_get_cidreq().'&action=calendar_logins'
1193
            );
1194
        }
1195
1196
        switch ($current) {
1197
            case 'users':
1198
                $usersLink = Display::url(
1199
                    Display::return_icon(
1200
                        'user_na.png',
1201
                        get_lang('StudentsTracking'),
1202
                        [],
1203
                        ICON_SIZE_MEDIUM
1204
                    ),
1205
                    '#'
1206
                );
1207
                break;
1208
            case 'groups':
1209
                $groupsLink = Display::url(
1210
                    Display::return_icon('group_na.png', get_lang('GroupReporting'), [], ICON_SIZE_MEDIUM),
1211
                    '#'
1212
                );
1213
                break;
1214
            case 'courses':
1215
                $courseLink = Display::url(
1216
                    Display::return_icon('course_na.png', get_lang('CourseTracking'), [], ICON_SIZE_MEDIUM),
1217
                    '#'
1218
                );
1219
                break;
1220
            case 'resources':
1221
                $resourcesLink = Display::url(
1222
                    Display::return_icon(
1223
                        'tools_na.png',
1224
                        get_lang('ResourcesTracking'),
1225
                        [],
1226
                        ICON_SIZE_MEDIUM
1227
                    ),
1228
                    '#'
1229
                );
1230
                break;
1231
            case 'exams':
1232
                $examLink = Display::url(
1233
                    Display::return_icon('quiz_na.png', get_lang('ExamTracking'), [], ICON_SIZE_MEDIUM),
1234
                    '#'
1235
                );
1236
                break;
1237
            case 'logs':
1238
                $eventsLink = Display::url(
1239
                    Display::return_icon('security_na.png', get_lang('EventsReport'), [], ICON_SIZE_MEDIUM),
1240
                    '#'
1241
                );
1242
                break;
1243
            case 'attendance':
1244
                if (!empty($sessionId)) {
1245
                    $attendanceLink = Display::url(
1246
                        Display::return_icon('attendance_list.png', get_lang('Logins'), [], ICON_SIZE_MEDIUM),
1247
                        '#'
1248
                    );
1249
                }
1250
                break;
1251
            case 'lp':
1252
                $lpLink = Display::url(
1253
                    Display::return_icon(
1254
                        'scorms_na.png',
1255
                        get_lang('CourseLearningPathsGenericStats'),
1256
                        [],
1257
                        ICON_SIZE_MEDIUM
1258
                    ),
1259
                    '#'
1260
                );
1261
                break;
1262
        }
1263
1264
        $items = [
1265
            $usersLink,
1266
            $groupsLink,
1267
            $courseLink,
1268
            $resourcesLink,
1269
            $examLink,
1270
            $eventsLink,
1271
            $lpLink,
1272
            $attendanceLink,
1273
        ];
1274
1275
        return implode('', $items).'&nbsp;';
1276
    }
1277
1278
    public static function calcBestScoreAverageNotInLP(
1279
        array $exerciseList,
1280
        array $usersInGroup,
1281
        int $cId,
1282
        int $sessionId = 0,
1283
        bool $returnFormatted = false
1284
    ) {
1285
        if (empty($exerciseList) || empty($usersInGroup)) {
1286
            return 0;
1287
        }
1288
1289
        $bestScoreAverageNotInLP = 0;
1290
1291
        foreach ($exerciseList as $exerciseData) {
1292
            foreach ($usersInGroup as $userId) {
1293
                $results = Event::get_best_exercise_results_by_user(
1294
                    $exerciseData['iid'],
1295
                    $cId,
1296
                    $sessionId,
1297
                    $userId
1298
                );
1299
1300
                $scores = array_map(
1301
                    function (array $result) {
1302
                        return empty($result['exe_weighting']) ? 0 : $result['exe_result'] / $result['exe_weighting'];
1303
                    },
1304
                    $results
1305
                );
1306
1307
                $bestScoreAverageNotInLP += $scores ? max($scores) : 0;
1308
            }
1309
        }
1310
1311
        $rounded = round(
1312
            $bestScoreAverageNotInLP / count($exerciseList) * 100 / count($usersInGroup),
1313
            2
1314
        );
1315
1316
        if ($returnFormatted) {
1317
            return sprintf(get_lang('XPercent'), $rounded);
1318
        }
1319
1320
        return $rounded;
1321
    }
1322
}
1323