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

TrackingCourseLog::getUserData()   F

Complexity

Conditions 66

Size

Total Lines 477
Code Lines 308

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 66
eloc 308
nop 11
dl 0
loc 477
rs 3.3333
c 1
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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