SessionManager::getSessionIdFromOriginalId()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 2
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Asset;
6
use Chamilo\CoreBundle\Entity\Course;
7
use Chamilo\CoreBundle\Entity\ExtraField;
8
use Chamilo\CoreBundle\Entity\SequenceResource;
9
use Chamilo\CoreBundle\Entity\Session;
10
use Chamilo\CoreBundle\Entity\SessionCategory;
11
use Chamilo\CoreBundle\Entity\SessionRelCourse;
12
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
13
use Chamilo\CoreBundle\Entity\SessionRelUser;
14
use Chamilo\CoreBundle\Entity\User;
15
use Chamilo\CoreBundle\Entity\UserAuthSource;
16
use Chamilo\CoreBundle\Enums\ObjectIcon;
17
use Chamilo\CoreBundle\Enums\StateIcon;
18
use Chamilo\CoreBundle\Framework\Container;
19
use Chamilo\CourseBundle\Entity\CStudentPublication;
20
use Chamilo\CourseBundle\Entity\CSurvey;
21
use ExtraField as ExtraFieldModel;
22
use Monolog\Logger;
23
24
/**
25
 * This is the session library for Chamilo
26
 * (as in courses>session, not as in PHP session)
27
 * All main sessions functions should be placed here.
28
 * This class provides methods for sessions management.
29
 * Include/require it in your code to use its features.
30
 */
31
class SessionManager
32
{
33
    public const STATUS_PLANNED = 1;
34
    public const STATUS_PROGRESS = 2;
35
    public const STATUS_FINISHED = 3;
36
    public const STATUS_CANCELLED = 4;
37
    // See BT#4871
38
    public const SESSION_CHANGE_USER_REASON_SCHEDULE = 1;
39
    public const SESSION_CHANGE_USER_REASON_CLASSROOM = 2;
40
    public const SESSION_CHANGE_USER_REASON_LOCATION = 3;
41
    public const SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION = 4;
42
    public const DEFAULT_VISIBILITY = 4;  //SESSION_AVAILABLE
43
44
    public function __construct()
45
    {
46
    }
47
48
    /**
49
     * Fetches a session from the database.
50
     *
51
     * @param int $id Session Id
52
     *
53
     * @return array Session details
54
     */
55
    public static function fetch($id)
56
    {
57
        if (empty($id)) {
58
            return [];
59
        }
60
61
        $session = api_get_session_entity($id);
62
63
        if (!$session) {
64
            return [];
65
        }
66
67
        $result = [
68
            'id' => $session->getId(),
69
            'session_category_id' => $session->getCategory() ? $session->getCategory()->getId() : null,
70
            'name' => $session->getTitle(), // only provided for backwards compatibility - should be removed in the long run
71
            'title' => $session->getTitle(),
72
            'description' => $session->getDescription(),
73
            'show_description' => $session->getShowDescription(),
74
            'duration' => $session->getDuration(),
75
            'nbr_courses' => $session->getNbrCourses(),
76
            'nbr_users' => $session->getNbrUsers(),
77
            'nbr_classes' => $session->getNbrClasses(),
78
            'visibility' => $session->getVisibility(),
79
            'promotion_id' => $session->getPromotion() ? $session->getPromotion()->getId() : 0,
80
            'display_start_date' => $session->getDisplayStartDate()?->format('Y-m-d H:i:s'),
81
            'display_end_date' => $session->getDisplayEndDate()?->format('Y-m-d H:i:s'),
82
            'access_start_date' => $session->getAccessStartDate()?->format('Y-m-d H:i:s'),
83
            'access_end_date' => $session->getAccessEndDate()?->format('Y-m-d H:i:s'),
84
            'coach_access_start_date' => $session->getCoachAccessStartDate()?->format('Y-m-d H:i:s'),
85
            'coach_access_end_date' => $session->getCoachAccessEndDate()?->format('Y-m-d H:i:s'),
86
            'send_subscription_notification' => $session->getSendSubscriptionNotification(),
87
            'status' => $session->getStatus(),
88
            'status_label' => self::getStatusLabel($session->getStatus()),
89
        ];
90
91
        // Converted to local values
92
        $variables = [
93
            'display_start_date',
94
            'display_end_date',
95
            'access_start_date',
96
            'access_end_date',
97
            'coach_access_start_date',
98
            'coach_access_end_date',
99
        ];
100
101
        foreach ($variables as $value) {
102
            $result[$value.'_to_local_time'] = null;
103
            if (!empty($result[$value])) {
104
                $result[$value.'_to_local_time'] = api_get_local_time($result[$value]);
105
            }
106
        }
107
108
        return $result;
109
    }
110
111
    /**
112
     * Create a session.
113
     *
114
     * @author Carlos Vargas <[email protected]>, from existing code
115
     *
116
     * @param string $name
117
     * @param string $startDate                    (YYYY-MM-DD hh:mm:ss)
118
     * @param string $endDate                      (YYYY-MM-DD hh:mm:ss)
119
     * @param string $displayStartDate             (YYYY-MM-DD hh:mm:ss)
120
     * @param string $displayEndDate               (YYYY-MM-DD hh:mm:ss)
121
     * @param string $coachStartDate               (YYYY-MM-DD hh:mm:ss)
122
     * @param string $coachEndDate                 (YYYY-MM-DD hh:mm:ss)
123
     * @param array  $coachesId                      If int, this is the session coach id,
124
     *                                             if string, the coach ID will be looked for from the user table
125
     * @param int    $sessionCategoryId            ID of the session category in which this session is registered
126
     * @param int    $visibility                   Visibility after end date (0 = read-only, 1 = invisible, 2 = accessible)
127
     * @param bool   $fixSessionNameIfExists
128
     * @param string $duration
129
     * @param string $description                  Optional. The session description
130
     * @param int    $showDescription              Optional. Whether show the session description
131
     * @param array  $extraFields
132
     * @param int    $sessionAdminId               Optional. If this sessions was created by a session admin, assign it to him
133
     * @param bool   $sendSubscriptionNotification Optional.
134
     *                                             Whether send a mail notification to users being subscribed
135
     * @param int    $accessUrlId                  Optional.
136
     * @param int    $status
137
     *
138
     * @return mixed Session ID on success, error message otherwise
139
     *
140
     * @todo use an array to replace all this parameters or use the model.lib.php ...
141
     */
142
    public static function create_session(
143
        $name,
144
        $startDate,
145
        $endDate,
146
        $displayStartDate,
147
        $displayEndDate,
148
        $coachStartDate,
149
        $coachEndDate,
150
        array $coachesId,
151
        $sessionCategoryId,
152
        $visibility = 1,
153
        $fixSessionNameIfExists = false,
154
        $duration = null,
155
        $description = null,
156
        $showDescription = 0,
157
        $extraFields = [],
158
        $sessionAdminId = 0,
159
        $sendSubscriptionNotification = false,
160
        $accessUrlId = 0,
161
        $status = 0,
162
        $notifyBoss = false,
163
        $parentId = null,
164
        $daysBeforeFinishingForReinscription = null,
165
        $lastRepetition = false,
166
        $daysBeforeFinishingToCreateNewRepetition = null,
167
        $validityInDays = null
168
    ) {
169
        global $_configuration;
170
171
        // Check portal limits
172
        $accessUrlId = api_is_multiple_url_enabled()
173
            ? (empty($accessUrlId) ? api_get_current_access_url_id() : (int) $accessUrlId)
174
            : 1;
175
176
        $hostingLimitSessions = get_hosting_limit($accessUrlId, 'sessions');
177
178
        if ($hostingLimitSessions !== null && $hostingLimitSessions > 0) {
179
            $num = self::count_sessions();
180
            if ($num >= $hostingLimitSessions) {
181
                api_warn_hosting_contact('hosting_limit_sessions');
182
183
                return get_lang('The number of sessions limit for this portal has been reached');
184
            }
185
        }
186
187
        $name = trim($name);
188
        $sessionCategoryId = (int) $sessionCategoryId;
189
        $visibility = (int) $visibility;
190
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
191
192
        if (empty($name)) {
193
            return get_lang('A title is required');
194
        } elseif (!empty($startDate) && !api_is_valid_date($startDate, 'Y-m-d H:i') &&
195
            !api_is_valid_date($startDate, 'Y-m-d H:i:s')
196
        ) {
197
            return get_lang('Invalid start date was given.');
198
        } elseif (!empty($endDate) && !api_is_valid_date($endDate, 'Y-m-d H:i') &&
199
            !api_is_valid_date($endDate, 'Y-m-d H:i:s')
200
        ) {
201
            return get_lang('Invalid end date was given.');
202
        } elseif (!empty($startDate) && !empty($endDate) && $startDate >= $endDate) {
203
            return get_lang('The first date should be before the end date');
204
        } else {
205
            $ready_to_create = false;
206
            if ($fixSessionNameIfExists) {
207
                $name = self::generateNextSessionName($name);
208
                if ($name) {
209
                    $ready_to_create = true;
210
                } else {
211
                    return get_lang('Session title already exists');
212
                }
213
            } else {
214
                $sessionRepo = Database::getManager()->getRepository(Session::class);
215
                $existingSession = $sessionRepo->findOneBy(['title' => $name]);
216
                if ($existingSession !== null) {
217
                    return get_lang('Session title already exists');
218
                }
219
                $ready_to_create = true;
220
            }
221
222
            if ($ready_to_create) {
223
                $session = new Session();
224
                $session
225
                    ->setTitle($name)
226
                    ->setVisibility($visibility)
227
                    ->setDescription($description)
228
                    ->setShowDescription(1 === $showDescription)
229
                    ->setSendSubscriptionNotification((bool) $sendSubscriptionNotification)
230
                    ->setNotifyBoss((bool) $notifyBoss)
231
                    ->setParentId($parentId)
232
                    ->setDaysToReinscription((int) $daysBeforeFinishingForReinscription)
233
                    ->setLastRepetition($lastRepetition)
234
                    ->setDaysToNewRepetition((int) $daysBeforeFinishingToCreateNewRepetition)
235
                    ->setValidityInDays((int) $validityInDays)
236
                    ->setStatus($status)
237
                ;
238
239
                if (!empty($duration)) {
240
                    $session->setDuration((int) $duration);
241
                } else {
242
                    $startDate = $startDate ? api_get_utc_datetime($startDate, true, true) : null;
243
                    $endDate = $endDate ? api_get_utc_datetime($endDate, true, true) : null;
244
                    $displayStartDate = $displayStartDate ? api_get_utc_datetime($displayStartDate, true, true) : null;
245
                    $displayEndDate = $displayEndDate ? api_get_utc_datetime($displayEndDate, true, true) : null;
246
                    $coachStartDate = $coachStartDate ? api_get_utc_datetime($coachStartDate, true, true) : null;
247
                    $coachEndDate = $coachEndDate ? api_get_utc_datetime($coachEndDate, true, true) : null;
248
249
                    $session->setAccessStartDate($startDate);
250
                    $session->setAccessEndDate($endDate);
251
                    $session->setDisplayStartDate($displayStartDate);
252
                    $session->setDisplayEndDate($displayEndDate);
253
                    $session->setCoachAccessStartDate($coachStartDate);
254
                    $session->setCoachAccessEndDate($coachEndDate);
255
                }
256
257
                foreach ($coachesId as $coachId) {
258
                    $session->addGeneralCoach(api_get_user_entity($coachId));
259
                }
260
261
                $sessionAdminId = !empty($sessionAdminId) ? $sessionAdminId : api_get_user_id();
262
263
                $session->addSessionAdmin(api_get_user_entity($sessionAdminId));
264
265
                $em = Database::getManager();
266
                $em->persist($session);
267
                $em->flush();
268
                $session_id = $session->getId();
269
270
                if (!empty($session_id)) {
271
                    $extraFields['item_id'] = $session_id;
272
                    $sessionFieldValue = new ExtraFieldValue('session');
273
                    $sessionFieldValue->saveFieldValues($extraFields);
274
275
                    // add event to system log
276
                    $user_id = api_get_user_id();
277
                    Event::addEvent(
278
                        LOG_SESSION_CREATE,
279
                        LOG_SESSION_ID,
280
                        $session_id,
281
                        api_get_utc_datetime(),
282
                        $user_id
283
                    );
284
                }
285
286
                return $session_id;
287
            }
288
        }
289
    }
290
291
    /**
292
     * @param string $name
293
     *
294
     * @return bool
295
     */
296
    public static function sessionNameExists($name)
297
    {
298
        $name = Database::escape_string($name);
299
        $sql = "SELECT COUNT(*) as count FROM ".Database::get_main_table(TABLE_MAIN_SESSION)."
300
                WHERE title = '$name'";
301
        $result = Database::fetch_array(Database::query($sql));
302
303
        return $result['count'] > 0;
304
    }
305
306
    /**
307
     * @param string $where_condition
308
     *
309
     * @return mixed
310
     */
311
    public static function get_count_admin($where_condition = '')
312
    {
313
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
314
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
315
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
316
        $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
317
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
318
319
        $where = 'WHERE 1=1 ';
320
        $user_id = api_get_user_id();
321
        $extraJoin = '';
322
323
        if (api_is_session_admin() &&
324
            'false' == api_get_setting('allow_session_admins_to_manage_all_sessions')
325
        ) {
326
            $where .= " AND (
327
                            sru.user_id = '$user_id' AND
328
                            sru.relation_type IN ('".Session::DRH.", ".Session::SESSION_ADMIN."')
329
                            )
330
                      ";
331
332
            $extraJoin = " INNER JOIN $tbl_session_rel_user sru
333
                           ON sru.session_id = s.id ";
334
        }
335
336
        $today = api_get_utc_datetime();
337
        $today = api_strtotime($today, 'UTC');
338
        $today = date('Y-m-d', $today);
339
340
        if (!empty($where_condition)) {
341
            $where_condition = str_replace("(  session_active = ':'  )", '1=1', $where_condition);
342
343
            $where_condition = str_replace('category_name', 'sc.title', $where_condition);
344
            $where_condition = str_replace(
345
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
346
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
347
                $where_condition
348
            );
349
            $where_condition = str_replace(
350
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
351
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
352
                $where_condition
353
            );
354
        } else {
355
            $where_condition = " AND 1 = 1";
356
        }
357
358
        $courseCondition = null;
359
        if (strpos($where_condition, 'c.id')) {
360
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
361
            $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
362
            $courseCondition = " INNER JOIN $table course_rel_session
363
                                 ON (s.id = course_rel_session.session_id)
364
                                 INNER JOIN $tableCourse c
365
                                 ON (course_rel_session.c_id = c.id)
366
                                ";
367
        }
368
369
        $sql = "SELECT COUNT(id) as total_rows FROM (
370
                SELECT DISTINCT
371
                 IF (
372
					(s.access_start_date <= '$today' AND '$today' <= s.access_end_date) OR
373
                    (s.access_start_date IS NULL AND s.access_end_date IS NULL ) OR
374
					(s.access_start_date <= '$today' AND s.access_end_date IS NULL) OR
375
					('$today' <= s.access_end_date AND s.access_start_date IS NULL)
376
				, 1, 0) as session_active,
377
                s.id
378
                FROM $tbl_session s
379
                LEFT JOIN $tbl_session_category sc
380
                ON s.session_category_id = sc.id
381
                INNER JOIN $tbl_user u
382
                ON s.id_coach = u.id
383
                $courseCondition
384
                $extraJoin
385
                $where $where_condition ) as session_table";
386
387
        if (api_is_multiple_url_enabled()) {
388
            $access_url_id = api_get_current_access_url_id();
389
            if (-1 != $access_url_id) {
390
                $where .= " AND ar.access_url_id = $access_url_id ";
391
392
                $sql = "SELECT count(id) as total_rows FROM (
393
                SELECT DISTINCT
394
                  IF (
395
					(s.access_start_date <= '$today' AND '$today' <= s.access_end_date) OR
396
                    (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
397
					(s.access_start_date <= '$today' AND s.access_end_date IS NULL) OR
398
					('$today' <= s.access_end_date AND s.access_start_date IS NULL)
399
				, 1, 0)
400
				as session_active,
401
				s.id
402
                FROM $tbl_session s
403
                    LEFT JOIN  $tbl_session_category sc
404
                    ON s.session_category_id = sc.id
405
                    INNER JOIN $tbl_user u ON s.id_coach = u.id
406
                    INNER JOIN $table_access_url_rel_session ar
407
                    ON ar.session_id = s.id
408
                    $courseCondition
409
                    $extraJoin
410
                $where $where_condition) as session_table";
411
            }
412
        }
413
414
        $sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
415
416
        $result_rows = Database::query($sql);
417
        $row = Database::fetch_array($result_rows);
418
        $num = $row['total_rows'];
419
420
        return $num;
421
    }
422
423
    /**
424
     * Get session list for a session admin or platform admin.
425
     *
426
     * @param int   $userId   User Id for the session admin.
427
     * @param array $options  Order and limit keys.
428
     * @param bool  $getCount Whether to get all the results or only the count.
429
     * @param array $columns  Columns from jqGrid.
430
     * @param string $listType
431
     * @param array $extraFieldsToLoad
432
     * @param bool  $formatted
433
     *
434
     * @return array
435
     */
436
    public static function getSessionsForAdmin(
437
        $userId,
438
        $options = [],
439
        $getCount = false,
440
        $columns = [],
441
        $listType = 'all',
442
        $extraFieldsToLoad = [],
443
        $formatted = false,
444
        $language = ''
445
    ) {
446
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
447
        $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
448
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
449
450
        $where = 'WHERE 1 = 1 ';
451
452
        $userId = (int) $userId;
453
454
        $extraFieldModel = new ExtraFieldModel('session');
455
        $conditions = $extraFieldModel->parseConditions($options);
456
457
        $sqlInjectJoins = $conditions['inject_joins'];
458
        $where .= $conditions['where'];
459
        $sqlInjectWhere = $conditions['inject_where'];
460
        $injectExtraFields = $conditions['inject_extra_fields'];
461
        $order = empty($conditions['order']) ? ' ORDER BY s.title ASC' : $conditions['order'];
462
        $limit = $conditions['limit'];
463
464
        $isMakingOrder = false;
465
        $showCountUsers = false;
466
467
        if (true === $getCount) {
468
            $select = ' SELECT count(DISTINCT s.id) as total_rows ';
469
        } else {
470
            if (!empty($columns['column_model'])) {
471
                foreach ($columns['column_model'] as $column) {
472
                    if ('users' == $column['name']) {
473
                        $showCountUsers = true;
474
                        break;
475
                    }
476
                }
477
            }
478
479
            $select =
480
                "SELECT DISTINCT
481
                     s.title,
482
                     s.display_start_date,
483
                     s.display_end_date,
484
                     access_start_date,
485
                     access_end_date,
486
                     s.visibility,
487
                     s.session_category_id,
488
                     s.id
489
             ";
490
491
            // ofaj fix
492
            if (!empty($extraFieldsToLoad)) {
493
                $select = "SELECT DISTINCT s.* ";
494
            }
495
            $select .= ', status';
496
497
            if ('replication' === $listType) {
498
                $select .= ', parent_id';
499
            }
500
501
            if (isset($options['order'])) {
502
                $isMakingOrder = 0 === strpos($options['order'], 'category_name');
503
            }
504
        }
505
506
        $isFilteringSessionCategory = false !== strpos($where, 'category_name');
507
        $isFilteringSessionCategoryWithName = false !== strpos($where, 'sc.title');
508
509
        if ($isMakingOrder || $isFilteringSessionCategory || $isFilteringSessionCategoryWithName) {
510
            $sqlInjectJoins .= " LEFT JOIN $sessionCategoryTable sc ON s.session_category_id = sc.id ";
511
512
            if ($isFilteringSessionCategory) {
513
                $where = str_replace('category_name', 'sc.title', $where);
514
            }
515
516
            if ($isMakingOrder) {
517
                $order = str_replace('category_name', 'sc.title', $order);
518
            }
519
        }
520
521
        if (!empty($language)) {
522
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
523
            $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
524
            $sqlInjectJoins .= " INNER JOIN $table sc ON (sc.session_id = s.id)
525
                               INNER JOIN $tableCourse c ON (sc.c_id = c.id)";
526
            $language = Database::escape_string($language);
527
528
            // Get the isoCode to filter course_language
529
            $isoCode = '';
530
            $languageId = api_get_language_id($language);
531
            if (!empty($languageId)) {
532
                $languageInfo = api_get_language_info($languageId);
533
                $isoCode = $languageInfo['isocode'];
534
            }
535
            if ('true' === api_get_setting('language.allow_course_multiple_languages')) {
536
                $tblExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
537
                $tblExtraFieldValue = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
538
                $extraFieldType = ExtraField::COURSE_FIELD_TYPE;
539
                $sql = "SELECT id FROM $tblExtraField WHERE item_type = $extraFieldType AND variable = 'multiple_language'";
540
                $rs = Database::query($sql);
541
                if (Database::num_rows($rs) > 0) {
542
                    $fieldId = Database::result($rs, 0, 0);
543
                    $sqlInjectJoins .= " LEFT JOIN $tblExtraFieldValue cfv ON (c.id = cfv.item_id AND cfv.field_id = $fieldId)";
544
                    $where .= " AND (c.course_language = '$isoCode' OR cfv.field_value LIKE '%$language%')";
545
                } else {
546
                    $where .= " AND c.course_language = '$isoCode' ";
547
                }
548
            } else {
549
                $where .= " AND c.course_language = '$isoCode' ";
550
            }
551
        }
552
553
        $allowSessionAdminsToManageAllSessions = !api_is_platform_admin()
554
            && api_is_session_admin()
555
            && 'false' === api_get_setting('allow_session_admins_to_manage_all_sessions');
556
557
        $allowTeachersToCreateSessions = !api_is_platform_admin()
558
            && api_is_teacher()
559
            && 'true' === api_get_setting('allow_teachers_to_create_sessions');
560
561
        if ($allowSessionAdminsToManageAllSessions || $allowTeachersToCreateSessions) {
562
            $sqlInjectJoins .= " INNER JOIN $tblSessionRelUser sru ON sru.session_id = s.id ";
563
564
            $relationTypeList = [];
565
566
            if ($allowSessionAdminsToManageAllSessions) {
567
                $relationTypeList[] = Session::SESSION_ADMIN;
568
            }
569
570
            if ($allowTeachersToCreateSessions) {
571
                $relationTypeList[] = Session::GENERAL_COACH;
572
            }
573
574
            $where .= " AND (sru.user_id = $userId AND sru.relation_type IN(".implode(',', $relationTypeList)."))";
575
        }
576
577
        $query = "$select";
578
        if (!empty($injectExtraFields)) {
579
            $injectExtraFields = rtrim(trim($injectExtraFields), ',');
580
            $query .= ", $injectExtraFields";
581
        }
582
        $query .= " FROM $tblSession s $sqlInjectJoins $where $sqlInjectWhere";
583
584
        if (api_is_multiple_url_enabled()) {
585
            $tblAccessUrlRelSession = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
586
            $accessUrlId = api_get_current_access_url_id();
587
588
            if (-1 != $accessUrlId) {
589
                $where .= " AND ar.access_url_id = $accessUrlId ";
590
                $query = "$select
591
                    FROM $tblSession s $sqlInjectJoins
592
                    INNER JOIN $tblAccessUrlRelSession ar
593
                    ON (ar.session_id = s.id) $where";
594
            }
595
        }
596
597
        $date = api_get_utc_datetime();
598
599
        switch ($listType) {
600
            case 'all':
601
                break;
602
            case 'active':
603
                $query .= "AND (
604
                    (s.access_end_date IS NULL)
605
                    OR
606
                    (
607
                    s.access_start_date IS NOT NULL AND
608
                    s.access_end_date IS NOT NULL AND
609
                    s.access_start_date <= '$date' AND s.access_end_date >= '$date')
610
                    OR
611
                    (
612
                        s.access_start_date IS NULL AND
613
                        s.access_end_date IS NOT NULL AND
614
                        s.access_end_date >= '$date'
615
                    )
616
                )";
617
                break;
618
            case 'close':
619
                $query .= "AND (
620
                    (
621
                    s.access_start_date IS NOT NULL AND
622
                    s.access_end_date IS NOT NULL AND
623
                    s.access_start_date <= '$date' AND s.access_end_date <= '$date')
624
                    OR
625
                    (
626
                        s.access_start_date IS NULL AND
627
                        s.access_end_date IS NOT NULL AND
628
                        s.access_end_date <= '$date'
629
                    )
630
                )";
631
                break;
632
            case 'replication':
633
                $formatted = false;
634
                $query .= "AND s.days_to_new_repetition IS NOT NULL
635
               AND (SELECT COUNT(id) FROM session AS child WHERE child.parent_id = s.id) <= 1";
636
                break;
637
        }
638
639
        $query .= $order;
640
        $query .= $limit;
641
        if (!$formatted) {
642
            $result = Database::query($query);
643
            $sessions = Database::store_result($result, 'ASSOC');
644
            if ($showCountUsers && !$getCount) {
645
                foreach ($sessions as &$session) {
646
                    $result = Database::query("SELECT COUNT(session_id) AS nbr
647
                    FROM session_rel_user WHERE session_id = {$session['id']} AND relation_type = ".Session::STUDENT);
648
                    $session['users'] = Database::fetch_assoc($result)['nbr'];
649
                }
650
            }
651
652
            if ('replication' === $listType) {
653
                $formattedSessions = [];
654
                foreach ($sessions as $session) {
655
                    $formattedSessions[] = $session;
656
                    if (isset($session['id'])) {
657
                        $childSessions = array_filter($sessions, fn($s) => isset($s['parent_id']) && $s['parent_id'] === $session['id']);
658
                        foreach ($childSessions as $childSession) {
659
                            $childSession['title'] = '-- ' . $childSession['title'];
660
                            $formattedSessions[] = $childSession;
661
                        }
662
                    }
663
                }
664
665
                return $formattedSessions;
666
            }
667
668
            if ('all' === $listType) {
669
                if ($getCount) {
670
                    return $sessions[0]['total_rows'];
671
                }
672
                return $sessions;
673
            }
674
            return $sessions;
675
        }
676
677
        // For search diagnosis format (Ofaj)
678
        $categories = self::get_all_session_category();
679
        $orderedCategories = [];
680
        if (!empty($categories)) {
681
            foreach ($categories as $category) {
682
                $orderedCategories[$category['id']] = $category['title'];
683
            }
684
        }
685
        $result = Database::query($query);
686
        $formattedSessions = [];
687
        if (Database::num_rows($result)) {
688
            $sessions = Database::store_result($result, 'ASSOC');
689
            if ($getCount) {
690
                return $sessions[0]['total_rows'];
691
            }
692
693
            $activeIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
694
            $inactiveIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
695
696
            foreach ($sessions as $session) {
697
                $session_id = $session['id'];
698
                if ($showCountUsers) {
699
                    $session['users'] = self::get_users_by_session(
700
                        $session['id'],
701
                        0,
702
                        true
703
                    );
704
                    $usersLang = self::getCountUsersLangBySession($session['id'], api_get_current_access_url_id(), Session::STUDENT);
705
                    $tooltipUserLangs = '';
706
                    if (!empty($usersLang)) {
707
                        $tooltipUserLangs = implode(' | ', $usersLang);
708
                    }
709
                    $session['users'] = '<a href="#" title="'.$tooltipUserLangs.'">'.$session['users'].'</a>';
710
                    $courses = self::getCoursesInSession($session_id);
711
                    $teachers = '';
712
                    foreach ($courses as $courseId) {
713
                        $courseInfo = api_get_course_info_by_id($courseId);
714
715
                        // Ofaj
716
                        $teachers = CourseManager::get_coachs_from_course_to_string($session_id, $courseInfo['real_id']);
717
                    }
718
                    // ofaj
719
                    $session['teachers'] = '';
720
                    if (!empty($teachers)) {
721
                        $session['teachers'] = Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_SMALL, addslashes($teachers));
722
                    }
723
                }
724
                $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
725
                if (api_is_drh()) {
726
                    $url = api_get_path(WEB_CODE_PATH).'session/about.php?session_id='.$session['id'];
727
                }
728
                if (api_is_platform_admin()) {
729
                    $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
730
                }
731
732
                if ($extraFieldsToLoad) {
733
                    $url = api_get_path(WEB_CODE_PATH).'session/about.php?session_id='.$session['id'];
734
                }
735
                $session['title'] = Display::url($session['title'], $url);
736
737
                if (isset($session['session_active']) && $session['session_active'] == 1) {
738
                    $session['session_active'] = $activeIcon;
739
                } else {
740
                    $session['session_active'] = $inactiveIcon;
741
                }
742
743
                $session = self::convert_dates_to_local($session, true);
744
745
                switch ($session['visibility']) {
746
                    case SESSION_VISIBLE_READ_ONLY: //1
747
                        $session['visibility'] = get_lang('Read only');
748
                        break;
749
                    case SESSION_VISIBLE:           //2
750
                    case SESSION_AVAILABLE:         //4
751
                        $session['visibility'] = get_lang('Visible');
752
                        break;
753
                    case SESSION_INVISIBLE:         //3
754
                        $session['visibility'] = api_ucfirst(get_lang('Invisible'));
755
                        break;
756
                }
757
758
                if (!empty($extraFieldsToLoad)) {
759
                    foreach ($extraFieldsToLoad as $field) {
760
                        $extraFieldValue = new ExtraFieldValue('session');
761
                        $fieldData = $extraFieldValue->getAllValuesByItemAndField(
762
                            $session['id'],
763
                            $field['id']
764
                        );
765
                        $fieldDataArray = [];
766
                        $fieldDataToString = '';
767
                        if (!empty($fieldData)) {
768
                            foreach ($fieldData as $data) {
769
                                $fieldDataArray[] = $data['field_value'];
770
                            }
771
                            $fieldDataToString = implode(', ', $fieldDataArray);
772
                        }
773
                        $session[$field['variable']] = $fieldDataToString;
774
                    }
775
                }
776
777
                $categoryName = $orderedCategories[$session['session_category_id']] ?? '';
778
                $session['category_name'] = $categoryName;
779
                if (isset($session['status'])) {
780
                    $session['status'] = self::getStatusLabel($session['status']);
781
                }
782
783
                $formattedSessions[] = $session;
784
            }
785
        }
786
787
        return $formattedSessions;
788
    }
789
790
    /**
791
     * Get the count of users by language and session
792
     *
793
     * @param $sid
794
     * @param int $urlId
795
     * @param null $status
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $status is correct as it would always require null to be passed?
Loading history...
796
     *
797
     * @return array A list of ISO lang of users registered in the session , ex: FR 6
798
     */
799
    public static function getCountUsersLangBySession(
800
        $sid,
801
        $urlId = 0,
802
        $status = null
803
    ): array
804
    {
805
        $sid = (int) $sid;
806
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
807
808
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
809
        $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
810
        $tableAccessUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
811
        $tableLanguage = Database::get_main_table(TABLE_MAIN_LANGUAGE);
812
813
        $sql = "SELECT l.isocode, count(u.id) as cLang
814
                FROM $tblSessionUser su
815
                INNER JOIN $tblUser u ON (u.id = su.user_id)
816
                INNER JOIN $tableLanguage l ON (l.isocode = u.locale)
817
                LEFT OUTER JOIN $tableAccessUrlUser au ON (au.user_id = u.id)
818
                ";
819
820
        if (is_numeric($status)) {
821
            $status = (int) $status;
822
            $sql .= " WHERE su.relation_type = $status AND (au.access_url_id = $urlId OR au.access_url_id is null)";
823
        } else {
824
            $sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
825
        }
826
        $sql .= " AND su.session_id = $sid GROUP BY l.isocode";
827
828
        $rs = Database::query($sql);
829
        $usersLang = [];
830
        if (Database::num_rows($rs) > 0) {
831
            while ($row = Database::fetch_assoc($rs)) {
832
                $usersLang[] = strtoupper($row['isocode'])." ".$row['cLang'];
833
            }
834
        }
835
836
        return $usersLang;
837
    }
838
839
    /**
840
     * Gets the admin session list callback of the session/session_list.php page.
841
     *
842
     * @param array  $options           order and limit keys
843
     * @param bool   $getCount          Whether to get all the results or only the count
844
     * @param array  $columns
845
     * @param array  $extraFieldsToLoad
846
     * @param string $listType
847
     *
848
     * @return mixed Integer for number of rows, or array of results
849
     * @assert ([],true) !== false
850
     */
851
    public static function formatSessionsAdminForGrid(
852
        $options = [],
853
        $getCount = false,
854
        $columns = [],
855
        $extraFieldsToLoad = [],
856
        $listType = 'all'
857
    ) {
858
        $showCountUsers = false;
859
        if (!$getCount && !empty($columns['column_model'])) {
860
            foreach ($columns['column_model'] as $column) {
861
                if ('users' === $column['name']) {
862
                    $showCountUsers = true;
863
                }
864
            }
865
        }
866
867
        $userId = api_get_user_id();
868
        $sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns, $listType, $extraFieldsToLoad);
869
        if ($getCount) {
870
            return (int) $sessions;
871
        }
872
873
        $formattedSessions = [];
874
        $categories = self::get_all_session_category();
875
        $orderedCategories = [];
876
        if (!empty($categories)) {
877
            foreach ($categories as $category) {
878
                $orderedCategories[$category['id']] = $category['title'];
879
            }
880
        }
881
882
        $activeIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
883
        $inactiveIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
884
885
        foreach ($sessions as $session) {
886
            if ($showCountUsers) {
887
                $session['users'] = self::get_users_by_session($session['id'], 0, true);
888
                $usersLang = self::getCountUsersLangBySession($session['id'], api_get_current_access_url_id(), Session::STUDENT);
889
                $tooltipUserLangs = '';
890
                if (!empty($usersLang)) {
891
                    $tooltipUserLangs = implode(' | ', $usersLang);
892
                }
893
                $session['users'] = '<a href="#" title="'.$tooltipUserLangs.'">'.$session['users'].'</a>';
894
                $courses = self::getCoursesInSession($session['id']);
895
                $teachers = '';
896
                foreach ($courses as $courseId) {
897
                    $courseInfo = api_get_course_info_by_id($courseId);
898
899
                    // Ofaj
900
                    $teachers = CourseManager::get_coachs_from_course_to_string($session['id'], $courseInfo['real_id']);
901
                }
902
                // ofaj
903
                $session['teachers'] = '';
904
                if (!empty($teachers)) {
905
                    $session['teachers'] = Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_SMALL, addslashes($teachers));
906
                }
907
            }
908
            $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
909
            if ($extraFieldsToLoad || api_is_drh()) {
910
                $url = api_get_path(WEB_PATH).'sessions/'.$session['id'].'/about/';
911
            }
912
913
            $session['title'] = Display::url($session['title'], $url);
914
915
            if (!empty($extraFieldsToLoad)) {
916
                foreach ($extraFieldsToLoad as $field) {
917
                    $extraFieldValue = new ExtraFieldValue('session');
918
                    $fieldData = $extraFieldValue->getAllValuesByItemAndField(
919
                        $session['id'],
920
                        $field['id']
921
                    );
922
                    $fieldDataArray = [];
923
                    $fieldDataToString = '';
924
                    if (!empty($fieldData)) {
925
                        foreach ($fieldData as $data) {
926
                            $fieldDataArray[] = $data['field_value'];
927
                        }
928
                        $fieldDataToString = implode(', ', $fieldDataArray);
929
                    }
930
                    $session[$field['variable']] = $fieldDataToString;
931
                }
932
            }
933
934
            if (isset($session['session_active']) && 1 == $session['session_active']) {
935
                $session['session_active'] = $activeIcon;
936
            } else {
937
                $session['session_active'] = $inactiveIcon;
938
            }
939
940
            $session = self::convert_dates_to_local($session, true);
941
942
            switch ($session['visibility']) {
943
                case SESSION_VISIBLE_READ_ONLY: //1
944
                    $session['visibility'] = get_lang('Read only');
945
                    break;
946
                case SESSION_VISIBLE:           //2
947
                case SESSION_AVAILABLE:         //4
948
                    $session['visibility'] = get_lang('Visible');
949
                    break;
950
                case SESSION_INVISIBLE:         //3
951
                    $session['visibility'] = api_ucfirst(get_lang('Invisible'));
952
                    break;
953
            }
954
955
            // Cleaning double selects.
956
            foreach ($session as $key => &$value) {
957
                /*if (isset($optionsByDouble[$key]) || isset($optionsByDouble[$key.'_second'])) {
958
                    $options = explode('::', $value);
959
                }*/
960
                $original_key = $key;
961
                if (false !== strpos($key, '_second')) {
962
                    $key = str_replace('_second', '', $key);
963
                }
964
965
                /*if (isset($optionsByDouble[$key]) &&
966
                    isset($options[0]) &&
967
                    isset($optionsByDouble[$key][$options[0]])
968
                ) {
969
                    if (false === strpos($original_key, '_second')) {
970
                        $value = $optionsByDouble[$key][$options[0]]['option_display_text'];
971
                    } else {
972
                        $value = $optionsByDouble[$key][$options[1]]['option_display_text'];
973
                    }
974
                }*/
975
            }
976
977
            $categoryName = isset($orderedCategories[$session['session_category_id']]) ? $orderedCategories[$session['session_category_id']] : '';
978
            $session['category_name'] = $categoryName;
979
            if (isset($session['status'])) {
980
                $session['status'] = self::getStatusLabel($session['status']);
981
            }
982
983
            $formattedSessions[] = $session;
984
        }
985
986
        return $formattedSessions;
987
    }
988
989
    /**
990
     * Gets the progress of learning paths in the given session.
991
     *
992
     * @param int    $sessionId
993
     * @param int    $courseId
994
     * @param string $date_from
995
     * @param string $date_to
996
     * @param array options order and limit keys
997
     *
998
     * @return array table with user name, lp name, progress
999
     */
1000
    public static function get_session_lp_progress(
1001
        $sessionId,
1002
        $courseId,
1003
        $date_from,
1004
        $date_to,
1005
        $options
1006
    ) {
1007
        //escaping vars
1008
        $sessionId = $sessionId === 'T' ? 'T' : intval($sessionId);
1009
        $courseId = intval($courseId);
1010
1011
        //tables
1012
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1013
        $user = Database::get_main_table(TABLE_MAIN_USER);
1014
        $tbl_course_lp_view = Database::get_course_table(TABLE_LP_VIEW);
1015
1016
        $course = api_get_course_info_by_id($courseId);
1017
        $sessionCond = 'and session_id = %s';
1018
        if ($sessionId === 'T') {
1019
            $sessionCond = '';
1020
        }
1021
1022
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT." $sessionCond";
1023
1024
        $limit = null;
1025
        if (!empty($options['limit'])) {
1026
            $limit = " LIMIT ".$options['limit'];
1027
        }
1028
1029
        if (!empty($options['where'])) {
1030
            $where .= ' '.$options['where'];
1031
        }
1032
1033
        $order = null;
1034
        if (!empty($options['order'])) {
1035
            $order = " ORDER BY ".$options['order']." ";
1036
        }
1037
1038
        $sql = "SELECT u.id as user_id, u.lastname, u.firstname, u.username, u.email, s.c_id
1039
                FROM $session_course_user s
1040
                INNER JOIN $user u ON u.id = s.user_id
1041
                $where
1042
                $order
1043
                $limit";
1044
1045
        $sql_query = sprintf($sql, Database::escape_string($course['real_id']), $sessionId);
1046
1047
        $rs = Database::query($sql_query);
1048
        while ($user = Database::fetch_array($rs)) {
1049
            $users[$user['user_id']] = $user;
1050
        }
1051
1052
        // Get lessons
1053
        $lessons = LearnpathList::get_course_lessons($course['code'], $sessionId);
1054
1055
        $table = [];
1056
        foreach ($users as $user) {
1057
            $data = [
1058
                'lastname' => $user[1],
1059
                'firstname' => $user[2],
1060
                'username' => $user[3],
1061
            ];
1062
1063
            $sessionCond = 'AND v.session_id = %d';
1064
            if ($sessionId == 'T') {
1065
                $sessionCond = "";
1066
            }
1067
1068
            //Get lessons progress by user
1069
            $sql = "SELECT v.lp_id as id, v.progress
1070
                    FROM  $tbl_course_lp_view v
1071
                    WHERE v.c_id = %d
1072
                    AND v.user_id = %d
1073
            $sessionCond";
1074
1075
            $sql_query = sprintf(
1076
                $sql,
1077
                intval($courseId),
1078
                intval($user['user_id']),
1079
                $sessionId
1080
            );
1081
1082
            $result = Database::query($sql_query);
1083
1084
            $user_lessons = [];
1085
            while ($row = Database::fetch_array($result)) {
1086
                $user_lessons[$row['id']] = $row;
1087
            }
1088
1089
            //Match course lessons with user progress
1090
            $progress = 0;
1091
            $count = 0;
1092
            foreach ($lessons as $lesson) {
1093
                $data[$lesson['id']] = (!empty($user_lessons[$lesson['id']]['progress'])) ? $user_lessons[$lesson['id']]['progress'] : 0;
1094
                $progress += $data[$lesson['id']];
1095
                $data[$lesson['id']] = $data[$lesson['id']].'%';
1096
                $count++;
1097
            }
1098
            if (0 == $count) {
1099
                $data['total'] = 0;
1100
            } else {
1101
                $data['total'] = round($progress / $count, 2).'%';
1102
            }
1103
            $table[] = $data;
1104
        }
1105
1106
        return $table;
1107
    }
1108
1109
    /**
1110
     * Gets the survey answers.
1111
     *
1112
     * @param int $sessionId
1113
     * @param int $courseId
1114
     * @param int $surveyId
1115
     * @param array options order and limit keys
1116
     *
1117
     * @todo fix the query
1118
     *
1119
     * @return array table with username, lp name, progress
1120
     */
1121
    public static function get_survey_overview(
1122
        $sessionId,
1123
        $courseId,
1124
        $surveyId,
1125
        $date_from,
1126
        $date_to,
1127
        $options
1128
    ) {
1129
        $sessionId = (int) $sessionId;
1130
        $courseId = (int) $courseId;
1131
        $surveyId = (int) $surveyId;
1132
1133
        //tables
1134
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1135
        $user = Database::get_main_table(TABLE_MAIN_USER);
1136
        $c_survey = Database::get_course_table(TABLE_SURVEY);
1137
        $c_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1138
        $c_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1139
        $c_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1140
1141
        $course = api_get_course_info_by_id($courseId);
1142
1143
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT." AND session_id = %s";
1144
1145
        $limit = null;
1146
        if (!empty($options['limit'])) {
1147
            $limit = " LIMIT ".$options['limit'];
1148
        }
1149
1150
        if (!empty($options['where'])) {
1151
            $where .= ' '.$options['where'];
1152
        }
1153
1154
        $order = null;
1155
        if (!empty($options['order'])) {
1156
            $order = " ORDER BY ".$options['order'];
1157
        }
1158
1159
        $sql = "SELECT u.id as user_id, u.lastname, u.firstname, u.username, u.email, s.c_id
1160
                FROM $session_course_user s
1161
                INNER JOIN $user u ON u.id = s.user_id
1162
                $where $order $limit";
1163
1164
        $sql_query = sprintf($sql, intval($course['real_id']), $sessionId);
1165
        $rs = Database::query($sql_query);
1166
        while ($user = Database::fetch_array($rs)) {
1167
            $users[$user['user_id']] = $user;
1168
        }
1169
        $repo = Container::getSurveyRepository();
1170
        /** @var CSurvey $survey */
1171
        $survey = $repo->find($surveyId);
1172
        $questions = $survey->getQuestions();
1173
        $anonymous = (1 == $survey->getAnonymous()) ? true : false;
1174
1175
        $table = [];
1176
        foreach ($users as $user) {
1177
            $data = [
1178
                'lastname' => ($anonymous ? '***' : $user[1]),
1179
                'firstname' => ($anonymous ? '***' : $user[2]),
1180
                'username' => ($anonymous ? '***' : $user[3]),
1181
            ];
1182
1183
            //Get questions by user
1184
            $sql = "SELECT sa.question_id, sa.option_id, sqo.option_text, sq.type
1185
                    FROM $c_survey_answer sa
1186
                    INNER JOIN $c_survey_question sq
1187
                    ON sq.question_id = sa.question_id
1188
                    LEFT JOIN $c_survey_question_option sqo
1189
                    ON
1190
                      sqo.c_id = sa.c_id AND
1191
                      sqo.question_id = sq.question_id AND
1192
                      sqo.iid = sa.option_id AND
1193
                      sqo.survey_id = sq.survey_id
1194
                    WHERE
1195
                      sa.survey_id = %d AND
1196
                      sa.c_id = %d AND
1197
                      sa.user = %d
1198
            "; //. $where_survey;
1199
            $sql_query = sprintf($sql, $surveyId, $courseId, $user['user_id']);
1200
            $result = Database::query($sql_query);
1201
            $user_questions = [];
1202
            while ($row = Database::fetch_array($result)) {
1203
                $user_questions[$row['question_id']] = $row;
1204
            }
1205
1206
            //Match course lessons with user progress
1207
            foreach ($questions as $question) {
1208
                $questionId = $question->getIid();
1209
                $option_text = 'option_text';
1210
                if ('open' === $user_questions[$questionId]['type']) {
1211
                    $option_text = 'option_id';
1212
                }
1213
                $data[$questionId] = $user_questions[$questionId][$option_text];
1214
            }
1215
            $table[] = $data;
1216
        }
1217
1218
        return $table;
1219
    }
1220
1221
    /**
1222
     * Gets the progress of the given session.
1223
     *
1224
     * @param int $sessionId
1225
     * @param int $courseId
1226
     * @param array options order and limit keys
1227
     *
1228
     * @return array table with username, lp name, progress
1229
     */
1230
    public static function get_session_progress(
1231
        $sessionId,
1232
        $courseId,
1233
        $date_from,
1234
        $date_to,
1235
        $options
1236
    ) {
1237
        $sessionId = (int) $sessionId;
1238
1239
        $getAllSessions = false;
1240
        if (empty($sessionId)) {
1241
            $sessionId = 0;
1242
            $getAllSessions = true;
1243
        }
1244
1245
        //tables
1246
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1247
        $user = Database::get_main_table(TABLE_MAIN_USER);
1248
        $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1249
        $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1250
        $tbl_course_lp = Database::get_course_table(TABLE_LP_MAIN);
1251
        $wiki = Database::get_course_table(TABLE_WIKI);
1252
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
1253
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
1254
1255
        $course = api_get_course_info_by_id($courseId);
1256
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT;
1257
1258
        $limit = null;
1259
        if (!empty($options['limit'])) {
1260
            $limit = " LIMIT ".$options['limit'];
1261
        }
1262
1263
        if (!empty($options['where'])) {
1264
            $where .= ' '.$options['where'];
1265
        }
1266
1267
        $order = null;
1268
        if (!empty($options['order'])) {
1269
            $order = " ORDER BY ".$options['order'];
1270
        }
1271
1272
        //TODO, fix create report without session
1273
        $queryVariables = [$course['real_id']];
1274
        if (!empty($sessionId)) {
1275
            $where .= ' AND session_id = %s';
1276
            $queryVariables[] = $sessionId;
1277
            $sql = "SELECT
1278
                        u.id as user_id, u.lastname, u.firstname, u.username,
1279
                        u.email, s.c_id, s.session_id
1280
                    FROM $session_course_user s
1281
                    INNER JOIN $user u
1282
                    ON u.id = s.user_id
1283
                    $where $order $limit";
1284
        } else {
1285
            $sql = "SELECT
1286
                        u.id as user_id, u.lastname, u.firstname, u.username,
1287
                        u.email, s.c_id, s.session_id
1288
                    FROM $session_course_user s
1289
                    INNER JOIN $user u ON u.id = s.user_id
1290
                    $where $order $limit";
1291
        }
1292
1293
        $sql_query = vsprintf($sql, $queryVariables);
1294
        $rs = Database::query($sql_query);
1295
        while ($user = Database::fetch_array($rs)) {
1296
            $users[$user['user_id']] = $user;
1297
        }
1298
1299
        /**
1300
         *  Lessons.
1301
         */
1302
        $sql = "SELECT * FROM $tbl_course_lp WHERE c_id = %s "; //AND session_id = %s
1303
        $sql_query = sprintf($sql, $course['real_id']);
1304
        $result = Database::query($sql_query);
1305
        $arrLesson = [[]];
1306
        while ($row = Database::fetch_array($result)) {
1307
            if (empty($arrLesson[$row['session_id']]['lessons_total'])) {
1308
                $arrLesson[$row['session_id']]['lessons_total'] = 1;
1309
            } else {
1310
                $arrLesson[$row['session_id']]['lessons_total']++;
1311
            }
1312
        }
1313
        $session = api_get_session_entity($sessionId);
1314
        $qb = Container::getQuizRepository()->findAllByCourse($course, $session, null, 2);
1315
        $exercises = $qb->getQuery()->getResult();
1316
        $exercises_total = count($exercises);
1317
1318
        /*$exercises = ExerciseLib::get_all_exercises(
1319
            $course,
1320
            $sessionId,
1321
            false,
1322
            '',
1323
            $getAllSessions
1324
        );
1325
        $exercises_total = count($exercises);*/
1326
1327
        /**
1328
         *  Assignments.
1329
         */
1330
        //total
1331
        $params = [$course['real_id']];
1332
        if ($getAllSessions) {
1333
            $sql = "SELECT count(w.id) as count
1334
                    FROM $workTable w
1335
                    LEFT JOIN $workTableAssignment a
1336
                    ON (a.publication_id = w.id AND a.c_id = w.c_id)
1337
                    WHERE
1338
                        w.c_id = %s AND
1339
                        parent_id = 0 AND
1340
                        active IN (1, 0)";
1341
        } else {
1342
            $sql = "SELECT count(w.id) as count
1343
                    FROM $workTable w
1344
                    LEFT JOIN $workTableAssignment a
1345
                    ON (a.publication_id = w.id AND a.c_id = w.c_id)
1346
                    WHERE
1347
                        w.c_id = %s AND
1348
                        parent_id = 0 AND
1349
                        active IN (1, 0)";
1350
1351
            if (empty($sessionId)) {
1352
                $sql .= ' AND w.session_id = NULL ';
1353
            } else {
1354
                $sql .= ' AND w.session_id = %s ';
1355
                $params[] = $sessionId;
1356
            }
1357
        }
1358
1359
        $sql_query = vsprintf($sql, $params);
1360
        $result = Database::query($sql_query);
1361
        $row = Database::fetch_array($result);
1362
        $assignments_total = $row['count'];
1363
1364
        /**
1365
         * Wiki.
1366
         */
1367
        if ($getAllSessions) {
1368
            $sql = "SELECT count(distinct page_id)  as count FROM $wiki
1369
                    WHERE c_id = %s";
1370
        } else {
1371
            $sql = "SELECT count(distinct page_id)  as count FROM $wiki
1372
                    WHERE c_id = %s and session_id = %s";
1373
        }
1374
        $sql_query = sprintf($sql, $course['real_id'], $sessionId);
1375
        $result = Database::query($sql_query);
1376
        $row = Database::fetch_array($result);
1377
        $wiki_total = $row['count'];
1378
1379
        /**
1380
         * Surveys.
1381
         */
1382
        $survey_user_list = [];
1383
        $survey_list = SurveyManager::get_surveys($course['code'], $sessionId);
1384
1385
        $surveys_total = count($survey_list);
1386
        foreach ($survey_list as $survey) {
1387
            $user_list = SurveyManager::get_people_who_filled_survey(
1388
                $survey['survey_id'],
1389
                false,
1390
                $course['real_id']
1391
            );
1392
            foreach ($user_list as $user_id) {
1393
                isset($survey_user_list[$user_id]) ? $survey_user_list[$user_id]++ : $survey_user_list[$user_id] = 1;
1394
            }
1395
        }
1396
1397
        /**
1398
         * Forums.
1399
         */
1400
        $forums_total = CourseManager::getCountForum(
1401
            $course['real_id'],
1402
            $sessionId,
1403
            $getAllSessions
1404
        );
1405
1406
        //process table info
1407
        foreach ($users as $user) {
1408
            //Course description
1409
            $sql = "SELECT count(*) as count
1410
                    FROM $table_stats_access
1411
                    WHERE access_tool = 'course_description'
1412
                    AND c_id = '%s'
1413
                    AND session_id = %s
1414
                    AND access_user_id = %s ";
1415
            $sql_query = sprintf($sql, $course['real_id'], $user['id_session'], $user['user_id']);
1416
1417
            $result = Database::query($sql_query);
1418
            $row = Database::fetch_array($result);
1419
            $course_description_progress = ($row['count'] > 0) ? 100 : 0;
1420
1421
            if (!empty($arrLesson[$user['id_session']]['lessons_total'])) {
1422
                $lessons_total = $arrLesson[$user['id_session']]['lessons_total'];
1423
            } else {
1424
                $lessons_total = !empty($arrLesson[0]['lessons_total']) ? $arrLesson[0]['lessons_total'] : 0;
1425
            }
1426
1427
            //Lessons
1428
            //TODO: Lessons done and left is calculated by progress per item in lesson,
1429
            // maybe we should calculate it only per completed lesson?
1430
            $lessons_progress = Tracking::get_avg_student_progress(
1431
                $user['user_id'],
1432
                $course['code'],
1433
                [],
1434
                $user['id_session']
1435
            );
1436
            $lessons_done = ($lessons_progress * $lessons_total) / 100;
1437
            $lessons_left = $lessons_total - $lessons_done;
1438
1439
            // Exercises
1440
            $exercises_progress = str_replace(
1441
                '%',
1442
                '',
1443
                Tracking::get_exercise_student_progress(
1444
                    $exercises,
1445
                    $user['user_id'],
1446
                    $course['real_id'],
1447
                    $user['id_session']
1448
                )
1449
            );
1450
            $exercises_done = round(($exercises_progress * $exercises_total) / 100);
1451
            $exercises_left = $exercises_total - $exercises_done;
1452
1453
            //Assignments
1454
            $assignments_done = Container::getStudentPublicationRepository()->countUserPublications(
1455
                $user['user_id'],
1456
                $course['code'],
1457
                $user['id_session']
1458
            );
1459
            $assignments_left = $assignments_total - $assignments_done;
1460
            if (!empty($assignments_total)) {
1461
                $assignments_progress = round((($assignments_done * 100) / $assignments_total), 2);
1462
            } else {
1463
                $assignments_progress = 0;
1464
            }
1465
1466
            // Wiki
1467
            // total revisions per user
1468
            $sql = "SELECT count(*) as count
1469
                    FROM $wiki
1470
                    WHERE c_id = %s and session_id = %s and user_id = %s";
1471
            $sql_query = sprintf($sql, $course['real_id'], $user['id_session'], $user['user_id']);
1472
            $result = Database::query($sql_query);
1473
            $row = Database::fetch_array($result);
1474
            $wiki_revisions = $row['count'];
1475
            //count visited wiki pages
1476
            $sql = "SELECT count(distinct default_value) as count
1477
                    FROM $table_stats_default
1478
                    WHERE
1479
                        default_user_id = %s AND
1480
                        default_event_type = 'wiki_page_view' AND
1481
                        default_value_type = 'wiki_page_id' AND
1482
                        c_id = %s
1483
                    ";
1484
            $sql_query = sprintf($sql, $user['user_id'], $course['real_id']);
1485
            $result = Database::query($sql_query);
1486
            $row = Database::fetch_array($result);
1487
1488
            $wiki_read = $row['count'];
1489
            $wiki_unread = $wiki_total - $wiki_read;
1490
            if (!empty($wiki_total)) {
1491
                $wiki_progress = round((($wiki_read * 100) / $wiki_total), 2);
1492
            } else {
1493
                $wiki_progress = 0;
1494
            }
1495
1496
            // Surveys
1497
            $surveys_done = isset($survey_user_list[$user['user_id']]) ? $survey_user_list[$user['user_id']] : 0;
1498
            $surveys_left = $surveys_total - $surveys_done;
1499
            if (!empty($surveys_total)) {
1500
                $surveys_progress = round((($surveys_done * 100) / $surveys_total), 2);
1501
            } else {
1502
                $surveys_progress = 0;
1503
            }
1504
1505
            //Forums
1506
            $forums_done = CourseManager::getCountForumPerUser(
1507
                $user['user_id'],
1508
                $course['real_id'],
1509
                $user['id_session']
1510
            );
1511
            $forums_left = $forums_total - $forums_done;
1512
            if (!empty($forums_total)) {
1513
                $forums_progress = round((($forums_done * 100) / $forums_total), 2);
1514
            } else {
1515
                $forums_progress = 0;
1516
            }
1517
1518
            // Overall Total
1519
            $overall_total = ($course_description_progress + $exercises_progress + $forums_progress + $assignments_progress + $wiki_progress + $surveys_progress) / 6;
1520
1521
            $link = '<a href="'.api_get_path(WEB_CODE_PATH).'my_space/myStudents.php?student='.$user[0].'&details=true&course='.$course['code'].'&sid='.$sessionId.'"> %s </a>';
1522
            $linkForum = '<a href="'.api_get_path(WEB_CODE_PATH).'forum/index.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1523
            $linkWork = '<a href="'.api_get_path(WEB_CODE_PATH).'work/work.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1524
            $linkWiki = '<a href="'.api_get_path(WEB_CODE_PATH).'wiki/index.php?cid='.$course['real_id'].'&sid='.$sessionId.'&action=statistics"> %s </a>';
1525
            $linkSurvey = '<a href="'.api_get_path(WEB_CODE_PATH).'survey/survey_list.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1526
1527
            $table[] = [
1528
                'lastname' => $user[1],
1529
                'firstname' => $user[2],
1530
                'username' => $user[3],
1531
                //'profile'   => '',
1532
                'total' => round($overall_total, 2).'%',
1533
                'courses' => sprintf($link, $course_description_progress.'%'),
1534
                'lessons' => sprintf($link, $lessons_progress.'%'),
1535
                'exercises' => sprintf($link, $exercises_progress.'%'),
1536
                'forums' => sprintf($link, $forums_progress.'%'),
1537
                'homeworks' => sprintf($link, $assignments_progress.'%'),
1538
                'wikis' => sprintf($link, $wiki_progress.'%'),
1539
                'surveys' => sprintf($link, $surveys_progress.'%'),
1540
                //course description
1541
                'course_description_progress' => $course_description_progress.'%',
1542
                //lessons
1543
                'lessons_total' => sprintf($link, $lessons_total),
1544
                'lessons_done' => sprintf($link, $lessons_done),
1545
                'lessons_left' => sprintf($link, $lessons_left),
1546
                'lessons_progress' => sprintf($link, $lessons_progress.'%'),
1547
                //exercises
1548
                'exercises_total' => sprintf($link, $exercises_total),
1549
                'exercises_done' => sprintf($link, $exercises_done),
1550
                'exercises_left' => sprintf($link, $exercises_left),
1551
                'exercises_progress' => sprintf($link, $exercises_progress.'%'),
1552
                //forums
1553
                'forums_total' => sprintf($linkForum, $forums_total),
1554
                'forums_done' => sprintf($linkForum, $forums_done),
1555
                'forums_left' => sprintf($linkForum, $forums_left),
1556
                'forums_progress' => sprintf($linkForum, $forums_progress.'%'),
1557
                //assignments
1558
                'assignments_total' => sprintf($linkWork, $assignments_total),
1559
                'assignments_done' => sprintf($linkWork, $assignments_done),
1560
                'assignments_left' => sprintf($linkWork, $assignments_left),
1561
                'assignments_progress' => sprintf($linkWork, $assignments_progress.'%'),
1562
                //wiki
1563
                'wiki_total' => sprintf($linkWiki, $wiki_total),
1564
                'wiki_revisions' => sprintf($linkWiki, $wiki_revisions),
1565
                'wiki_read' => sprintf($linkWiki, $wiki_read),
1566
                'wiki_unread' => sprintf($linkWiki, $wiki_unread),
1567
                'wiki_progress' => sprintf($linkWiki, $wiki_progress.'%'),
1568
                //survey
1569
                'surveys_total' => sprintf($linkSurvey, $surveys_total),
1570
                'surveys_done' => sprintf($linkSurvey, $surveys_done),
1571
                'surveys_left' => sprintf($linkSurvey, $surveys_left),
1572
                'surveys_progress' => sprintf($linkSurvey, $surveys_progress.'%'),
1573
            ];
1574
        }
1575
1576
        return $table;
1577
    }
1578
1579
    /**
1580
     * Get the ip, total of clicks, login date and time logged in for all user, in one session.
1581
     *
1582
     * @todo track_e_course_access table should have ip so we dont have to look for it in track_e_login
1583
     *
1584
     * @author César Perales <[email protected]>, Beeznest Team
1585
     *
1586
     * @version 1.9.6
1587
     */
1588
    public static function get_user_data_access_tracking_overview(
1589
        $sessionId,
1590
        $courseId,
1591
        $studentId = 0,
1592
        $profile = '',
1593
        $date_from = '',
1594
        $date_to = '',
1595
        $options = []
1596
    ) {
1597
        $sessionId = intval($sessionId);
1598
        $courseId = intval($courseId);
1599
        $studentId = intval($studentId);
1600
        $profile = intval($profile);
1601
        $date_from = Database::escape_string($date_from);
1602
        $date_to = Database::escape_string($date_to);
1603
1604
        // database table definition
1605
        $user = Database::get_main_table(TABLE_MAIN_USER);
1606
        $course = Database::get_main_table(TABLE_MAIN_COURSE);
1607
        $track_e_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
1608
        $track_e_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
1609
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1610
1611
        global $export_csv;
1612
        if ($export_csv) {
1613
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
1614
        } else {
1615
            $is_western_name_order = api_is_western_name_order();
1616
        }
1617
1618
        $where = null;
1619
        if (isset($sessionId) && !empty($sessionId)) {
1620
            $where = sprintf(" WHERE a.session_id = %d", $sessionId);
1621
        }
1622
        if (isset($courseId) && !empty($courseId)) {
1623
            $where .= sprintf(" AND c.id = %d", $courseId);
1624
        }
1625
        if (isset($studentId) && !empty($studentId)) {
1626
            $where .= sprintf(" AND u.id = %d", $studentId);
1627
        }
1628
        if (isset($profile) && !empty($profile)) {
1629
            $where .= sprintf(" AND u.status = %d", $profile);
1630
        }
1631
        if (!empty($date_to) && !empty($date_from)) {
1632
            $where .= sprintf(
1633
                " AND a.login_course_date >= '%s 00:00:00'
1634
                 AND a.login_course_date <= '%s 23:59:59'",
1635
                $date_from,
1636
                $date_to
1637
            );
1638
        }
1639
1640
        $limit = null;
1641
        if (!empty($options['limit'])) {
1642
            $limit = " LIMIT ".$options['limit'];
1643
        }
1644
1645
        if (!empty($options['where'])) {
1646
            $where .= ' '.$options['where'];
1647
        }
1648
1649
        $order = null;
1650
        if (!empty($options['order'])) {
1651
            $order = " ORDER BY ".$options['order'];
1652
        }
1653
1654
        //TODO add course name
1655
        $sql = "SELECT
1656
                a.login_course_date ,
1657
                u.username ,
1658
                ".($is_western_name_order ? "
1659
                    u.firstname,
1660
                    u.lastname,
1661
                    " : "
1662
                    u.lastname,
1663
                    u.firstname,
1664
                ")."
1665
                a.logout_course_date,
1666
                a.counter,
1667
                c.title,
1668
                c.code,
1669
                u.id as user_id,
1670
                a.session_id
1671
            FROM $track_e_course_access a
1672
            INNER JOIN $user u ON a.user_id = u.id
1673
            INNER JOIN $course c ON a.c_id = c.id
1674
            $where $order $limit";
1675
        $result = Database::query(sprintf($sql, $sessionId, $courseId));
1676
1677
        $data = [];
1678
        while ($user = Database::fetch_assoc($result)) {
1679
            $data[] = $user;
1680
        }
1681
1682
        foreach ($data as $key => $info) {
1683
            $sql = "SELECT
1684
                    title
1685
                    FROM $sessionTable
1686
                    WHERE
1687
                    id = {$info['session_id']}";
1688
            $result = Database::query($sql);
1689
            $session = Database::fetch_assoc($result);
1690
1691
            // building array to display
1692
            $return[] = [
1693
                'user_id' => $info['user_id'],
1694
                'logindate' => $info['login_course_date'],
1695
                'username' => $info['username'],
1696
                'firstname' => $info['firstname'],
1697
                'lastname' => $info['lastname'],
1698
                'clicks' => $info['counter'], //+ $clicks[$info['user_id']],
1699
                'ip' => '',
1700
                'timeLoggedIn' => gmdate("H:i:s", strtotime($info['logout_course_date']) - strtotime($info['login_course_date'])),
1701
                'session' => $session['title'],
1702
            ];
1703
        }
1704
1705
        foreach ($return as $key => $info) {
1706
            //Search for ip, we do less querys if we iterate the final array
1707
            $sql = sprintf(
1708
                "SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date < '%s' ORDER BY login_date DESC LIMIT 1",
1709
                $info['user_id'],
1710
                $info['logindate']
1711
            ); //TODO add select by user too
1712
            $result = Database::query($sql);
1713
            $ip = Database::fetch_assoc($result);
1714
            //if no ip founded, we search the closest higher ip
1715
            if (empty($ip['user_ip'])) {
1716
                $sql = sprintf(
1717
                    "SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date > '%s'  ORDER BY login_date ASC LIMIT 1",
1718
                    $info['user_id'],
1719
                    $info['logindate']
1720
                ); //TODO add select by user too
1721
                $result = Database::query($sql);
1722
                $ip = Database::fetch_assoc($result);
1723
            }
1724
            //add ip to final array
1725
            $return[$key]['ip'] = $ip['user_ip'];
1726
        }
1727
1728
        return $return;
1729
    }
1730
1731
    /**
1732
     * Creates a new course code based in given code.
1733
     *
1734
     * @param string $session_name
1735
     *                             <code>
1736
     *                             $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3
1737
     *                             if the course code doest not exist in the DB the same course code will be returned
1738
     *                             </code>
1739
     *
1740
     * @return string wanted unused code
1741
     */
1742
    public static function generateNextSessionName($session_name)
1743
    {
1744
        $session_name_ok = !self::sessionNameExists($session_name);
1745
        if (!$session_name_ok) {
1746
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1747
            $session_name = Database::escape_string($session_name);
1748
            $sql = "SELECT count(*) as count FROM $table
1749
                    WHERE title LIKE '$session_name%'";
1750
            $result = Database::query($sql);
1751
            if (Database::num_rows($result) > 0) {
1752
                $row = Database::fetch_array($result);
1753
                $count = $row['count'] + 1;
1754
                $session_name = $session_name.'_'.$count;
1755
                $result = self::sessionNameExists($session_name);
1756
                if (!$result) {
1757
                    return $session_name;
1758
                }
1759
            }
1760
1761
            return false;
1762
        }
1763
1764
        return $session_name;
1765
    }
1766
1767
    /**
1768
     * Edit a session.
1769
     *
1770
     * @author Carlos Vargas from existing code
1771
     *
1772
     * @param int    $id                           Session primary key
1773
     * @param string $name
1774
     * @param string $startDate
1775
     * @param string $endDate
1776
     * @param string $displayStartDate
1777
     * @param string $displayEndDate
1778
     * @param string $coachStartDate
1779
     * @param string $coachEndDate
1780
     * @param array  $coachesId
1781
     * @param int    $sessionCategoryId
1782
     * @param int    $visibility
1783
     * @param string $description
1784
     * @param int    $showDescription
1785
     * @param int    $duration
1786
     * @param array  $extraFields
1787
     * @param int    $sessionAdminId
1788
     * @param bool   $sendSubscriptionNotification Optional. Whether send a mail notification to users being subscribed
1789
     * @param int    $status
1790
     *
1791
     * @return mixed
1792
     */
1793
    public static function edit_session(
1794
        $id,
1795
        $name,
1796
        $startDate,
1797
        $endDate,
1798
        $displayStartDate,
1799
        $displayEndDate,
1800
        $coachStartDate,
1801
        $coachEndDate,
1802
        $coachesId,
1803
        $sessionCategoryId,
1804
        $visibility,
1805
        $description = null,
1806
        $showDescription = 0,
1807
        $duration = 0,
1808
        $extraFields = [],
1809
        $sessionAdminId = 0,
1810
        $sendSubscriptionNotification = false,
1811
        $status = 0,
1812
        $notifyBoss = 0,
1813
        $parentId = 0,
1814
        $daysBeforeFinishingForReinscription = null,
1815
        $daysBeforeFinishingToCreateNewRepetition = null,
1816
        $lastRepetition = false,
1817
        $validityInDays = null
1818
    ) {
1819
        $id = (int) $id;
1820
        $status = (int) $status;
1821
        $coachesId = array_map(fn($id) => (int) $id, $coachesId);
1822
        $sessionCategoryId = (int) $sessionCategoryId;
1823
        $visibility = (int) $visibility;
1824
        $duration = (int) $duration;
1825
1826
        $em = Database::getManager();
1827
1828
        if (empty($name)) {
1829
            Display::addFlash(
1830
                Display::return_message(get_lang('A name is required for the session'), 'warning')
1831
            );
1832
1833
            return false;
1834
        } elseif (!empty($startDate) &&
1835
            !api_is_valid_date($startDate, 'Y-m-d H:i') &&
1836
            !api_is_valid_date($startDate, 'Y-m-d H:i:s')
1837
        ) {
1838
            Display::addFlash(
1839
                Display::return_message(get_lang('Invalid start date was given.'), 'warning')
1840
            );
1841
1842
            return false;
1843
        } elseif (!empty($endDate) &&
1844
            !api_is_valid_date($endDate, 'Y-m-d H:i') &&
1845
            !api_is_valid_date($endDate, 'Y-m-d H:i:s')
1846
        ) {
1847
            Display::addFlash(
1848
                Display::return_message(get_lang('Invalid end date was given.'), 'warning')
1849
            );
1850
1851
            return false;
1852
        } elseif (!empty($startDate) && !empty($endDate) && $startDate >= $endDate) {
1853
            Display::addFlash(
1854
                Display::return_message(get_lang('The first date should be before the end date'), 'warning')
1855
            );
1856
1857
            return false;
1858
        } else {
1859
            $sessionInfo = self::get_session_by_name($name);
1860
            $exists = false;
1861
            if (!empty($sessionInfo) && (int) $sessionInfo['id'] !== $id) {
1862
                $exists = true;
1863
            }
1864
1865
            if ($exists) {
1866
                Display::addFlash(
1867
                    Display::return_message(get_lang('Session title already exists'), 'warning')
1868
                );
1869
1870
                return false;
1871
            } else {
1872
                $sessionEntity = api_get_session_entity($id);
1873
                $sessionEntity
1874
                    ->setTitle($name)
1875
                    ->setDuration($duration)
1876
                    ->setDescription($description)
1877
                    ->setShowDescription(1 === $showDescription)
1878
                    ->setVisibility($visibility)
1879
                    ->setSendSubscriptionNotification((bool) $sendSubscriptionNotification)
1880
                    ->setNotifyBoss((bool) $notifyBoss)
1881
                    ->setParentId($parentId)
1882
                    ->setDaysToReinscription((int) $daysBeforeFinishingForReinscription)
1883
                    ->setLastRepetition($lastRepetition)
1884
                    ->setDaysToNewRepetition((int) $daysBeforeFinishingToCreateNewRepetition)
1885
                    ->setValidityInDays((int) $validityInDays)
1886
                    ->setAccessStartDate(null)
1887
                    ->setAccessStartDate(null)
1888
                    ->setDisplayStartDate(null)
1889
                    ->setDisplayEndDate(null)
1890
                    ->setCoachAccessStartDate(null)
1891
                    ->setCoachAccessEndDate(null)
1892
                ;
1893
1894
                if ($parentId) {
1895
                    $sessionEntity->setParentId($parentId);
1896
                } else {
1897
                    $sessionEntity->setParentId(null);
1898
                }
1899
1900
                $sessionEntity->setDaysToReinscription($daysBeforeFinishingForReinscription);
1901
                $sessionEntity->setLastRepetition($lastRepetition);
1902
                $sessionEntity->setDaysToNewRepetition($daysBeforeFinishingToCreateNewRepetition);
1903
1904
                $newGeneralCoaches = array_map(
1905
                    fn($coachId) => api_get_user_entity($coachId),
1906
                    $coachesId
1907
                );
1908
                $currentGeneralCoaches = $sessionEntity->getGeneralCoaches();
1909
1910
                foreach ($newGeneralCoaches as $generalCoach) {
1911
                    if (!$sessionEntity->hasUserAsGeneralCoach($generalCoach)) {
1912
                        $sessionEntity->addGeneralCoach($generalCoach);
1913
                    }
1914
                }
1915
1916
                foreach ($currentGeneralCoaches as $generalCoach) {
1917
                    if (!in_array($generalCoach, $newGeneralCoaches, true)) {
1918
                        $sessionEntity->removeGeneralCoach($generalCoach);
1919
                    }
1920
                }
1921
1922
                if (!empty($sessionAdminId)) {
1923
                    $sessionEntity->addSessionAdmin(api_get_user_entity($sessionAdminId));
1924
                }
1925
1926
                if (!empty($startDate)) {
1927
                    $sessionEntity->setAccessStartDate(
1928
                        api_get_utc_datetime($startDate, true, true),
1929
                        true
1930
                    );
1931
                }
1932
1933
                if (!empty($endDate)) {
1934
                    $sessionEntity->setAccessEndDate(
1935
                        api_get_utc_datetime($endDate, true, true),
1936
                        true
1937
                    );
1938
                }
1939
1940
                if (!empty($displayStartDate)) {
1941
                    $sessionEntity->setDisplayStartDate(api_get_utc_datetime($displayStartDate, true, true));
1942
                }
1943
1944
                if (!empty($displayEndDate)) {
1945
                    $sessionEntity->setDisplayEndDate(api_get_utc_datetime($displayEndDate, true, true));
1946
                }
1947
1948
                if (!empty($coachStartDate)) {
1949
                    $sessionEntity->setCoachAccessStartDate(
1950
                        api_get_utc_datetime($coachStartDate, true, true),
1951
                        true,
1952
                        true
1953
                    );
1954
                }
1955
1956
                if (!empty($coachEndDate)) {
1957
                    $sessionEntity->setCoachAccessEndDate(
1958
                        api_get_utc_datetime($coachEndDate, true, true),
1959
                        true,
1960
                        true
1961
                    );
1962
                }
1963
1964
                if (!empty($sessionCategoryId)) {
1965
                    $category = $em->getRepository(SessionCategory::class)->find($sessionCategoryId);
1966
                    $sessionEntity->setCategory($category);
1967
                } else {
1968
                    $sessionEntity->setCategory(null);
1969
                }
1970
                $sessionEntity->setStatus($status);
1971
1972
                $em->flush();
1973
1974
                if (!empty($extraFields)) {
1975
                    $extraFields['item_id'] = $id;
1976
                    $sessionFieldValue = new ExtraFieldValue('session');
1977
                    $sessionFieldValue->saveFieldValues($extraFields);
1978
                }
1979
1980
                return $id;
1981
            }
1982
        }
1983
    }
1984
1985
    /**
1986
     * Delete session.
1987
     *
1988
     * @author Carlos Vargas  from existing code
1989
     *
1990
     * @param array $idChecked an array to delete sessions
1991
     * @param bool  $fromWs    optional, true if the function is called
1992
     *                          by a webservice, false otherwise
1993
     *
1994
     * @return bool
1995
     * */
1996
    public static function delete($idChecked, $fromWs = false)
1997
    {
1998
        $sessionId = null;
1999
        if (is_array($idChecked)) {
2000
            foreach ($idChecked as $sessionId) {
2001
                self::delete($sessionId);
2002
            }
2003
        } else {
2004
            $sessionId = (int) $idChecked;
2005
        }
2006
2007
        if (empty($sessionId)) {
2008
            return false;
2009
        }
2010
2011
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2012
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2013
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2014
        $tblUrlSession = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2015
        $userGroupSessionTable = Database::get_main_table(TABLE_USERGROUP_REL_SESSION);
2016
        $trackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2017
        $trackAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2018
2019
        $ticket = Database::get_main_table(TABLE_TICKET_TICKET);
2020
        $em = Database::getManager();
2021
        $userId = api_get_user_id();
2022
        $user = api_get_user_entity();
2023
2024
        $repo = Container::getSequenceResourceRepository();
2025
        $sequenceResource = $repo->findRequirementForResource(
2026
            $sessionId,
2027
            SequenceResource::SESSION_TYPE
2028
        );
2029
2030
        $sessionEntity = api_get_session_entity($sessionId);
2031
        if (null === $sessionEntity) {
2032
            return false;
2033
        }
2034
2035
        if ($sequenceResource) {
2036
            Display::addFlash(
2037
                Display::return_message(
2038
                    get_lang('There is a sequence resource linked to this session. You must delete this link first.'),
2039
                    'error'
2040
                )
2041
            );
2042
2043
            return false;
2044
        }
2045
2046
        if (self::allowed($sessionEntity) && !$fromWs) {
2047
            if (!$sessionEntity->hasUserAsSessionAdmin($user) && !api_is_platform_admin()) {
2048
                api_not_allowed(true);
2049
            }
2050
        }
2051
2052
        // Delete Picture Session
2053
        SessionManager::deleteAsset($sessionId);
2054
2055
        $sessionName = $sessionEntity->getTitle();
2056
        $em->remove($sessionEntity);
2057
        $em->flush();
2058
2059
        // Delete explicitly from tables not directly related to 'session'
2060
        $tables = [
2061
            'track_e_lastaccess',
2062
            'track_e_default',
2063
            'track_e_exercise_confirmation',
2064
            'track_e_links',
2065
            'track_e_online',
2066
            'track_e_attempt_qualify',
2067
            'track_e_access_complete',
2068
            'track_e_uploads',
2069
            'c_dropbox_file',
2070
            'c_forum_thread_qualify_log',
2071
            'c_dropbox_post',
2072
            'c_survey_answer',
2073
            'c_wiki_mailcue',
2074
            'c_dropbox_category',
2075
            'skill_rel_item',
2076
            'scheduled_announcements',
2077
            'sequence_row_entity',
2078
        ];
2079
2080
        foreach ($tables as $table) {
2081
            Database::delete($table, ['session_id = ?' => $sessionId]);
2082
        }
2083
2084
        // Delete other related tables
2085
        Database::delete($userGroupSessionTable, ['session_id = ?' => $sessionId]);
2086
        Database::delete($tblSessionRelCourse, ['session_id = ?' => $sessionId]);
2087
        Database::delete($tblSessionRelCourseRelUser, ['session_id = ?' => $sessionId]);
2088
        Database::delete($tblSessionRelUser, ['session_id = ?' => $sessionId]);
2089
        Database::delete($tblUrlSession, ['session_id = ?' => $sessionId]);
2090
        Database::delete($trackCourseAccess, ['session_id = ?' => $sessionId]);
2091
        Database::delete($trackAccess, ['session_id = ?' => $sessionId]);
2092
        Database::update($ticket, ['session_id' => null], ['session_id = ?' => $sessionId]);
2093
2094
        $extraFieldValue = new ExtraFieldValue('session');
2095
        $extraFieldValue->deleteValuesByItem($sessionId);
2096
2097
        $repo->deleteSequenceResource($sessionId, SequenceResource::SESSION_TYPE);
2098
2099
        // Add event to system log
2100
        Event::addEvent(
2101
            LOG_SESSION_DELETE,
2102
            LOG_SESSION_ID,
2103
            $sessionName.' - id:'.$sessionId,
2104
            api_get_utc_datetime(),
2105
            $userId
2106
        );
2107
2108
        return true;
2109
    }
2110
2111
    /**
2112
     * @param int $id promotion id
2113
     *
2114
     * @return bool
2115
     */
2116
    public static function clear_session_ref_promotion($id)
2117
    {
2118
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2119
        $id = intval($id);
2120
        $sql = "UPDATE $tbl_session
2121
                SET promotion_id = 0
2122
                WHERE promotion_id = $id";
2123
        if (Database::query($sql)) {
2124
            return true;
2125
        } else {
2126
            return false;
2127
        }
2128
    }
2129
2130
    /**
2131
     * Subscribes students to the given session and optionally (default)
2132
     * unsubscribes previous users.
2133
     *
2134
     * @author Carlos Vargas from existing code
2135
     * @author Julio Montoya. Cleaning code.
2136
     *
2137
     * @param int   $sessionId
2138
     * @param array $userList
2139
     * @param int   $session_visibility
2140
     * @param bool  $empty_users
2141
     * @param bool  $registerUsersToAllCourses
2142
     *
2143
     * @return bool
2144
     */
2145
    public static function subscribeUsersToSession(
2146
        $sessionId,
2147
        $userList,
2148
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2149
        $empty_users = true,
2150
        $registerUsersToAllCourses = true
2151
    ) {
2152
        $sessionId = (int) $sessionId;
2153
2154
        if (empty($sessionId)) {
2155
            return false;
2156
        }
2157
2158
        foreach ($userList as $intUser) {
2159
            if ($intUser != strval(intval($intUser))) {
2160
                return false;
2161
            }
2162
        }
2163
2164
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2165
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2166
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2167
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2168
2169
        $session = api_get_session_entity($sessionId);
2170
2171
        // from function parameter
2172
        if (empty($session_visibility)) {
2173
            $session_visibility = $session->getVisibility();
2174
            //default status loaded if empty
2175
            // by default readonly 1
2176
            if (empty($session_visibility)) {
2177
                $session_visibility = SESSION_VISIBLE_READ_ONLY;
2178
            }
2179
        } elseif (!in_array($session_visibility, [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_INVISIBLE])) {
2180
            $session_visibility = SESSION_VISIBLE_READ_ONLY;
2181
        }
2182
2183
        $sql = "SELECT user_id FROM $tbl_session_rel_course_rel_user
2184
                WHERE session_id = $sessionId AND status = ".Session::STUDENT;
2185
        $result = Database::query($sql);
2186
        $existingUsers = [];
2187
        while ($row = Database::fetch_array($result)) {
2188
            $existingUsers[] = $row['user_id'];
2189
        }
2190
2191
        $sql = "SELECT c_id FROM $tbl_session_rel_course
2192
                WHERE session_id = $sessionId";
2193
        $result = Database::query($sql);
2194
        $course_list = [];
2195
        while ($row = Database::fetch_array($result)) {
2196
            $course_list[] = $row['c_id'];
2197
        }
2198
2199
        if ($session->getSendSubscriptionNotification() && is_array($userList)) {
2200
            foreach ($userList as $user_id) {
2201
                $tplSubject = new Template(
2202
                    null,
2203
                    false,
2204
                    false,
2205
                    false,
2206
                    false,
2207
                    false
2208
                );
2209
                $layoutSubject = $tplSubject->get_template(
2210
                    'mail/subject_subscription_to_session_confirmation.tpl'
2211
                );
2212
                $subject = $tplSubject->fetch($layoutSubject);
2213
                $user_info = api_get_user_info($user_id);
2214
2215
                $tplContent = new Template(
2216
                    null,
2217
                    false,
2218
                    false,
2219
                    false,
2220
                    false,
2221
                    false
2222
                );
2223
                // Variables for default template
2224
                $tplContent->assign('complete_name', stripslashes($user_info['complete_name']));
2225
                $tplContent->assign('session_name', $session->getTitle());
2226
                $tplContent->assign(
2227
                    'session_coaches',
2228
                    $session->getGeneralCoaches()->map(fn(User $coach) => UserManager::formatUserFullName($coach))
2229
                );
2230
                $layoutContent = $tplContent->get_template(
2231
                    'mail/content_subscription_to_session_confirmation.tpl'
2232
                );
2233
                $content = $tplContent->fetch($layoutContent);
2234
2235
                // Send email
2236
                api_mail_html(
2237
                    $user_info['complete_name'],
2238
                    $user_info['mail'],
2239
                    $subject,
2240
                    $content,
2241
                    api_get_person_name(
2242
                        api_get_setting('administratorName'),
2243
                        api_get_setting('administratorSurname')
2244
                    ),
2245
                    api_get_setting('emailAdministrator')
2246
                );
2247
2248
                // Record message in system
2249
                MessageManager::send_message_simple(
2250
                    $user_id,
2251
                    $subject,
2252
                    $content,
2253
                    api_get_user_id(),
2254
                    false,
2255
                    true
2256
                );
2257
            }
2258
        }
2259
2260
        if ($session->getNotifyBoss()) {
2261
            foreach ($userList as $user_id) {
2262
                $studentBossList = UserManager::getStudentBossList($user_id);
2263
2264
                if (!empty($studentBossList)) {
2265
                    $studentBossList = array_column($studentBossList, 'boss_id');
2266
                    foreach ($studentBossList as $bossId) {
2267
                        $boss = api_get_user_entity($bossId);
2268
                        self::notifyBossOfInscription($boss, $session, $user_id);
2269
                    }
2270
                }
2271
            }
2272
        }
2273
2274
        if ($registerUsersToAllCourses) {
2275
            foreach ($course_list as $courseId) {
2276
                // for each course in the session
2277
                $nbr_users = 0;
2278
                $courseId = (int) $courseId;
2279
2280
                $sql = "SELECT DISTINCT user_id
2281
                        FROM $tbl_session_rel_course_rel_user
2282
                        WHERE
2283
                            session_id = $sessionId AND
2284
                            c_id = $courseId AND
2285
                            status = ".Session::STUDENT;
2286
                $result = Database::query($sql);
2287
                $existingUsers = [];
2288
                while ($row = Database::fetch_array($result)) {
2289
                    $existingUsers[] = $row['user_id'];
2290
                }
2291
2292
                // Delete existing users
2293
                if ($empty_users) {
2294
                    foreach ($existingUsers as $existing_user) {
2295
                        if (!in_array($existing_user, $userList)) {
2296
                            self::unSubscribeUserFromCourseSession($existing_user, $courseId, $sessionId);
2297
                        }
2298
                    }
2299
                }
2300
2301
                $usersToSubscribeInCourse = array_filter(
2302
                    $userList,
2303
                    function ($userId) use ($existingUsers) {
2304
                        return !in_array($userId, $existingUsers);
2305
                    }
2306
                );
2307
2308
                self::insertUsersInCourse(
2309
                    $usersToSubscribeInCourse,
2310
                    $courseId,
2311
                    $sessionId,
2312
                    ['visibility' => $session_visibility],
2313
                    false
2314
                );
2315
            }
2316
        }
2317
2318
        // Delete users from the session
2319
        if (true === $empty_users) {
2320
            $sql = "DELETE FROM $tbl_session_rel_user
2321
                    WHERE
2322
                      session_id = $sessionId AND
2323
                      relation_type = ".Session::STUDENT;
2324
            // Don't reset session_rel_user.registered_at of users that will be registered later anyways.
2325
            if (!empty($userList)) {
2326
                $avoidDeleteThisUsers = " AND user_id NOT IN ('".implode("','", $userList)."')";
2327
                $sql .= $avoidDeleteThisUsers;
2328
            }
2329
            Event::addEvent(
2330
                LOG_SESSION_DELETE_USER,
2331
                LOG_USER_ID,
2332
                'all',
2333
                api_get_utc_datetime(),
2334
                api_get_user_id(),
2335
                null,
2336
                $sessionId
2337
            );
2338
            Database::query($sql);
2339
        }
2340
2341
        // Insert missing users into session
2342
        foreach ($userList as $enreg_user) {
2343
            $isUserSubscribed = self::isUserSubscribedAsStudent($sessionId, $enreg_user);
2344
            if (false === $isUserSubscribed) {
2345
                $enreg_user = (int) $enreg_user;
2346
                if ($session->getDuration() > 0) {
2347
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at)
2348
                        VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."')";
2349
                } else {
2350
                    if (null != ($accessStartDate = $session->getAccessStartDate())) {
2351
                        $accessStartDate = "'".$accessStartDate->format('Y-m-d H:i:s')."'";
2352
                    } else {
2353
                        $accessStartDate = "NULL";
2354
                    }
2355
                    if (null != ($accessEndDate = $session->getAccessEndDate())) {
2356
                        $accessEndDate = "'".$accessEndDate->format('Y-m-d H:i:s')."'";
2357
                    } else {
2358
                        $accessEndDate = "NULL";
2359
                    }
2360
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at, access_start_date, access_end_date)
2361
                            VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."', ".$accessStartDate.", ".$accessEndDate.")";
2362
                }
2363
                Database::query($sql);
2364
                Event::addEvent(
2365
                    LOG_SESSION_ADD_USER,
2366
                    LOG_USER_ID,
2367
                    $enreg_user,
2368
                    api_get_utc_datetime(),
2369
                    api_get_user_id(),
2370
                    null,
2371
                    $sessionId
2372
                );
2373
            }
2374
        }
2375
2376
        // update number of users in the session
2377
        $sql = "UPDATE $tbl_session
2378
                SET nbr_users = (SELECT count(user_id) FROM $tbl_session_rel_user WHERE session_id = $sessionId)
2379
                WHERE id = $sessionId";
2380
        Database::query($sql);
2381
2382
        return true;
2383
    }
2384
2385
    /**
2386
     * Sends a notification email to the student's boss when the student is enrolled in a session.
2387
     *
2388
     * @param User $boss The boss of the student to be notified.
2389
     * @param Session $session The session the student has been enrolled in.
2390
     * @param int $userId The ID of the student being enrolled.
2391
     */
2392
    public static function notifyBossOfInscription(User $boss, Session $session, int $userId): void
2393
    {
2394
        $tpl = Container::getTwig();
2395
2396
        $user_info = api_get_user_info($userId);
2397
2398
        $subject = $tpl->render(
2399
            '@ChamiloCore/Mailer/Legacy/subject_subscription_to_boss_notification.html.twig',
2400
            [
2401
                'locale' => $boss->getLocale(),
2402
                'boss_name' => $boss->getFullName(),
2403
                'student_name' => $user_info['complete_name'],
2404
                'session_name' => $session->getTitle(),
2405
            ]
2406
        );
2407
2408
        $content = $tpl->render(
2409
            '@ChamiloCore/Mailer/Legacy/content_subscription_to_boss_notification.html.twig',
2410
            [
2411
                'locale' => $boss->getLocale(),
2412
                'boss_name' => $boss->getFullName(),
2413
                'student_name' => $user_info['complete_name'],
2414
                'session_name' => $session->getTitle(),
2415
            ]
2416
        );
2417
2418
        // Send email
2419
        api_mail_html(
2420
            $boss->getFullName(),
2421
            $boss->getEmail(),
2422
            $subject,
2423
            $content,
2424
            api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname')),
2425
            api_get_setting('emailAdministrator')
2426
        );
2427
2428
        // Record message in system
2429
        MessageManager::send_message_simple(
2430
            $boss->getId(),
2431
            $subject,
2432
            $content,
2433
            api_get_user_id(),
2434
            false,
2435
            true
2436
        );
2437
    }
2438
2439
    /**
2440
     * Returns user list of the current users subscribed in the course-session.
2441
     *
2442
     * @param int   $sessionId
2443
     * @param array $courseInfo
2444
     * @param int   $status
2445
     *
2446
     * @return array
2447
     */
2448
    public static function getUsersByCourseSession(
2449
        $sessionId,
2450
        $courseInfo,
2451
        $status = null
2452
    ) {
2453
        $sessionId = (int) $sessionId;
2454
        $courseId = $courseInfo['real_id'];
2455
2456
        if (empty($sessionId) || empty($courseId)) {
2457
            return [];
2458
        }
2459
2460
        $statusCondition = null;
2461
        if (isset($status) && !is_null($status)) {
2462
            $status = (int) $status;
2463
            $statusCondition = " AND status = $status";
2464
        }
2465
2466
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2467
2468
        $sql = "SELECT DISTINCT user_id
2469
                FROM $table
2470
                WHERE
2471
                    session_id = $sessionId AND
2472
                    c_id = $courseId
2473
                    $statusCondition
2474
                ";
2475
2476
        $result = Database::query($sql);
2477
        $existingUsers = [];
2478
        while ($row = Database::fetch_array($result)) {
2479
            $existingUsers[] = $row['user_id'];
2480
        }
2481
2482
        return $existingUsers;
2483
    }
2484
2485
    /**
2486
     * Returns user list of the current users subscribed in the course-session.
2487
     *
2488
     * @param array $sessionList
2489
     * @param array $courseList
2490
     * @param int   $status
2491
     * @param int   $start
2492
     * @param int   $limit
2493
     *
2494
     * @return array
2495
     */
2496
    public static function getUsersByCourseAndSessionList(
2497
        $sessionList,
2498
        $courseList,
2499
        $status = null,
2500
        $start = null,
2501
        $limit = null
2502
    ) {
2503
        if (empty($sessionList) || empty($courseList)) {
2504
            return [];
2505
        }
2506
        $sessionListToString = implode("','", $sessionList);
2507
        $courseListToString = implode("','", $courseList);
2508
2509
        $statusCondition = null;
2510
        if (isset($status) && !is_null($status)) {
2511
            $status = (int) $status;
2512
            $statusCondition = " AND status = $status";
2513
        }
2514
2515
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2516
2517
        $sql = "SELECT DISTINCT user_id
2518
                FROM $table
2519
                WHERE
2520
                    session_id IN ('$sessionListToString') AND
2521
                    c_id IN ('$courseListToString')
2522
                    $statusCondition
2523
                ";
2524
        if (!is_null($start) && !is_null($limit)) {
2525
            $start = (int) $start;
2526
            $limit = (int) $limit;
2527
            $sql .= "LIMIT $start, $limit";
2528
        }
2529
        $result = Database::query($sql);
2530
        $existingUsers = [];
2531
        while ($row = Database::fetch_array($result)) {
2532
            $existingUsers[] = $row['user_id'];
2533
        }
2534
2535
        return $existingUsers;
2536
    }
2537
2538
    /**
2539
     * Remove a list of users from a course-session.
2540
     *
2541
     * @param array $userList
2542
     * @param int   $sessionId
2543
     * @param array $courseInfo
2544
     * @param int   $status
2545
     * @param bool  $updateTotal
2546
     *
2547
     * @return bool
2548
     */
2549
    public static function removeUsersFromCourseSession(
2550
        $userList,
2551
        $sessionId,
2552
        $courseInfo,
2553
        $status = null,
2554
        $updateTotal = true
2555
    ) {
2556
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2557
        $tableSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2558
        $sessionId = (int) $sessionId;
2559
2560
        if (empty($sessionId) || empty($userList) || empty($courseInfo)) {
2561
            return false;
2562
        }
2563
2564
        $courseId = is_array($courseInfo) ? $courseInfo['real_id'] : $courseInfo;
2565
2566
        $statusCondition = null;
2567
        if (isset($status) && !is_null($status)) {
2568
            $status = (int) $status;
2569
            $statusCondition = " AND status = $status";
2570
        }
2571
2572
        foreach ($userList as $userId) {
2573
            $userId = (int) $userId;
2574
            $sql = "DELETE FROM $table
2575
                    WHERE
2576
                        session_id = $sessionId AND
2577
                        c_id = $courseId AND
2578
                        user_id = $userId
2579
                        $statusCondition
2580
                    ";
2581
            Database::query($sql);
2582
2583
            Event::addEvent(
2584
                LOG_SESSION_DELETE_USER_COURSE,
2585
                LOG_USER_ID,
2586
                $userId,
2587
                api_get_utc_datetime(),
2588
                api_get_user_id(),
2589
                $courseId,
2590
                $sessionId
2591
            );
2592
        }
2593
2594
        if ($updateTotal) {
2595
            // Count users in this session-course relation
2596
            $sql = "SELECT COUNT(user_id) as nbUsers
2597
                    FROM $table
2598
                    WHERE
2599
                        session_id = $sessionId AND
2600
                        c_id = $courseId AND
2601
                        status = ".Session::STUDENT;
2602
            $result = Database::query($sql);
2603
            [$userCount] = Database::fetch_array($result);
2604
2605
            // update the session-course relation to add the users total
2606
            $sql = "UPDATE $tableSessionCourse
2607
                    SET nbr_users = $userCount
2608
                    WHERE
2609
                        session_id = $sessionId AND
2610
                        c_id = $courseId";
2611
            Database::query($sql);
2612
        }
2613
    }
2614
2615
    /**
2616
     * Subscribe a user to an specific course inside a session.
2617
     *
2618
     * @param array  $user_list
2619
     * @param int    $session_id
2620
     * @param string $course_code
2621
     * @param int    $session_visibility
2622
     * @param bool   $removeUsersNotInList
2623
     *
2624
     * @return bool
2625
     */
2626
    public static function subscribe_users_to_session_course(
2627
        $user_list,
2628
        $session_id,
2629
        $course_code,
2630
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2631
        $removeUsersNotInList = false
2632
    ) {
2633
        if (empty($session_id) || empty($course_code)) {
2634
            return false;
2635
        }
2636
2637
        $session_id = (int) $session_id;
2638
        $session_visibility = (int) $session_visibility;
2639
        $course_code = Database::escape_string($course_code);
2640
        $courseInfo = api_get_course_info($course_code);
2641
        $courseId = $courseInfo['real_id'];
2642
        $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseInfo);
2643
        $forums = [];
2644
        if (1 === $subscribe) {
2645
            $forums = get_forums($courseId, $session_id);
2646
        }
2647
2648
        if ($removeUsersNotInList) {
2649
            $currentUsers = self::getUsersByCourseSession($session_id, $courseInfo, 0);
2650
2651
            if (!empty($user_list)) {
2652
                $userToDelete = array_diff($currentUsers, $user_list);
2653
            } else {
2654
                $userToDelete = $currentUsers;
2655
            }
2656
2657
            if (!empty($userToDelete)) {
2658
                self::removeUsersFromCourseSession(
2659
                    $userToDelete,
2660
                    $session_id,
2661
                    $courseInfo,
2662
                    0,
2663
                    true
2664
                );
2665
            }
2666
        }
2667
2668
        self::insertUsersInCourse(
2669
            $user_list,
2670
            $courseId,
2671
            $session_id,
2672
            ['visibility' => $session_visibility],
2673
            true,
2674
            true
2675
        );
2676
    }
2677
2678
    /**
2679
     * Unsubscribe user from session.
2680
     *
2681
     * @param int Session id
2682
     * @param int User id
2683
     *
2684
     * @return bool True in case of success, false in case of error
2685
     */
2686
    public static function unsubscribe_user_from_session($session_id, $user_id)
2687
    {
2688
        $session_id = (int) $session_id;
2689
        $user_id = (int) $user_id;
2690
2691
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2692
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2693
2694
        $sql = "DELETE FROM $tbl_session_rel_user
2695
                WHERE
2696
                    session_id = $session_id AND
2697
                    user_id = $user_id ";
2698
        Database::query($sql);
2699
2700
        // Update number of users
2701
        $sql = "UPDATE $tbl_session
2702
                SET nbr_users = nbr_users - 1
2703
                WHERE id = $session_id ";
2704
        Database::query($sql);
2705
2706
        Event::addEvent(
2707
            LOG_SESSION_DELETE_USER,
2708
            LOG_USER_ID,
2709
            $user_id,
2710
            api_get_utc_datetime(),
2711
            api_get_user_id(),
2712
            null,
2713
            $session_id
2714
        );
2715
2716
        // Get the list of courses related to this session
2717
        $course_list = self::get_course_list_by_session_id($session_id);
2718
        if (!empty($course_list)) {
2719
            foreach ($course_list as $course) {
2720
                self::unSubscribeUserFromCourseSession($user_id, $course['id'], $session_id);
2721
            }
2722
        }
2723
2724
        return true;
2725
    }
2726
2727
    /**
2728
     * @param int $user_id
2729
     * @param int $courseId
2730
     * @param int $session_id
2731
     */
2732
    public static function unSubscribeUserFromCourseSession($user_id, $courseId, $session_id)
2733
    {
2734
        $user_id = (int) $user_id;
2735
        $courseId = (int) $courseId;
2736
        $session_id = (int) $session_id;
2737
2738
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2739
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2740
2741
        // Delete user from course
2742
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2743
                WHERE session_id = $session_id AND c_id = $courseId AND user_id = $user_id";
2744
        $result = Database::query($sql);
2745
2746
        if (Database::affected_rows($result)) {
2747
            // Update number of users in this relation
2748
            $sql = "UPDATE $tbl_session_rel_course SET
2749
                    nbr_users = nbr_users - 1
2750
                    WHERE session_id = $session_id AND c_id = $courseId";
2751
            Database::query($sql);
2752
        }
2753
2754
        Event::addEvent(
2755
            LOG_SESSION_DELETE_USER_COURSE,
2756
            LOG_USER_ID,
2757
            $user_id,
2758
            api_get_utc_datetime(),
2759
            api_get_user_id(),
2760
            $courseId,
2761
            $session_id
2762
        );
2763
    }
2764
2765
    /**
2766
     * Subscribes courses to the given session and optionally (default)
2767
     * unsubscribe previous users.
2768
     *
2769
     * @author Carlos Vargas from existing code
2770
     *
2771
     * @param int   $sessionId
2772
     * @param array $courseList                     List of courses int ids
2773
     * @param bool  $removeExistingCoursesWithUsers Whether to unsubscribe
2774
     *                                              existing courses and users (true, default) or not (false)
2775
     * @param bool  $copyEvaluation                 from base course to session course
2776
     * @param bool  $copyCourseTeachersAsCoach
2777
     * @param bool  $importAssignments
2778
     *
2779
     * @throws Exception
2780
     *
2781
     * @return bool False on failure, true otherwise
2782
     * */
2783
    public static function add_courses_to_session(
2784
        $sessionId,
2785
        $courseList,
2786
        $removeExistingCoursesWithUsers = true,
2787
        $copyEvaluation = false,
2788
        $copyCourseTeachersAsCoach = false,
2789
        $importAssignments = false
2790
    ) {
2791
        $sessionId = (int) $sessionId;
2792
2793
        if (empty($sessionId) || empty($courseList)) {
2794
            return false;
2795
        }
2796
2797
        $session = api_get_session_entity($sessionId);
2798
2799
        if (!$session) {
2800
            return false;
2801
        }
2802
        $sessionVisibility = $session->getVisibility();
2803
2804
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2805
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2806
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2807
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2808
2809
        // Get list of courses subscribed to this session
2810
        $sql = "SELECT c_id
2811
                FROM $tbl_session_rel_course
2812
                WHERE session_id = $sessionId";
2813
        $rs = Database::query($sql);
2814
        $existingCourses = Database::store_result($rs);
2815
        $nbr_courses = count($existingCourses);
2816
2817
        // Get list of users subscribed to this session
2818
        $sql = "SELECT user_id
2819
                FROM $tbl_session_rel_user
2820
                WHERE
2821
                    session_id = $sessionId AND
2822
                    relation_type = ".Session::STUDENT;
2823
        $result = Database::query($sql);
2824
        $user_list = Database::store_result($result);
2825
2826
        // Remove existing courses from the session.
2827
        if (true === $removeExistingCoursesWithUsers && !empty($existingCourses)) {
2828
            foreach ($existingCourses as $existingCourse) {
2829
                if (!in_array($existingCourse['c_id'], $courseList)) {
2830
                    $sql = "DELETE FROM $tbl_session_rel_course
2831
                            WHERE
2832
                                c_id = ".$existingCourse['c_id']." AND
2833
                                session_id = $sessionId";
2834
                    Database::query($sql);
2835
2836
                    $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2837
                            WHERE
2838
                                c_id = ".$existingCourse['c_id']." AND
2839
                                session_id = $sessionId";
2840
                    Database::query($sql);
2841
2842
                    Event::addEvent(
2843
                        LOG_SESSION_DELETE_COURSE,
2844
                        LOG_COURSE_ID,
2845
                        $existingCourse['c_id'],
2846
                        api_get_utc_datetime(),
2847
                        api_get_user_id(),
2848
                        $existingCourse['c_id'],
2849
                        $sessionId
2850
                    );
2851
2852
                    CourseManager::remove_course_ranking($existingCourse['c_id']);
2853
                    $nbr_courses--;
2854
                }
2855
            }
2856
        }
2857
2858
        // Pass through the courses list we want to add to the session
2859
        foreach ($courseList as $courseId) {
2860
            $courseInfo = api_get_course_info_by_id($courseId);
2861
2862
            // If course doesn't exist continue!
2863
            if (empty($courseInfo)) {
2864
                continue;
2865
            }
2866
2867
            $exists = false;
2868
            // check if the course we want to add is already subscribed
2869
            foreach ($existingCourses as $existingCourse) {
2870
                if ($courseId == $existingCourse['c_id']) {
2871
                    $exists = true;
2872
                }
2873
            }
2874
2875
            if (!$exists) {
2876
                // Copy gradebook categories and links (from base course)
2877
                // to the new course session
2878
                if ($copyEvaluation) {
2879
                    $cats = Category::load(null, null, $courseId);
2880
                    if (!empty($cats)) {
2881
                        $sessionCategory = Category:: load(
2882
                            null,
2883
                            null,
2884
                            $courseId,
2885
                            null,
2886
                            null,
2887
                            $sessionId,
2888
                            null
2889
                        );
2890
2891
                        // @todo remove commented code
2892
                        if (empty($sessionCategory)) {
2893
                            // There is no category for this course+session, so create one
2894
                            $cat = new Category();
2895
                            $sessionName = $session->getTitle();
2896
                            $cat->set_name($courseInfo['code'].' - '.get_lang('Session').' '.$sessionName);
2897
                            $cat->set_session_id($sessionId);
2898
                            $cat->setCourseId($courseId);
2899
                            $cat->set_description(null);
2900
                            //$cat->set_user_id($stud_id);
2901
                            $cat->set_parent_id(0);
2902
                            $cat->set_weight(100);
2903
                            $cat->set_visible(0);
2904
                            $cat->set_certificate_min_score(75);
2905
                            $cat->setGenerateCertificates(1);
2906
                            $cat->setIsRequirement(1);
2907
                            $cat->add();
2908
                            $sessionGradeBookCategoryId = $cat->get_id();
2909
                        } else {
2910
                            if (!empty($sessionCategory[0])) {
2911
                                $sessionGradeBookCategoryId = $sessionCategory[0]->get_id();
2912
                            }
2913
                        }
2914
2915
                        $categoryIdList = [];
2916
                        /** @var Category $cat */
2917
                        foreach ($cats as $cat) {
2918
                            $categoryIdList[$cat->get_id()] = $cat->get_id();
2919
                        }
2920
2921
                        $newCategoryIdList = [];
2922
                        foreach ($cats as $cat) {
2923
                            $links = $cat->get_links(
2924
                                null,
2925
                                false,
2926
                                $courseId,
2927
                                $sessionId
2928
                            );
2929
2930
                            //$cat->set_session_id($sessionId);
2931
                            //$oldCategoryId = $cat->get_id();
2932
                            //$newId = $cat->add();
2933
                            //$newCategoryIdList[$oldCategoryId] = $newId;
2934
                            //$parentId = $cat->get_parent_id();
2935
2936
                            /*if (!empty($parentId)) {
2937
                                $newParentId = $newCategoryIdList[$parentId];
2938
                                $cat->set_parent_id($newParentId);
2939
                                $cat->save();
2940
                            }*/
2941
2942
                            if (!empty($links)) {
2943
                                /** @var AbstractLink $link */
2944
                                foreach ($links as $link) {
2945
                                    //$newCategoryId = $newCategoryIdList[$link->get_category_id()];
2946
                                    $link->set_category_id($sessionGradeBookCategoryId);
2947
                                    $link->add();
2948
                                }
2949
                            }
2950
2951
                            $evaluationList = $cat->get_evaluations(
2952
                                null,
2953
                                false,
2954
                                $courseId,
2955
                                $sessionId
2956
                            );
2957
2958
                            if (!empty($evaluationList)) {
2959
                                /** @var Evaluation $evaluation */
2960
                                foreach ($evaluationList as $evaluation) {
2961
                                    //$evaluationId = $newCategoryIdList[$evaluation->get_category_id()];
2962
                                    $evaluation->set_category_id($sessionGradeBookCategoryId);
2963
                                    $evaluation->add();
2964
                                }
2965
                            }
2966
                        }
2967
2968
                        // Create
2969
                        DocumentManager::generateDefaultCertificate(
2970
                            $courseInfo,
2971
                            true,
2972
                            $sessionId
2973
                        );
2974
                    }
2975
                }
2976
2977
                if ($importAssignments) {
2978
                    $repo = Container::getStudentPublicationRepository();
2979
                    $course = api_get_course_entity($courseId);
2980
                    $session = api_get_session_entity($sessionId);
2981
                    $user = api_get_user_entity();
2982
2983
                    $qb = $repo->getResourcesByCourse($course, null);
2984
                    $qb
2985
                        ->andWhere('resource.active = 1')
2986
                        ->andWhere('resource.filetype = :filetype')
2987
                        ->andWhere('resource.publicationParent IS NULL')
2988
                        ->setParameter('filetype', 'folder');
2989
2990
                    $baseAssignments = $qb->getQuery()->getResult();
2991
2992
                    foreach ($baseAssignments as $originalAssignment) {
2993
                        if (!$originalAssignment instanceof CStudentPublication) {
2994
                            continue;
2995
                        }
2996
2997
                        $newAssignment = new CStudentPublication();
2998
                        $newAssignment
2999
                            ->setTitle($originalAssignment->getTitle())
3000
                            ->setDescription($originalAssignment->getDescription() ?? '')
3001
                            ->setActive(1)
3002
                            ->setAccepted(true)
3003
                            ->setFiletype('folder')
3004
                            ->setPostGroupId(0)
3005
                            ->setSentDate(new \DateTime())
3006
                            ->setQualification($originalAssignment->getQualification())
3007
                            ->setWeight($originalAssignment->getWeight())
3008
                            ->setAllowTextAssignment($originalAssignment->getAllowTextAssignment())
3009
                            ->setUser($user)
3010
                            ->setParent($course)
3011
                            ->addCourseLink($course, $session, null);
3012
3013
                        $repo->create($newAssignment);
3014
                    }
3015
                }
3016
                // If the course isn't subscribed yet
3017
                $sql = "INSERT INTO $tbl_session_rel_course (session_id, c_id, nbr_users, position)
3018
                        VALUES ($sessionId, $courseId, 0, 0)";
3019
                Database::query($sql);
3020
3021
                Event::addEvent(
3022
                    LOG_SESSION_ADD_COURSE,
3023
                    LOG_COURSE_ID,
3024
                    $courseId,
3025
                    api_get_utc_datetime(),
3026
                    api_get_user_id(),
3027
                    $courseId,
3028
                    $sessionId
3029
                );
3030
3031
                // We add the current course in the existing courses array,
3032
                // to avoid adding another time the current course
3033
                $existingCourses[] = ['c_id' => $courseId];
3034
                $nbr_courses++;
3035
3036
                // Subscribe all the users from the session to this course inside the session
3037
                self::insertUsersInCourse(
3038
                    array_column($user_list, 'user_id'),
3039
                    $courseId,
3040
                    $sessionId,
3041
                    ['visibility' => $sessionVisibility],
3042
                    false
3043
                );
3044
            }
3045
3046
            if ($copyCourseTeachersAsCoach) {
3047
                $teachers = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
3048
                if (!empty($teachers)) {
3049
                    foreach ($teachers as $teacher) {
3050
                        self::updateCoaches(
3051
                            $sessionId,
3052
                            $courseId,
3053
                            [$teacher['user_id']],
3054
                            false
3055
                        );
3056
                    }
3057
                }
3058
            }
3059
        }
3060
3061
        $sql = "UPDATE $tbl_session SET nbr_courses = $nbr_courses WHERE id = $sessionId";
3062
        Database::query($sql);
3063
3064
        return true;
3065
    }
3066
3067
    /**
3068
     * Unsubscribe course from a session.
3069
     *
3070
     * @param int $session_id
3071
     * @param int $course_id
3072
     *
3073
     * @return bool True in case of success, false otherwise
3074
     */
3075
    public static function unsubscribe_course_from_session($session_id, $course_id)
3076
    {
3077
        $session_id = (int) $session_id;
3078
        $course_id = (int) $course_id;
3079
3080
        if (empty($course_id) || empty($session_id)) {
3081
            return false;
3082
        }
3083
3084
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3085
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3086
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3087
3088
        // Unsubscribe course.
3089
        $sql = "DELETE FROM $tbl_session_rel_course
3090
                WHERE c_id = $course_id AND session_id = $session_id";
3091
        $result = Database::query($sql);
3092
        $nb_affected = Database::affected_rows($result);
3093
3094
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
3095
                WHERE c_id = $course_id AND session_id = $session_id";
3096
        Database::query($sql);
3097
3098
        Event::addEvent(
3099
            LOG_SESSION_DELETE_COURSE,
3100
            LOG_COURSE_ID,
3101
            $course_id,
3102
            api_get_utc_datetime(),
3103
            api_get_user_id(),
3104
            $course_id,
3105
            $session_id
3106
        );
3107
3108
        if ($nb_affected > 0) {
3109
            // Update number of courses in the session
3110
            $sql = "UPDATE $tbl_session SET nbr_courses= nbr_courses - $nb_affected
3111
                    WHERE id = $session_id";
3112
            Database::query($sql);
3113
3114
            return true;
3115
        }
3116
3117
        return false;
3118
    }
3119
3120
    /**
3121
     * Creates a new extra field for a given session.
3122
     *
3123
     * @param string $variable    Field's internal variable name
3124
     * @param int    $fieldType   Field's type
3125
     * @param string $displayText Field's language var name
3126
     * @param string $default     Field's default value
3127
     *
3128
     * @return int new extra field id
3129
     */
3130
    public static function create_session_extra_field(
3131
        $variable,
3132
        $valueType,
3133
        $displayText,
3134
        $default = ''
3135
    ) {
3136
        $extraField = new ExtraFieldModel('session');
3137
        $params = [
3138
            'variable' => $variable,
3139
            'value_type' => $valueType,
3140
            'display_text' => $displayText,
3141
            'default_value' => $default,
3142
        ];
3143
3144
        return $extraField->save($params);
3145
    }
3146
3147
    /**
3148
     * Update an extra field value for a given session.
3149
     *
3150
     * @param int    $sessionId Session ID
3151
     * @param string $variable  Field variable name
3152
     * @param string $value     Optional. Default field value
3153
     *
3154
     * @return bool|int An integer when register a new extra field. And boolean when update the extrafield
3155
     */
3156
    public static function update_session_extra_field_value($sessionId, $variable, $value = '')
3157
    {
3158
        $extraFieldValue = new ExtraFieldValue('session');
3159
        $params = [
3160
            'item_id' => $sessionId,
3161
            'variable' => $variable,
3162
            'value' => $value,
3163
        ];
3164
3165
        return $extraFieldValue->save($params);
3166
    }
3167
3168
    /**
3169
     * Checks the relationship between a session and a course.
3170
     *
3171
     * @param int $session_id
3172
     * @param int $courseId
3173
     *
3174
     * @return bool returns TRUE if the session and the course are related, FALSE otherwise
3175
     * */
3176
    public static function relation_session_course_exist($session_id, $courseId)
3177
    {
3178
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3179
        $return_value = false;
3180
        $sql = "SELECT c_id FROM $tbl_session_course
3181
                WHERE
3182
                  session_id = ".intval($session_id)." AND
3183
                  c_id = ".intval($courseId);
3184
        $result = Database::query($sql);
3185
        $num = Database::num_rows($result);
3186
        if ($num > 0) {
3187
            $return_value = true;
3188
        }
3189
3190
        return $return_value;
3191
    }
3192
3193
    /**
3194
     * Get the session information by name.
3195
     *
3196
     * @param string $name
3197
     *
3198
     * @return mixed false if the session does not exist, array if the session exist
3199
     */
3200
    public static function get_session_by_name($name)
3201
    {
3202
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3203
        $name = Database::escape_string(trim($name));
3204
        if (empty($name)) {
3205
            return false;
3206
        }
3207
3208
        $sql = 'SELECT *
3209
		        FROM '.$tbl_session.'
3210
		        WHERE title = "'.$name.'"';
3211
        $result = Database::query($sql);
3212
        $num = Database::num_rows($result);
3213
        if ($num > 0) {
3214
            return Database::fetch_array($result);
3215
        } else {
3216
            return false;
3217
        }
3218
    }
3219
3220
    /**
3221
     * @param int $sessionId
3222
     * @param int $name
3223
     *
3224
     * @return bool
3225
     */
3226
    public static function sessionNameExistBesidesMySession($sessionId, $name)
3227
    {
3228
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
3229
        $name = Database::escape_string(trim($name));
3230
        $sessionId = (int) $sessionId;
3231
3232
        if (empty($name)) {
3233
            return false;
3234
        }
3235
3236
        $sql = "SELECT *
3237
		        FROM $table
3238
		        WHERE title = '$name' AND id <> $sessionId ";
3239
        $result = Database::query($sql);
3240
        $num = Database::num_rows($result);
3241
        if ($num > 0) {
3242
            return true;
3243
        }
3244
3245
        return false;
3246
    }
3247
3248
    /**
3249
     * Create a session category.
3250
     *
3251
     * @author Jhon Hinojosa <[email protected]>, from existing code
3252
     *
3253
     * @param string        name
3254
     * @param int        year_start
3255
     * @param int        month_start
3256
     * @param int        day_start
3257
     * @param int        year_end
3258
     * @param int        month_end
3259
     * @param int        day_end
3260
     *
3261
     * @return int session ID
3262
     * */
3263
    public static function create_category_session(
3264
        $sname,
3265
        $syear_start,
3266
        $smonth_start,
3267
        $sday_start,
3268
        $syear_end,
3269
        $smonth_end,
3270
        $sday_end
3271
    ) {
3272
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3273
        $name = Security::remove_XSS(trim($sname));
3274
        $year_start = intval($syear_start);
3275
        $month_start = intval($smonth_start);
3276
        $day_start = intval($sday_start);
3277
        $year_end = intval($syear_end);
3278
        $month_end = intval($smonth_end);
3279
        $day_end = intval($sday_end);
3280
3281
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3282
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3283
3284
        if (empty($name)) {
3285
            $msg = get_lang('Please give a name to the sessions category');
3286
3287
            return $msg;
3288
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3289
            $msg = get_lang('Invalid start date was given.');
3290
3291
            return $msg;
3292
        } elseif (!$month_end && !$day_end && !$year_end) {
3293
            $date_end = '';
3294
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3295
            $msg = get_lang('Invalid end date was given.');
3296
3297
            return $msg;
3298
        } elseif ($date_start >= $date_end) {
3299
            $msg = get_lang('The first date should be before the end date');
3300
3301
            return $msg;
3302
        }
3303
3304
        $access_url_id = api_get_current_access_url_id();
3305
        $params = [
3306
            'title' => $name,
3307
            'date_start' => $date_start,
3308
            'access_url_id' => $access_url_id,
3309
        ];
3310
3311
        if (!empty($date_end)) {
3312
            $params['date_end'] = $date_end;
3313
        }
3314
3315
        $id = Database::insert($tbl_session_category, $params);
3316
3317
        // Add event to system log
3318
        $user_id = api_get_user_id();
3319
        Event::addEvent(
3320
            LOG_SESSION_CATEGORY_CREATE,
3321
            LOG_SESSION_CATEGORY_ID,
3322
            $id,
3323
            api_get_utc_datetime(),
3324
            $user_id
3325
        );
3326
3327
        return $id;
3328
    }
3329
3330
    /**
3331
     * Edit a sessions category.
3332
     *
3333
     * @author Jhon Hinojosa <[email protected]>,from existing code
3334
     *
3335
     * @param int        id
3336
     * @param string        name
3337
     * @param int        year_start
3338
     * @param int        month_start
3339
     * @param int        day_start
3340
     * @param int        year_end
3341
     * @param int        month_end
3342
     * @param int        day_end
3343
     *
3344
     * @return bool
3345
     *              The parameter id is a primary key
3346
     * */
3347
    public static function edit_category_session(
3348
        $id,
3349
        $sname,
3350
        $syear_start,
3351
        $smonth_start,
3352
        $sday_start,
3353
        $syear_end,
3354
        $smonth_end,
3355
        $sday_end
3356
    ) {
3357
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3358
        $name = trim((string) $sname);
3359
        $year_start = intval($syear_start);
3360
        $month_start = intval($smonth_start);
3361
        $day_start = intval($sday_start);
3362
        $year_end = intval($syear_end);
3363
        $month_end = intval($smonth_end);
3364
        $day_end = intval($sday_end);
3365
        $id = intval($id);
3366
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3367
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3368
3369
        if (empty($name)) {
3370
            $msg = get_lang('Please give a name to the sessions category');
3371
3372
            return $msg;
3373
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3374
            $msg = get_lang('Invalid start date was given.');
3375
3376
            return $msg;
3377
        } elseif (!$month_end && !$day_end && !$year_end) {
3378
            $date_end = null;
3379
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3380
            $msg = get_lang('Invalid end date was given.');
3381
3382
            return $msg;
3383
        } elseif ($date_start >= $date_end) {
3384
            $msg = get_lang('The first date should be before the end date');
3385
3386
            return $msg;
3387
        }
3388
        if (null != $date_end) {
3389
            $sql = "UPDATE $tbl_session_category
3390
                    SET
3391
                        title = '".Database::escape_string($name)."',
3392
                        date_start = '$date_start' ,
3393
                        date_end = '$date_end'
3394
                    WHERE id= $id";
3395
        } else {
3396
            $sql = "UPDATE $tbl_session_category SET
3397
                        title = '".Database::escape_string($name)."',
3398
                        date_start = '$date_start',
3399
                        date_end = NULL
3400
                    WHERE id= $id";
3401
        }
3402
        $result = Database::query($sql);
3403
3404
        return $result ? true : false;
3405
    }
3406
3407
    /**
3408
     * Delete sessions categories.
3409
     *
3410
     * @param array|int $categoryId
3411
     * @param bool      $deleteSessions Optional. Include delete session.
3412
     * @param bool      $fromWs         Optional. True if the function is called by a webservice, false otherwise.
3413
     *
3414
     * @return bool Nothing, or false on error
3415
     *              The parameters is a array to delete sessions
3416
     *
3417
     * @author Jhon Hinojosa <[email protected]>, from existing code
3418
     */
3419
    public static function delete_session_category($categoryId, $deleteSessions = false, $fromWs = false)
3420
    {
3421
        $tblSessionCategory = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3422
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
3423
3424
        if (is_array($categoryId)) {
3425
            $categoryId = array_map('intval', $categoryId);
3426
        } else {
3427
            $categoryId = [(int) $categoryId];
3428
        }
3429
3430
        $categoryId = implode(', ', $categoryId);
3431
3432
        if ($deleteSessions) {
3433
            $sql = "SELECT id FROM $tblSession WHERE session_category_id IN ($categoryId)";
3434
            $result = Database::query($sql);
3435
            while ($rows = Database::fetch_array($result)) {
3436
                $sessionId = $rows['id'];
3437
                self::delete($sessionId, $fromWs);
3438
            }
3439
        } else {
3440
            $sql = "UPDATE $tblSession SET session_category_id = NULL WHERE session_category_id IN ($categoryId)";
3441
            Database::query($sql);
3442
        }
3443
3444
        $sql = "DELETE FROM $tblSessionCategory WHERE id IN ($categoryId)";
3445
        Database::query($sql);
3446
3447
        // Add event to system log
3448
        Event::addEvent(
3449
            LOG_SESSION_CATEGORY_DELETE,
3450
            LOG_SESSION_CATEGORY_ID,
3451
            $categoryId,
3452
            api_get_utc_datetime(),
3453
            api_get_user_id()
3454
        );
3455
3456
        return true;
3457
    }
3458
3459
    /**
3460
     * Get a list of sessions of which the given conditions match with an = 'cond'.
3461
     *
3462
     * @param array $conditions          a list of condition example :
3463
     *                                   array('status' => STUDENT) or
3464
     *                                   array('s.title' => array('operator' => 'LIKE', value = '%$needle%'))
3465
     * @param array $order_by            a list of fields on which sort
3466
     * @param int   $urlId
3467
     * @param array $onlyThisSessionList
3468
     *
3469
     * @return array an array with all sessions of the platform
3470
     *
3471
     * @todo   optional course code parameter, optional sorting parameters...
3472
     */
3473
    public static function get_sessions_list(
3474
        $conditions = [],
3475
        $order_by = [],
3476
        $from = null,
3477
        $to = null,
3478
        $urlId = 0,
3479
        $onlyThisSessionList = []
3480
    ) {
3481
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3482
        $session_category_table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3483
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3484
        $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3485
        $session_course_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3486
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
3487
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
3488
        $return_array = [];
3489
3490
        $sql_query = " SELECT
3491
                    DISTINCT(s.id),
3492
                    s.title,
3493
                    s.nbr_courses,
3494
                    s.access_start_date,
3495
                    s.access_end_date,
3496
                    sc.title as category_name,
3497
                    s.promotion_id
3498
				FROM $session_table s
3499
				INNER JOIN $table_access_url_rel_session ar ON ar.session_id = s.id
3500
				LEFT JOIN  $session_category_table sc ON s.session_category_id = sc.id
3501
				LEFT JOIN $session_course_table sco ON (sco.session_id = s.id)
3502
				INNER JOIN $course_table c ON sco.c_id = c.id
3503
				WHERE ar.access_url_id = $urlId ";
3504
3505
        $availableFields = [
3506
            's.id',
3507
            's.title',
3508
            'c.id',
3509
        ];
3510
3511
        $availableOperator = [
3512
            'like',
3513
            '>=',
3514
            '<=',
3515
            '=',
3516
        ];
3517
3518
        if (count($conditions) > 0) {
3519
            foreach ($conditions as $field => $options) {
3520
                $operator = strtolower($options['operator']);
3521
                $value = Database::escape_string($options['value']);
3522
                if (in_array($field, $availableFields) && in_array($operator, $availableOperator)) {
3523
                    $sql_query .= ' AND '.$field." $operator '".$value."'";
3524
                }
3525
            }
3526
        }
3527
3528
        if (!empty($onlyThisSessionList)) {
3529
            $onlyThisSessionList = array_map('intval', $onlyThisSessionList);
3530
            $onlyThisSessionList = implode("','", $onlyThisSessionList);
3531
            $sql_query .= " AND s.id IN ('$onlyThisSessionList') ";
3532
        }
3533
3534
        $orderAvailableList = ['title'];
3535
        if (count($order_by) > 0) {
3536
            $order = null;
3537
            $direction = null;
3538
            if (isset($order_by[0]) && in_array($order_by[0], $orderAvailableList)) {
3539
                $order = $order_by[0];
3540
            }
3541
            if (isset($order_by[1]) && in_array(strtolower($order_by[1]), ['desc', 'asc'])) {
3542
                $direction = $order_by[1];
3543
            }
3544
3545
            if (!empty($order)) {
3546
                $sql_query .= " ORDER BY $order $direction ";
3547
            }
3548
        }
3549
3550
        if (!is_null($from) && !is_null($to)) {
3551
            $to = (int) $to;
3552
            $from = (int) $from;
3553
            $sql_query .= "LIMIT $from, $to";
3554
        }
3555
3556
        $sql_result = Database::query($sql_query);
3557
        if (Database::num_rows($sql_result) > 0) {
3558
            while ($result = Database::fetch_array($sql_result)) {
3559
                $return_array[$result['id']] = $result;
3560
            }
3561
        }
3562
3563
        return $return_array;
3564
    }
3565
3566
    /**
3567
     * Get the session category information by id.
3568
     *
3569
     * @param string session category ID
3570
     *
3571
     * @return mixed false if the session category does not exist, array if the session category exists
3572
     */
3573
    public static function get_session_category($id)
3574
    {
3575
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3576
        $id = (int) $id;
3577
        $sql = "SELECT id, title, date_start, date_end
3578
                FROM $table
3579
                WHERE id= $id";
3580
        $result = Database::query($sql);
3581
        $num = Database::num_rows($result);
3582
        if ($num > 0) {
3583
            return Database::fetch_array($result);
3584
        } else {
3585
            return false;
3586
        }
3587
    }
3588
3589
    /**
3590
     * Get Hot Sessions (limit 8).
3591
     *
3592
     * @return array with sessions
3593
     */
3594
    public static function getHotSessions()
3595
    {
3596
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3597
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3598
        $tbl_users = Database::get_main_table(TABLE_MAIN_USER);
3599
        $tbl_extra_fields = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3600
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3601
        $tbl_lp = Database::get_course_table(TABLE_LP_MAIN);
3602
3603
        $extraField = new ExtraFieldModel('session');
3604
        $field = $extraField->get_handler_field_info_by_field_variable('image');
3605
3606
        $sql = "SELECT
3607
                s.id,
3608
                s.title,
3609
                s.session_category_id,
3610
                c.title as category_name,
3611
                s.description,
3612
                s.nbr_users as users,
3613
				(SELECT COUNT(*) FROM $tbl_lp WHERE session_id = s.id) as lessons ";
3614
        if (false !== $field) {
3615
            $fieldId = $field['id'];
3616
            $sql .= ",(SELECT value FROM $tbl_extra_fields WHERE field_id = $fieldId AND item_id = s.id) as image ";
3617
        }
3618
        $sql .= " FROM $tbl_session s
3619
                LEFT JOIN $tbl_session_category c
3620
                    ON s.session_category_id = c.id
3621
                ORDER BY 8 DESC
3622
                LIMIT 8";
3623
        $result = Database::query($sql);
3624
3625
        if (Database::num_rows($result) > 0) {
3626
            $plugin = BuyCoursesPlugin::create();
3627
            $checker = $plugin->isEnabled();
3628
            $sessions = [];
3629
            while ($row = Database::fetch_assoc($result)) {
3630
                if (!isset($row['image'])) {
3631
                    $row['image'] = '';
3632
                }
3633
                $row['on_sale'] = '';
3634
                if ($checker) {
3635
                    $row['on_sale'] = $plugin->getItemByProduct(
3636
                        $row['id'],
3637
                        BuyCoursesPlugin::PRODUCT_TYPE_SESSION
3638
                    );
3639
                }
3640
                $sessions[] = $row;
3641
            }
3642
3643
            return $sessions;
3644
        }
3645
3646
        return false;
3647
    }
3648
3649
    /**
3650
     * Get all session categories (filter by access_url_id).
3651
     *
3652
     * @return mixed false if the session category does not exist, array if the session category exists
3653
     */
3654
    public static function get_all_session_category()
3655
    {
3656
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3657
        $id = api_get_current_access_url_id();
3658
        $sql = 'SELECT * FROM '.$table.'
3659
                WHERE access_url_id = '.$id.'
3660
                ORDER BY title ASC';
3661
        $result = Database::query($sql);
3662
        if (Database::num_rows($result) > 0) {
3663
            $data = Database::store_result($result, 'ASSOC');
3664
3665
            return $data;
3666
        }
3667
3668
        return false;
3669
    }
3670
3671
    /**
3672
     * Assign a coach to course in session with status = 2.
3673
     *
3674
     * @param int  $userId
3675
     * @param int  $sessionId
3676
     * @param int  $courseId
3677
     * @param bool $noCoach   optional, if is true the user don't be a coach now,
3678
     *                        otherwise it'll assign a coach
3679
     *
3680
     * @return bool true if there are affected rows, otherwise false
3681
     */
3682
    public static function set_coach_to_course_session(
3683
        $userId,
3684
        $sessionId = 0,
3685
        $courseId = 0,
3686
        $noCoach = false
3687
    ) {
3688
        $userId = (int) $userId;
3689
3690
        $sessionId = !empty($sessionId) ? (int) $sessionId : api_get_session_id();
3691
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_id();
3692
3693
        if (empty($sessionId) || empty($courseId) || empty($userId)) {
3694
            return false;
3695
        }
3696
3697
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3698
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3699
3700
        $user = api_get_user_entity($userId);
3701
3702
        if (!$user->isTeacher()) {
3703
            return false;
3704
        }
3705
3706
        if ($noCoach) {
3707
            // Delete the course-specific coach record
3708
            $sql = "DELETE FROM $tblSessionRelCourseRelUser
3709
                WHERE
3710
                    session_id = $sessionId AND
3711
                    c_id = $courseId AND
3712
                    user_id = $userId AND
3713
                    status = ".Session::COURSE_COACH;
3714
            $result = Database::query($sql);
3715
3716
            // Check if the user is still a coach for any course in this session
3717
            $sql = "SELECT COUNT(*) AS count FROM $tblSessionRelCourseRelUser
3718
                WHERE
3719
                    session_id = $sessionId AND
3720
                    user_id = $userId AND
3721
                    status = ".Session::COURSE_COACH;
3722
            $res = Database::query($sql);
3723
            $resultRow = Database::fetch_assoc($res);
3724
3725
            // If the user is no longer a coach for any course in this session, remove the session relationship
3726
            if (0 === (int) $resultRow['count']) {
3727
                $sql = "DELETE FROM $tblSessionRelUser
3728
                    WHERE
3729
                        session_id = $sessionId AND
3730
                        user_id = $userId AND
3731
                        relation_type = ".Session::COURSE_COACH;
3732
                Database::query($sql);
3733
            }
3734
3735
            return Database::affected_rows($result) > 0;
3736
        }
3737
3738
        // Assign user as a coach to course
3739
        // First check if the user is registered to the course
3740
        $sql = "SELECT user_id FROM $tblSessionRelCourseRelUser
3741
                WHERE
3742
                    session_id = $sessionId AND
3743
                    c_id = $courseId AND
3744
                    user_id = $userId";
3745
        $rs_check = Database::query($sql);
3746
3747
        // Then update or insert.
3748
        if (Database::num_rows($rs_check) > 0) {
3749
            $sql = "UPDATE $tblSessionRelCourseRelUser
3750
                    SET status = ".Session::COURSE_COACH."
3751
                    WHERE
3752
                        session_id = $sessionId AND
3753
                        c_id = $courseId AND
3754
                        user_id = $userId ";
3755
            $result = Database::query($sql);
3756
3757
            return Database::affected_rows($result) > 0;
3758
        }
3759
3760
        $em = Container::getEntityManager();
3761
        $em->clear();
3762
        $session = $em->getRepository(Session::class)->find($sessionId);
3763
        $course = api_get_course_entity($courseId);
3764
        if (!$session->hasCourse($course)) {
3765
            $session->addCourse($course);
3766
        }
3767
        $sessionRepo = Container::getSessionRepository();
3768
        $sessionRepo->addUserInCourse(
3769
            Session::COURSE_COACH,
3770
            api_get_user_entity($userId),
3771
            $course,
3772
            $session
3773
        );
3774
3775
        $sessionRepo->update($session);
3776
3777
        return true;
3778
    }
3779
3780
    /**
3781
     * Subscribes sessions to human resource manager (Dashboard feature).
3782
     *
3783
     * @param array $userInfo               Human Resource Manager info
3784
     * @param array $sessions_list          Sessions id
3785
     * @param bool  $sendEmail
3786
     * @param bool  $removeSessionsFromUser
3787
     *
3788
     * @return int
3789
     * */
3790
    public static function subscribeSessionsToDrh(
3791
        $userInfo,
3792
        $sessions_list,
3793
        $sendEmail = false,
3794
        $removeSessionsFromUser = true
3795
    ) {
3796
        // Database Table Definitions
3797
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3798
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3799
3800
        if (empty($userInfo)) {
3801
            return 0;
3802
        }
3803
3804
        $userId = $userInfo['user_id'];
3805
        $user = api_get_user_entity();
3806
3807
        // Only subscribe DRH users.
3808
        $rolesAllowed = [
3809
            DRH,
3810
            SESSIONADMIN,
3811
            PLATFORM_ADMIN,
3812
            COURSE_TUTOR,
3813
        ];
3814
        $isAdmin = api_is_platform_admin_by_id($userInfo['user_id']);
3815
        if (!$isAdmin && !in_array($userInfo['status'], $rolesAllowed)) {
3816
            return 0;
3817
        }
3818
3819
        $affected_rows = 0;
3820
        // Deleting assigned sessions to hrm_id.
3821
        if ($removeSessionsFromUser) {
3822
            if (api_is_multiple_url_enabled()) {
3823
                $sql = "SELECT s.session_id
3824
                        FROM $tbl_session_rel_user s
3825
                        INNER JOIN $tbl_session_rel_access_url a
3826
                        ON (a.session_id = s.session_id)
3827
                        WHERE
3828
                            s.user_id = $userId AND
3829
                            relation_type = ".Session::DRH." AND
3830
                            access_url_id = ".api_get_current_access_url_id();
3831
            } else {
3832
                $sql = "SELECT s.session_id
3833
                        FROM $tbl_session_rel_user s
3834
                        WHERE user_id = $userId AND relation_type=".Session::DRH;
3835
            }
3836
            $result = Database::query($sql);
3837
3838
            if (Database::num_rows($result) > 0) {
3839
                while ($row = Database::fetch_array($result)) {
3840
                    $sql = "DELETE FROM $tbl_session_rel_user
3841
                            WHERE
3842
                                session_id = {$row['session_id']} AND
3843
                                user_id = $userId AND
3844
                                relation_type =".Session::DRH;
3845
                    Database::query($sql);
3846
                }
3847
            }
3848
        }
3849
3850
        // Inserting new sessions list.
3851
        if (!empty($sessions_list) && is_array($sessions_list)) {
3852
            foreach ($sessions_list as $session_id) {
3853
                $session = api_get_session_entity($session_id);
3854
3855
                if (!$session->hasUserInSession($user, Session::DRH)) {
3856
                    $session->addUserInSession(Session::DRH, $user);
3857
3858
                    $affected_rows++;
3859
                }
3860
            }
3861
        }
3862
3863
        return $affected_rows;
3864
    }
3865
3866
    /**
3867
     * @param int $sessionId
3868
     *
3869
     * @return array
3870
     */
3871
    public static function getDrhUsersInSession($sessionId)
3872
    {
3873
        return self::get_users_by_session($sessionId, Session::DRH);
3874
    }
3875
3876
    /**
3877
     * @param int $userId
3878
     * @param int $sessionId
3879
     *
3880
     * @return array
3881
     */
3882
    public static function getSessionFollowedByDrh($userId, $sessionId)
3883
    {
3884
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3885
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3886
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3887
3888
        $userId = (int) $userId;
3889
        $sessionId = (int) $sessionId;
3890
3891
        $select = " SELECT * ";
3892
        if (api_is_multiple_url_enabled()) {
3893
            $sql = " $select FROM $tbl_session s
3894
                    INNER JOIN $tbl_session_rel_user sru ON (sru.session_id = s.id)
3895
                    LEFT JOIN $tbl_session_rel_access_url a ON (s.id = a.session_id)
3896
                    WHERE
3897
                        sru.user_id = '$userId' AND
3898
                        sru.session_id = '$sessionId' AND
3899
                        sru.relation_type = '".Session::DRH."' AND
3900
                        access_url_id = ".api_get_current_access_url_id()."
3901
                    ";
3902
        } else {
3903
            $sql = "$select FROM $tbl_session s
3904
                     INNER JOIN $tbl_session_rel_user sru
3905
                     ON
3906
                        sru.session_id = s.id AND
3907
                        sru.user_id = '$userId' AND
3908
                        sru.session_id = '$sessionId' AND
3909
                        sru.relation_type = '".Session::DRH."'
3910
                    ";
3911
        }
3912
3913
        $result = Database::query($sql);
3914
        if (Database::num_rows($result)) {
3915
            $row = Database::fetch_assoc($result);
3916
            $row['course_list'] = self::get_course_list_by_session_id($sessionId);
3917
3918
            return $row;
3919
        }
3920
3921
        return [];
3922
    }
3923
3924
    /**
3925
     * Get sessions followed by human resources manager.
3926
     *
3927
     * @param int    $userId
3928
     * @param int    $start
3929
     * @param int    $limit
3930
     * @param bool   $getCount
3931
     * @param bool   $getOnlySessionId
3932
     * @param bool   $getSql
3933
     * @param string $orderCondition
3934
     * @param string $keyword
3935
     * @param string $description
3936
     * @param array  $options
3937
     *
3938
     * @return array sessions
3939
     */
3940
    public static function get_sessions_followed_by_drh(
3941
        $userId,
3942
        $start = null,
3943
        $limit = null,
3944
        $getCount = false,
3945
        $getOnlySessionId = false,
3946
        $getSql = false,
3947
        $orderCondition = null,
3948
        $keyword = '',
3949
        $description = '',
3950
        $options = []
3951
    ) {
3952
        return self::getSessionsFollowedByUser(
3953
            $userId,
3954
            DRH,
3955
            $start,
3956
            $limit,
3957
            $getCount,
3958
            $getOnlySessionId,
3959
            $getSql,
3960
            $orderCondition,
3961
            $keyword,
3962
            $description,
3963
            $options
3964
        );
3965
    }
3966
3967
    /**
3968
     * Get sessions followed by human resources manager.
3969
     *
3970
     * @param int    $userId
3971
     * @param int    $status           DRH Optional
3972
     * @param int    $start
3973
     * @param int    $limit
3974
     * @param bool   $getCount
3975
     * @param bool   $getOnlySessionId
3976
     * @param bool   $getSql
3977
     * @param string $orderCondition
3978
     * @param string $keyword
3979
     * @param string $description
3980
     * @param array  $options
3981
     *
3982
     * @return array|string sessions
3983
     */
3984
    public static function getSessionsFollowedByUser(
3985
        $userId,
3986
        $status = null,
3987
        $start = null,
3988
        $limit = null,
3989
        $getCount = false,
3990
        $getOnlySessionId = false,
3991
        $getSql = false,
3992
        $orderCondition = null,
3993
        $keyword = '',
3994
        $description = '',
3995
        $options = []
3996
    ) {
3997
        // Database Table Definitions
3998
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3999
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4000
4001
        $extraFieldModel = new ExtraFieldModel('session');
4002
        $conditions = $extraFieldModel->parseConditions($options);
4003
        $sqlInjectJoins = $conditions['inject_joins'];
4004
        $extraFieldsConditions = $conditions['where'];
4005
        $sqlInjectWhere = $conditions['inject_where'];
4006
        $injectExtraFields = $conditions['inject_extra_fields'];
4007
4008
        if (!empty($injectExtraFields)) {
4009
            $injectExtraFields = ' , '.$injectExtraFields.' s.id';
4010
        }
4011
4012
        $userId = (int) $userId;
4013
        $user = api_get_user_entity($userId);
4014
4015
        $select = ' SELECT DISTINCT * '.$injectExtraFields;
4016
        if ($getCount) {
4017
            $select = ' SELECT count(DISTINCT(s.id)) as count ';
4018
        }
4019
4020
        if ($getOnlySessionId) {
4021
            $select = ' SELECT DISTINCT(s.id) ';
4022
        }
4023
4024
        $limitCondition = null;
4025
        if (!is_null($start) && !is_null($limit)) {
4026
            $limitCondition = " LIMIT ".intval($start).", ".intval($limit);
4027
        }
4028
4029
        if (empty($orderCondition)) {
4030
            $orderCondition = ' ORDER BY s.title ';
4031
        }
4032
4033
        $whereConditions = null;
4034
4035
        switch ($status) {
4036
            case DRH:
4037
                $sessionsQuery = array_map(
4038
                    fn(Session $session) => $session->getId(),
4039
                    $user->getDRHSessions()
4040
                );
4041
                break;
4042
            case COURSEMANAGER:
4043
                $coachSessions = array_map(
4044
                    fn(Session $session) => $session->getId(),
4045
                    $user->getSessionsByStatusInCourseSubscription(Session::COURSE_COACH)->getValues()
4046
                );
4047
                $generalCoachSessions = array_map(
4048
                    fn(Session $session) => $session->getId(),
4049
                    $user->getSessionsAsGeneralCoach()
4050
                );
4051
4052
                $sessionsQuery = array_merge($coachSessions, $generalCoachSessions);
4053
                break;
4054
            case SESSIONADMIN:
4055
                $sessionsQuery = array_map(
4056
                    fn(Session $session) => $session->getId(),
4057
                    $user->getSessionsAsAdmin()
4058
                );
4059
                break;
4060
            default:
4061
                $sessionsQuery = array_map(
4062
                    fn(Session $session) => $session->getId(),
4063
                    $user->getSessionsAsStudent()
4064
                );
4065
                break;
4066
        }
4067
4068
        $keywordCondition = '';
4069
        if (!empty($keyword)) {
4070
            $keyword = Database::escape_string($keyword);
4071
            $keywordCondition = " AND (s.title LIKE '%$keyword%' ) ";
4072
            if (!empty($description)) {
4073
                $description = Database::escape_string($description);
4074
                $keywordCondition = " AND (s.title LIKE '%$keyword%' OR s.description LIKE '%$description%' ) ";
4075
            }
4076
        }
4077
4078
        $whereConditions .= $keywordCondition;
4079
        $subQuery = !empty($sessionsQuery) ? (' AND s.id IN ('.implode(',', $sessionsQuery).')') : '';
4080
4081
        $sql = " $select
4082
                FROM $tbl_session s
4083
                INNER JOIN $tbl_session_rel_access_url a
4084
                ON (s.id = a.session_id)
4085
                $sqlInjectJoins
4086
                WHERE
4087
                    access_url_id = ".api_get_current_access_url_id()."
4088
                    $subQuery
4089
                    $whereConditions
4090
                    $extraFieldsConditions
4091
                    $sqlInjectWhere
4092
                    $orderCondition
4093
                    $limitCondition";
4094
4095
        if ($getSql) {
4096
            return $sql;
4097
        }
4098
        $result = Database::query($sql);
4099
4100
        if ($getCount) {
4101
            $row = Database::fetch_array($result);
4102
            if ($row) {
4103
                return (int) $row['count'];
4104
            }
4105
4106
            return 0;
4107
        }
4108
4109
        $sessions = [];
4110
        if (Database::num_rows($result) > 0) {
4111
            $imgPath = Display::return_icon(
4112
                'session_default_small.png',
4113
                null,
4114
                [],
4115
                ICON_SIZE_SMALL,
4116
                false,
4117
                true
4118
            );
4119
4120
            $extraFieldValue = new ExtraFieldValue('session');
4121
            while ($row = Database::fetch_array($result)) {
4122
                if ($getOnlySessionId) {
4123
                    $sessions[$row['id']] = $row;
4124
                    continue;
4125
                }
4126
4127
                $extraFieldImage = $extraFieldValue->get_values_by_handler_and_field_variable($row['id'], 'image');
4128
                $image = $imgPath;
4129
                if (!empty($extraFieldImage) && isset($extraFieldImage['url'])) {
4130
                    $image = $extraFieldImage['url'];
4131
                }
4132
                $row['image'] = $image;
4133
                if ('0000-00-00 00:00:00' === $row['display_start_date'] || '0000-00-00' === $row['display_start_date']) {
4134
                    $row['display_start_date'] = null;
4135
                }
4136
4137
                if ('0000-00-00 00:00:00' === $row['display_end_date'] || '0000-00-00' === $row['display_end_date']) {
4138
                    $row['display_end_date'] = null;
4139
                }
4140
4141
                if ('0000-00-00 00:00:00' === $row['access_start_date'] || '0000-00-00' === $row['access_start_date']) {
4142
                    $row['access_start_date'] = null;
4143
                }
4144
4145
                if ('0000-00-00 00:00:00' === $row['access_end_date'] || '0000-00-00' === $row['access_end_date']) {
4146
                    $row['access_end_date'] = null;
4147
                }
4148
4149
                if ('0000-00-00 00:00:00' === $row['coach_access_start_date'] ||
4150
                    '0000-00-00' === $row['coach_access_start_date']
4151
                ) {
4152
                    $row['coach_access_start_date'] = null;
4153
                }
4154
4155
                if ('0000-00-00 00:00:00' === $row['coach_access_end_date'] ||
4156
                    '0000-00-00' === $row['coach_access_end_date']
4157
                ) {
4158
                    $row['coach_access_end_date'] = null;
4159
                }
4160
4161
                $sessions[$row['id']] = $row;
4162
            }
4163
        }
4164
4165
        return $sessions;
4166
    }
4167
4168
    /**
4169
     * Gets the list (or the count) of courses by session filtered by access_url.
4170
     *
4171
     * @param int    $session_id  The session id
4172
     * @param string $course_name The course code
4173
     * @param string $orderBy     Field to order the data
4174
     * @param bool   $getCount    Optional. Count the session courses
4175
     *
4176
     * @return array|int List of courses. Whether $getCount is true, return the count
4177
     */
4178
    public static function get_course_list_by_session_id(
4179
        $session_id,
4180
        $course_name = '',
4181
        $orderBy = null,
4182
        $getCount = false
4183
    ) {
4184
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4185
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4186
        $session_id = (int) $session_id;
4187
        $sqlSelect = '*, c.id, c.id as real_id, c.code as course_code';
4188
4189
        if ($getCount) {
4190
            $sqlSelect = 'COUNT(1) as count';
4191
        }
4192
4193
        // select the courses
4194
        $sql = "SELECT $sqlSelect
4195
                FROM $tbl_course c
4196
                INNER JOIN $tbl_session_rel_course src
4197
                ON (c.id = src.c_id)
4198
		        WHERE src.session_id = '$session_id' ";
4199
4200
        if (!empty($course_name)) {
4201
            $course_name = Database::escape_string($course_name);
4202
            $sql .= " AND c.title LIKE '%$course_name%' ";
4203
        }
4204
4205
        if (!empty($orderBy)) {
4206
            $orderBy = Database::escape_string($orderBy);
4207
            $orderBy = " ORDER BY $orderBy";
4208
        } else {
4209
            if (self::orderCourseIsEnabled()) {
4210
                $orderBy .= ' ORDER BY position ';
4211
            } else {
4212
                $orderBy .= ' ORDER BY title ';
4213
            }
4214
        }
4215
4216
        $sql .= Database::escape_string($orderBy);
4217
        $result = Database::query($sql);
4218
        $num_rows = Database::num_rows($result);
4219
        $courses = [];
4220
        if ($num_rows > 0) {
4221
            if ($getCount) {
4222
                $count = Database::fetch_assoc($result);
4223
4224
                return (int) $count['count'];
4225
            }
4226
4227
            while ($row = Database::fetch_assoc($result)) {
4228
                $courses[$row['real_id']] = $row;
4229
            }
4230
        }
4231
4232
        return $courses;
4233
    }
4234
4235
    /**
4236
     * Gets the list of courses by session filtered by access_url.
4237
     *
4238
     * @param $userId
4239
     * @param $sessionId
4240
     * @param null   $from
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $from is correct as it would always require null to be passed?
Loading history...
4241
     * @param null   $limit
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $limit is correct as it would always require null to be passed?
Loading history...
4242
     * @param null   $column
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $column is correct as it would always require null to be passed?
Loading history...
4243
     * @param null   $direction
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $direction is correct as it would always require null to be passed?
Loading history...
4244
     * @param bool   $getCount
4245
     * @param string $keyword
4246
     *
4247
     * @return array
4248
     */
4249
    public static function getAllCoursesFollowedByUser(
4250
        $userId,
4251
        $sessionId,
4252
        $from = null,
4253
        $limit = null,
4254
        $column = null,
4255
        $direction = null,
4256
        $getCount = false,
4257
        $keyword = ''
4258
    ) {
4259
        if (empty($sessionId)) {
4260
            $sessionsSQL = self::get_sessions_followed_by_drh(
4261
                $userId,
4262
                null,
4263
                null,
4264
                null,
4265
                true,
4266
                true
4267
            );
4268
        } else {
4269
            $sessionsSQL = intval($sessionId);
4270
        }
4271
4272
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4273
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4274
4275
        if ($getCount) {
4276
            $select = "SELECT COUNT(DISTINCT(c.code)) as count ";
4277
        } else {
4278
            $select = "SELECT DISTINCT c.* ";
4279
        }
4280
4281
        $keywordCondition = null;
4282
        if (!empty($keyword)) {
4283
            $keyword = Database::escape_string($keyword);
4284
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4285
        }
4286
4287
        // Select the courses
4288
        $sql = "$select
4289
                FROM $tbl_course c
4290
                INNER JOIN $tbl_session_rel_course src
4291
                ON c.id = src.c_id
4292
		        WHERE
4293
		            src.session_id IN ($sessionsSQL)
4294
		            $keywordCondition
4295
		        ";
4296
        if ($getCount) {
4297
            $result = Database::query($sql);
4298
            $row = Database::fetch_assoc($result);
4299
4300
            return $row['count'];
4301
        }
4302
4303
        if (isset($from) && isset($limit)) {
4304
            $from = intval($from);
4305
            $limit = intval($limit);
4306
            $sql .= " LIMIT $from, $limit";
4307
        }
4308
4309
        $result = Database::query($sql);
4310
        $num_rows = Database::num_rows($result);
4311
        $courses = [];
4312
4313
        if ($num_rows > 0) {
4314
            while ($row = Database::fetch_assoc($result)) {
4315
                $courses[$row['id']] = $row;
4316
            }
4317
        }
4318
4319
        return $courses;
4320
    }
4321
4322
    /**
4323
     * Gets the list of courses by session filtered by access_url.
4324
     *
4325
     * @param int    $session_id
4326
     * @param string $course_name
4327
     *
4328
     * @return array list of courses
4329
     */
4330
    public static function get_course_list_by_session_id_like($session_id, $course_name = '')
4331
    {
4332
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4333
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4334
4335
        $session_id = (int) $session_id;
4336
        $course_name = Database::escape_string($course_name);
4337
4338
        // select the courses
4339
        $sql = "SELECT c.id, c.title FROM $tbl_course c
4340
                INNER JOIN $tbl_session_rel_course src
4341
                ON c.id = src.c_id
4342
		        WHERE ";
4343
4344
        if (!empty($session_id)) {
4345
            $sql .= "src.session_id LIKE '$session_id' AND ";
4346
        }
4347
4348
        if (!empty($course_name)) {
4349
            $sql .= "UPPER(c.title) LIKE UPPER('%$course_name%') ";
4350
        }
4351
4352
        $sql .= "ORDER BY title;";
4353
        $result = Database::query($sql);
4354
        $num_rows = Database::num_rows($result);
4355
        $courses = [];
4356
        if ($num_rows > 0) {
4357
            while ($row = Database::fetch_assoc($result)) {
4358
                $courses[$row['id']] = $row;
4359
            }
4360
        }
4361
4362
        return $courses;
4363
    }
4364
4365
    /**
4366
     * Gets the count of courses by session filtered by access_url.
4367
     *
4368
     * @param int session id
4369
     * @param string $keyword
4370
     *
4371
     * @return array list of courses
4372
     */
4373
    public static function getCourseCountBySessionId($session_id, $keyword = '')
4374
    {
4375
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4376
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4377
        $session_id = (int) $session_id;
4378
4379
        // select the courses
4380
        $sql = "SELECT COUNT(c.code) count
4381
                FROM $tbl_course c
4382
                INNER JOIN $tbl_session_rel_course src
4383
                ON c.id = src.c_id
4384
		        WHERE src.session_id = '$session_id' ";
4385
4386
        $keywordCondition = null;
4387
        if (!empty($keyword)) {
4388
            $keyword = Database::escape_string($keyword);
4389
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4390
        }
4391
        $sql .= $keywordCondition;
4392
4393
        $result = Database::query($sql);
4394
        $num_rows = Database::num_rows($result);
4395
        if ($num_rows > 0) {
4396
            $row = Database::fetch_assoc($result);
4397
4398
            return $row['count'];
4399
        }
4400
4401
        return null;
4402
    }
4403
4404
    /**
4405
     * Get the session id based on the original id and field name in the extra fields.
4406
     * Returns 0 if session was not found.
4407
     *
4408
     * @param string $value    Original session id
4409
     * @param string $variable Original field name
4410
     *
4411
     * @return int Session id
4412
     */
4413
    public static function getSessionIdFromOriginalId($value, $variable)
4414
    {
4415
        $extraFieldValue = new ExtraFieldValue('session');
4416
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4417
            $variable,
4418
            $value
4419
        );
4420
4421
        if (!empty($result)) {
4422
            return $result['item_id'];
4423
        }
4424
4425
        return 0;
4426
    }
4427
4428
    /**
4429
     * Get users by session.
4430
     *
4431
     * @param int  $id       session id
4432
     * @param int  $status   filter by status coach = 2
4433
     * @param bool $getCount Optional. Allow get the number of rows from the result
4434
     * @param int  $urlId
4435
     *
4436
     * @return array|int A list with an user list. If $getCount is true then return a the count of registers
4437
     */
4438
    public static function get_users_by_session(
4439
        $id,
4440
        $status = null,
4441
        $getCount = false,
4442
        $urlId = 0
4443
    ) {
4444
        if (empty($id)) {
4445
            return [];
4446
        }
4447
        $id = (int) $id;
4448
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
4449
4450
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4451
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4452
        $table_access_url_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4453
4454
        $selectedField = '
4455
            u.id as user_id, u.lastname, u.firstname, u.username, su.relation_type, au.access_url_id,
4456
            su.moved_to, su.moved_status, su.moved_at, su.registered_at
4457
        ';
4458
4459
        if ($getCount) {
4460
            $selectedField = 'count(1) AS count';
4461
        }
4462
4463
        $sql = "SELECT $selectedField
4464
                FROM $tbl_user u
4465
                INNER JOIN $tbl_session_rel_user su
4466
                ON u.id = su.user_id AND
4467
                su.session_id = $id
4468
                LEFT OUTER JOIN $table_access_url_user au
4469
                ON (au.user_id = u.id)
4470
                ";
4471
4472
        if (is_numeric($status)) {
4473
            $status = (int) $status;
4474
            $sql .= " WHERE su.relation_type = $status AND (au.access_url_id = $urlId OR au.access_url_id is null)";
4475
        } else {
4476
            $sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
4477
        }
4478
4479
        $sql .= ' AND u.active <> '.USER_SOFT_DELETED.' ORDER BY su.relation_type, ';
4480
        $sql .= api_sort_by_first_name() ? ' u.firstname, u.lastname' : '  u.lastname, u.firstname';
4481
4482
        $result = Database::query($sql);
4483
        if ($getCount) {
4484
            $count = Database::fetch_assoc($result);
4485
            if ($count) {
4486
                return (int) $count['count'];
4487
            }
4488
4489
            return 0;
4490
        }
4491
4492
        $return = [];
4493
        while ($row = Database::fetch_assoc($result)) {
4494
            $return[] = $row;
4495
        }
4496
4497
        return $return;
4498
    }
4499
4500
    /**
4501
     * The general coach (session_rel_user.relation_type = Session::GENERAL_COACH).
4502
     *
4503
     * @param int  $user_id         user id
4504
     * @param bool $asPlatformAdmin The user is platform admin, return everything
4505
     *
4506
     * @return array
4507
     */
4508
    public static function get_sessions_by_general_coach($user_id, $asPlatformAdmin = false)
4509
    {
4510
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
4511
        $user_id = (int) $user_id;
4512
4513
        $innerJoin = '';
4514
        $whereConditions = '';
4515
4516
        if (!$asPlatformAdmin) {
4517
            $innerJoin = " INNER JOIN session_rel_user AS sru ON (s.id = sru.session_id) ";
4518
            $whereConditions = "sru.user_id = $user_id AND sru.relation_type = ".Session::GENERAL_COACH;
4519
        }
4520
4521
        if (api_is_multiple_url_enabled()) {
4522
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4523
            $access_url_id = api_get_current_access_url_id();
4524
4525
            if (-1 != $access_url_id) {
4526
                $innerJoin .= " INNER JOIN $tblSessionRelAccessUrl session_rel_url
4527
                    ON (s.id = access_url_rel_session.session_id)";
4528
                $whereConditions .= " AND access_url_rel_session.access_url_id = $access_url_id";
4529
            }
4530
        }
4531
        $sql = "SELECT s.* FROM $sessionTable AS s $innerJoin ";
4532
        if (!empty($whereConditions)) {
4533
            $sql .= "WHERE $whereConditions ";
4534
        }
4535
        $sql .= "ORDER BY s.title";
4536
        $result = Database::query($sql);
4537
4538
        return Database::store_result($result, 'ASSOC');
4539
    }
4540
4541
    /**
4542
     * @param int $user_id
4543
     * @param int $courseId
4544
     * @param int $session_id
4545
     *
4546
     * @return array|bool
4547
     */
4548
    public static function get_user_status_in_course_session($user_id, $courseId, $session_id)
4549
    {
4550
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4551
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4552
        $sql = "SELECT session_rcru.status
4553
                FROM $table session_rcru
4554
                INNER JOIN $tbl_user user
4555
                ON (session_rcru.user_id = user.id)
4556
                WHERE
4557
                    session_rcru.session_id = '".intval($session_id)."' AND
4558
                    session_rcru.c_id ='".intval($courseId)."' AND
4559
                    user.id = ".intval($user_id);
4560
4561
        $result = Database::query($sql);
4562
        $status = false;
4563
        if (Database::num_rows($result)) {
4564
            $status = Database::fetch_row($result);
4565
            $status = $status['0'];
4566
        }
4567
4568
        return $status;
4569
    }
4570
4571
    /**
4572
     * Gets user status within a session.
4573
     *
4574
     * @param int $userId
4575
     * @param int $sessionId
4576
     *
4577
     * @return SessionRelUser
4578
     */
4579
    public static function getUserStatusInSession($userId, $sessionId)
4580
    {
4581
        $em = Database::getManager();
4582
        $subscriptions = $em
4583
            ->getRepository(SessionRelUser::class)
4584
            ->findBy(['session' => $sessionId, 'user' => $userId]);
4585
4586
        /** @var SessionRelUser $subscription */
4587
        $subscription = current($subscriptions);
4588
4589
        return $subscription;
4590
    }
4591
4592
    /**
4593
     * @param int $id
4594
     *
4595
     * @return array
4596
     */
4597
    public static function get_all_sessions_by_promotion($id)
4598
    {
4599
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4600
4601
        return Database::select(
4602
            '*',
4603
            $table,
4604
            ['where' => ['promotion_id = ?' => $id]]
4605
        );
4606
    }
4607
4608
    /**
4609
     * @param int   $promotion_id
4610
     * @param array $list
4611
     */
4612
    public static function subscribe_sessions_to_promotion($promotion_id, $list)
4613
    {
4614
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4615
        $params = [];
4616
        $params['promotion_id'] = 0;
4617
        Database::update(
4618
            $table,
4619
            $params,
4620
            ['promotion_id = ?' => $promotion_id]
4621
        );
4622
4623
        $params['promotion_id'] = $promotion_id;
4624
        if (!empty($list)) {
4625
            foreach ($list as $session_id) {
4626
                $session_id = (int) $session_id;
4627
                Database::update($table, $params, ['id = ?' => $session_id]);
4628
            }
4629
        }
4630
    }
4631
4632
    /**
4633
     * Updates a session status.
4634
     *
4635
     * @param int session id
4636
     * @param int status
4637
     */
4638
    public static function set_session_status($session_id, $status)
4639
    {
4640
        $t = Database::get_main_table(TABLE_MAIN_SESSION);
4641
        $params['visibility'] = $status;
4642
        Database::update($t, $params, ['id = ?' => $session_id]);
4643
    }
4644
4645
    /**
4646
     * Copies a session with the same data to a new session.
4647
     * The new copy is not assigned to the same promotion.
4648
     *
4649
     * @param int  $id                         Session ID
4650
     * @param bool $copy_courses               Whether to copy the relationship with courses
4651
     * @param bool $copyTeachersAndDrh
4652
     * @param bool $create_new_courses         New courses will be created
4653
     * @param bool $set_exercises_lp_invisible Set exercises and LPs in the new session to invisible by default
4654
     * @param bool $copyWithSessionContent     Copy course session content into the courses
4655
     *
4656
     * @return int The new session ID on success, 0 otherwise
4657
     *
4658
     * @see subscribe_sessions_to_promotions() for that.
4659
     *
4660
     * @todo make sure the extra session fields are copied too
4661
     */
4662
    public static function copy(
4663
        int $id,
4664
        bool $copy_courses = true,
4665
        bool $copyTeachersAndDrh = true,
4666
        bool $create_new_courses = false,
4667
        bool $set_exercises_lp_invisible = false,
4668
        bool $copyWithSessionContent = false,
4669
    ) {
4670
        $id = (int) $id;
4671
        $s = self::fetch($id);
4672
4673
        if (empty($s)) {
4674
            return false;
4675
        }
4676
4677
        // Check all dates before copying
4678
        // Get timestamp for now in UTC - see http://php.net/manual/es/function.time.php#117251
4679
        $now = time() - date('Z');
4680
        // Timestamp in one month
4681
        $inOneMonth = $now + (30 * 24 * 3600);
4682
        $inOneMonth = api_get_local_time($inOneMonth);
4683
        if (api_strtotime($s['access_start_date']) < $now) {
4684
            $s['access_start_date'] = api_get_local_time($now);
4685
        } else {
4686
            $s['access_start_date'] = api_get_local_time($s['access_start_date']);
4687
        }
4688
        if (api_strtotime($s['display_start_date']) < $now) {
4689
            $s['display_start_date'] = api_get_local_time($now);
4690
        } else {
4691
            $s['display_start_date'] = api_get_local_time($s['display_start_date']);
4692
        }
4693
        if (api_strtotime($s['coach_access_start_date']) < $now) {
4694
            $s['coach_access_start_date'] = api_get_local_time($now);
4695
        } else {
4696
            $s['coach_access_start_date'] = api_get_local_time($s['coach_access_start_date']);
4697
        }
4698
        if (api_strtotime($s['access_end_date']) < $now) {
4699
            $s['access_end_date'] = $inOneMonth;
4700
        } else {
4701
            $s['access_end_date'] = api_get_local_time($s['access_end_date']);
4702
        }
4703
        if (api_strtotime($s['display_end_date']) < $now) {
4704
            $s['display_end_date'] = $inOneMonth;
4705
        } else {
4706
            $s['display_end_date'] = api_get_local_time($s['display_end_date']);
4707
        }
4708
        if (api_strtotime($s['coach_access_end_date']) < $now) {
4709
            $s['coach_access_end_date'] = $inOneMonth;
4710
        } else {
4711
            $s['coach_access_end_date'] = api_get_local_time($s['coach_access_end_date']);
4712
        }
4713
4714
        $extraFieldValue = new ExtraFieldValue('session');
4715
        $extraFieldsValues = $extraFieldValue->getAllValuesByItem($id);
4716
        $extraFieldsValuesToCopy = [];
4717
        if (!empty($extraFieldsValues)) {
4718
            foreach ($extraFieldsValues as $extraFieldValue) {
4719
                //$extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4720
                $extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']]['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4721
            }
4722
        }
4723
4724
        // @todo fix session image url copy.
4725
        /*if (isset($extraFieldsValuesToCopy['extra_image']) &&
4726
            isset($extraFieldsValuesToCopy['extra_image']['extra_image'])
4727
        ) {
4728
            $extraFieldsValuesToCopy['extra_image'] = [
4729
                'tmp_name' => api_get_path(SYS_UPLOAD_PATH).$extraFieldsValuesToCopy['extra_image']['extra_image'],
4730
                'error' => 0,
4731
            ];
4732
        }*/
4733
4734
        $generalCoaches = self::getGeneralCoachesIdForSession($id);
4735
4736
        // Now try to create the session
4737
        $sid = self::create_session(
4738
            $s['title'].' '.get_lang('Copy'),
4739
            $s['access_start_date'],
4740
            $s['access_end_date'],
4741
            $s['display_start_date'],
4742
            $s['display_end_date'],
4743
            $s['coach_access_start_date'],
4744
            $s['coach_access_end_date'],
4745
            $generalCoaches,
4746
            $s['session_category_id'],
4747
            (int) $s['visibility'],
4748
            true,
4749
            $s['duration'],
4750
            $s['description'],
4751
            $s['show_description'],
4752
            $extraFieldsValuesToCopy
4753
        );
4754
4755
        if (!is_numeric($sid) || empty($sid)) {
4756
            return false;
4757
        }
4758
4759
        if ($copy_courses) {
4760
            // Register courses from the original session to the new session
4761
            $courses = self::get_course_list_by_session_id($id);
4762
            $short_courses = $new_short_courses = [];
4763
            if (is_array($courses) && count($courses) > 0) {
4764
                foreach ($courses as $course) {
4765
                    $short_courses[] = $course;
4766
                }
4767
            }
4768
4769
            // We will copy the current courses of the session to new courses
4770
            if (!empty($short_courses)) {
4771
                if ($create_new_courses) {
4772
                    api_set_more_memory_and_time_limits();
4773
                    $params = [];
4774
                    $params['skip_lp_dates'] = true;
4775
4776
                    foreach ($short_courses as $course_data) {
4777
                        $course = CourseManager::copy_course_simple(
4778
                            $course_data['title'].' '.get_lang('Copy'),
4779
                            $course_data['course_code'],
4780
                            $id,
4781
                            $sid,
4782
                            $params
4783
                        );
4784
4785
                        if (null !== $course) {
4786
                            $course_info = api_get_course_info($course->getCode());
4787
                            //By default new elements are invisible
4788
                            if ($set_exercises_lp_invisible) {
4789
                                $list = new LearnpathList('', $course_info, $sid);
4790
                                $flat_list = $list->get_flat_list();
4791
                                if (!empty($flat_list)) {
4792
                                    foreach ($flat_list as $lp_id => $data) {
4793
                                        // @todo fix
4794
                                        /*api_item_property_update(
4795
                                            $course_info,
4796
                                            TOOL_LEARNPATH,
4797
                                            $lp_id,
4798
                                            'invisible',
4799
                                            api_get_user_id(),
4800
                                            0,
4801
                                            0,
4802
                                            0,
4803
                                            0,
4804
                                            $sid
4805
                                        );*/
4806
                                    }
4807
                                }
4808
                                $quiz_table = Database::get_course_table(TABLE_QUIZ_TEST);
4809
                                $course_id = $course_info['real_id'];
4810
                                //@todo check this query
4811
                                $sql = "UPDATE $quiz_table SET active = 0
4812
                                        WHERE c_id = $course_id AND session_id = $sid";
4813
                                Database::query($sql);
4814
                            }
4815
                            $new_short_courses[] = $course_info['real_id'];
4816
                        }
4817
                    }
4818
                } else {
4819
                    foreach ($short_courses as $course_data) {
4820
                        $new_short_courses[] = $course_data['id'];
4821
                    }
4822
                }
4823
4824
                $short_courses = $new_short_courses;
4825
                self::add_courses_to_session($sid, $short_courses, true);
4826
4827
                if ($copyWithSessionContent) {
4828
                    foreach ($courses as $course) {
4829
                        CourseManager::copy_course(
4830
                            $course['code'],
4831
                            $id,
4832
                            $course['code'],
4833
                            $sid,
4834
                            [],
4835
                            false,
4836
                            true
4837
                        );
4838
                    }
4839
                }
4840
4841
                if (false === $create_new_courses && $copyTeachersAndDrh) {
4842
                    foreach ($short_courses as $courseItemId) {
4843
                        $coachList = self::getCoachesByCourseSession($id, $courseItemId);
4844
                        foreach ($coachList as $userId) {
4845
                            self::set_coach_to_course_session($userId, $sid, $courseItemId);
4846
                        }
4847
                    }
4848
                }
4849
            }
4850
        }
4851
4852
        if ($copyTeachersAndDrh) {
4853
            // Register users from the original session to the new session
4854
            $users = self::get_users_by_session($id);
4855
            if (!empty($users)) {
4856
                $userListByStatus = [];
4857
                foreach ($users as $userData) {
4858
                    $userData['relation_type'] = (int) $userData['relation_type'];
4859
                    $userListByStatus[$userData['relation_type']][] = $userData;
4860
                }
4861
4862
                foreach ($userListByStatus as $status => $userList) {
4863
                    $userList = array_column($userList, 'user_id');
4864
                    switch ($status) {
4865
                        case 0:
4866
                            /*self::subscribeUsersToSession(
4867
                                $sid,
4868
                                $userList,
4869
                                SESSION_VISIBLE_READ_ONLY,
4870
                                false,
4871
                                true
4872
                            );*/
4873
                            break;
4874
                        case 1:
4875
                            // drh users
4876
                            foreach ($userList as $drhId) {
4877
                                $userInfo = api_get_user_info($drhId);
4878
                                self::subscribeSessionsToDrh($userInfo, [$sid], false, false);
4879
                            }
4880
                            break;
4881
                    }
4882
                }
4883
            }
4884
        }
4885
4886
        return $sid;
4887
    }
4888
4889
    /**
4890
     * Get the number of sessions.
4891
     *
4892
     * @param int $access_url_id ID of the URL we want to filter on (optional)
4893
     *
4894
     * @return int Number of sessions
4895
     */
4896
    public static function count_sessions($access_url_id = 0)
4897
    {
4898
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
4899
        $access_url_rel_session_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4900
        $access_url_id = (int) $access_url_id;
4901
        $sql = "SELECT count(s.id) FROM $session_table s";
4902
        if (!empty($access_url_id)) {
4903
            $sql .= ", $access_url_rel_session_table u ".
4904
                " WHERE s.id = u.session_id AND u.access_url_id = $access_url_id";
4905
        }
4906
        $res = Database::query($sql);
4907
        $row = Database::fetch_row($res);
4908
4909
        return $row[0];
4910
    }
4911
4912
    public static function cantEditSession(?Session $session = null, bool $checkSession = true): bool
4913
    {
4914
        if (!self::allowToManageSessions()) {
4915
            return false;
4916
        }
4917
4918
        if (api_is_platform_admin() && self::allowed($session)) {
4919
            return true;
4920
        }
4921
4922
        if ($checkSession) {
4923
            if (self::allowed($session)) {
4924
                return true;
4925
            }
4926
4927
            return false;
4928
        }
4929
4930
        return true;
4931
    }
4932
4933
    /**
4934
     * Protect a session to be edited.
4935
     *
4936
     * @return mixed | bool true if pass the check, api_not_allowed otherwise
4937
     */
4938
    public static function protectSession(?Session $session = null, bool $checkSession = true)
4939
    {
4940
        if (!self::cantEditSession($session, $checkSession)) {
4941
            api_not_allowed(true);
4942
        }
4943
    }
4944
4945
    public static function allowToManageSessions(): bool
4946
    {
4947
        if (self::allowManageAllSessions()) {
4948
            return true;
4949
        }
4950
4951
        if (api_is_teacher() && 'true' === api_get_setting('allow_teachers_to_create_sessions')) {
4952
            return true;
4953
        }
4954
4955
        return false;
4956
    }
4957
4958
    /**
4959
     * @return bool
4960
     */
4961
    public static function allowOnlyMySessions()
4962
    {
4963
        if (self::allowToManageSessions() &&
4964
            !api_is_platform_admin() &&
4965
            api_is_teacher()
4966
        ) {
4967
            return true;
4968
        }
4969
4970
        return false;
4971
    }
4972
4973
    /**
4974
     * @return bool
4975
     */
4976
    public static function allowManageAllSessions()
4977
    {
4978
        if (api_is_platform_admin() || api_is_session_admin()) {
4979
            return true;
4980
        }
4981
4982
        return false;
4983
    }
4984
4985
    /**
4986
     * @param $id
4987
     *
4988
     * @return bool
4989
     */
4990
    public static function protect_teacher_session_edit($id)
4991
    {
4992
        if (!api_is_coach($id) && !api_is_platform_admin()) {
4993
            api_not_allowed(true);
4994
        } else {
4995
            return true;
4996
        }
4997
    }
4998
4999
    /**
5000
     * @param int $courseId
5001
     *
5002
     * @return array
5003
     */
5004
    public static function get_session_by_course($courseId)
5005
    {
5006
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5007
        $table_session = Database::get_main_table(TABLE_MAIN_SESSION);
5008
        $url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
5009
        $courseId = (int) $courseId;
5010
        $urlId = api_get_current_access_url_id();
5011
5012
        if (empty($courseId)) {
5013
            return [];
5014
        }
5015
5016
        $sql = "SELECT title, s.id
5017
                FROM $table_session_course sc
5018
                INNER JOIN $table_session s
5019
                ON (sc.session_id = s.id)
5020
                INNER JOIN $url u
5021
                ON (u.session_id = s.id)
5022
                WHERE
5023
                    u.access_url_id = $urlId AND
5024
                    sc.c_id = '$courseId' ";
5025
        $result = Database::query($sql);
5026
5027
        return Database::store_result($result);
5028
    }
5029
5030
    /**
5031
     * @param int  $userId
5032
     * @param bool $ignoreVisibilityForAdmins
5033
     * @param bool $ignoreTimeLimit
5034
     *
5035
     * @return array
5036
     */
5037
    public static function get_sessions_by_user(
5038
        $userId,
5039
        $ignoreVisibilityForAdmins = false,
5040
        $ignoreTimeLimit = false
5041
    ) {
5042
        $sessionCategories = UserManager::get_sessions_by_category(
5043
            $userId,
5044
            false,
5045
            $ignoreVisibilityForAdmins,
5046
            $ignoreTimeLimit
5047
        );
5048
5049
        $sessionArray = [];
5050
        if (!empty($sessionCategories)) {
5051
            foreach ($sessionCategories as $category) {
5052
                if (isset($category['sessions'])) {
5053
                    foreach ($category['sessions'] as $session) {
5054
                        $sessionArray[] = $session;
5055
                    }
5056
                }
5057
            }
5058
        }
5059
5060
        return $sessionArray;
5061
    }
5062
5063
    /**
5064
     * Imports sessions from a CSV file, creating or updating sessions with related users and courses.
5065
     *
5066
     * @return array Contains the import result with errors, counters, and session IDs.
5067
     */
5068
    public static function importCSV(
5069
        string $file,
5070
        bool $updateSession,
5071
        ?int $defaultUserId = null,
5072
        ?Logger $logger = null,
5073
        array $extraFields = [],
5074
        ?string $extraFieldId = null,
5075
        ?int $daysCoachAccessBeforeBeginning = null,
5076
        ?int $daysCoachAccessAfterBeginning = null,
5077
        int $sessionVisibility = 1,
5078
        array $fieldsToAvoidUpdate = [],
5079
        bool $deleteUsersNotInList = false,
5080
        bool $updateCourseCoaches = false,
5081
        bool $sessionWithCoursesModifier = false,
5082
        bool $addOriginalCourseTeachersAsCourseSessionCoaches = true,
5083
        bool $removeAllTeachersFromCourse = true,
5084
        ?int $showDescription = null,
5085
        array &$teacherBackupList = [],
5086
        array &$groupBackup = []
5087
    ): array {
5088
5089
        $sepCheck = Import::assertCommaSeparated($file, true);
5090
        if ($sepCheck !== true) {
5091
            return [
5092
                'error_message'   => $sepCheck,
5093
                'session_counter' => 0,
5094
                'session_list'    => [],
5095
            ];
5096
        }
5097
5098
        $error_message = null;
5099
        $session_counter = 0;
5100
        $defaultUserId = empty($defaultUserId) ? api_get_user_id() : (int) $defaultUserId;
5101
        $defaultUser = api_get_user_entity($defaultUserId);
5102
5103
        $eol = PHP_SAPI != 'cli' ? '<br />' : PHP_EOL;
5104
5105
        $debug = isset($logger);
5106
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5107
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
5108
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5109
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5110
5111
        $rows = Import::csvToArray($file);
5112
        if (empty($rows) || !is_array($rows)) {
5113
            return [
5114
                'error_message'   => get_lang('The specified file is not CSV format !'),
5115
                'session_counter' => 0,
5116
                'session_list'    => [],
5117
            ];
5118
        }
5119
5120
        $normalizeKey = static function (string $k): string {
5121
            return trim(ltrim($k, "\xEF\xBB\xBF"));
5122
        };
5123
5124
        $normalizedRows = [];
5125
        foreach ($rows as $r) {
5126
            $nr = [];
5127
            foreach ($r as $k => $v) {
5128
                $nr[$normalizeKey($k)] = $v;
5129
            }
5130
            $normalizedRows[] = $nr;
5131
        }
5132
        $rows = $normalizedRows;
5133
        $first = $rows[0] ?? [];
5134
        $required = ['SessionName', 'DateStart', 'DateEnd'];
5135
        foreach ($required as $col) {
5136
            if (!array_key_exists($col, $first)) {
5137
                return [
5138
                    'error_message'   => get_lang("The specified file doesn't contain all needed data !"),
5139
                    'session_counter' => 0,
5140
                    'session_list'    => [],
5141
                ];
5142
            }
5143
        }
5144
5145
        $sessions = $rows;
5146
        $sessionList = [];
5147
        $report = [];
5148
        foreach ($sessions as $enreg) {
5149
            $user_counter = 0;
5150
            $course_counter = 0;
5151
5152
            if (!empty($extraFields)) {
5153
                foreach ($extraFields as $original => $to) {
5154
                    $enreg[$to] = $enreg[$original] ?? null;
5155
                }
5156
            }
5157
5158
            $session_name = $enreg['SessionName'];
5159
5160
            if ($debug) {
5161
                $logger->debug('---------------------------------------');
5162
                $logger->debug("Sessions - Start process of session: $session_name");
5163
                $logger->debug('---------------------------------------');
5164
            }
5165
5166
            // Default visibility
5167
            $visibilityAfterExpirationPerSession = $sessionVisibility;
5168
            if (isset($enreg['VisibilityAfterExpiration'])) {
5169
                $visibility = $enreg['VisibilityAfterExpiration'];
5170
                switch ($visibility) {
5171
                    case 'read_only':
5172
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE_READ_ONLY;
5173
                        break;
5174
                    case 'accessible':
5175
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE;
5176
                        break;
5177
                    case 'not_accessible':
5178
                        $visibilityAfterExpirationPerSession = SESSION_INVISIBLE;
5179
                        break;
5180
                }
5181
            }
5182
5183
            if (empty($session_name)) {
5184
                continue;
5185
            }
5186
5187
            $displayAccessStartDate = $enreg['DisplayStartDate'] ?? $enreg['DateStart'];
5188
            $displayAccessEndDate = $enreg['DisplayEndDate'] ?? $enreg['DateEnd'];
5189
            $coachAccessStartDate = $enreg['CoachStartDate'] ?? $enreg['DateStart'];
5190
            $coachAccessEndDate = $enreg['CoachEndDate'] ?? $enreg['DateEnd'];
5191
            $dateStart = date('Y-m-d H:i:s', strtotime(trim($enreg['DateStart'])));
5192
            $displayAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($displayAccessStartDate)));
5193
            $coachAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($coachAccessStartDate)));
5194
            $dateEnd = self::normalizeDateEnd($enreg['DateEnd']);
5195
            $displayAccessEndDate = self::normalizeDateEnd($displayAccessEndDate);
5196
            $coachAccessEndDate = self::normalizeDateEnd($coachAccessEndDate);
5197
            $session_category_id = $enreg['SessionCategory'] ?? null;
5198
            $sessionDescription = $enreg['SessionDescription'] ?? null;
5199
            $classes = isset($enreg['Classes']) ? explode('|', $enreg['Classes']) : [];
5200
            $extraParams = [];
5201
            if (!is_null($showDescription)) {
5202
                $extraParams['show_description'] = intval($showDescription);
5203
            }
5204
5205
            $coachBefore = '';
5206
            $coachAfter = '';
5207
            if (!empty($daysCoachAccessBeforeBeginning) && !empty($daysCoachAccessAfterBeginning)) {
5208
                $date = new \DateTime($dateStart);
5209
                $interval = new DateInterval('P'.$daysCoachAccessBeforeBeginning.'D');
5210
                $date->sub($interval);
5211
                $coachBefore = $date->format('Y-m-d h:i');
5212
                $coachAccessStartDate = $coachBefore;
5213
                $coachBefore = api_get_utc_datetime($coachBefore);
5214
5215
                $date = new \DateTime($dateEnd);
5216
                $interval = new DateInterval('P'.$daysCoachAccessAfterBeginning.'D');
5217
                $date->add($interval);
5218
                $coachAfter = $date->format('Y-m-d h:i');
5219
                $coachAccessEndDate = $coachAfter;
5220
                $coachAfter = api_get_utc_datetime($coachAfter);
5221
            }
5222
5223
            $dateStart = api_get_utc_datetime($dateStart);
5224
            $dateEnd = api_get_utc_datetime($dateEnd);
5225
            $displayAccessStartDate = api_get_utc_datetime($displayAccessStartDate);
5226
            $displayAccessEndDate = api_get_utc_datetime($displayAccessEndDate);
5227
            $coachAccessStartDate = api_get_utc_datetime($coachAccessStartDate);
5228
            $coachAccessEndDate = api_get_utc_datetime($coachAccessEndDate);
5229
5230
            if (!empty($sessionDescription)) {
5231
                $extraParams['description'] = $sessionDescription;
5232
            }
5233
5234
            if (!empty($session_category_id)) {
5235
                $extraParams['session_category_id'] = $session_category_id;
5236
            }
5237
5238
            // Searching a general coach.
5239
            if (!empty($enreg['Coach'])) {
5240
                $coach_id = UserManager::get_user_id_from_username($enreg['Coach']);
5241
                if (false === $coach_id) {
5242
                    // If the coach-user does not exist - I'm the coach.
5243
                    $coach_id = $defaultUserId;
5244
                }
5245
            } else {
5246
                $coach_id = $defaultUserId;
5247
            }
5248
5249
            $coach = api_get_user_entity($coach_id);
5250
5251
            $usersRaw = (string)($enreg['Users'] ?? '');
5252
            $users = $usersRaw === ''
5253
                ? []
5254
                : array_values(array_filter(array_map('trim', explode('|', $usersRaw)), 'strlen'));
5255
            $courses = isset($enreg['Courses']) && $enreg['Courses'] !== '' ? explode('|', $enreg['Courses']) : [];
5256
5257
            $deleteOnlyCourseCoaches = false;
5258
            if (1 == count($courses)) {
5259
                if ($logger) {
5260
                    $logger->debug('Only one course delete old coach list');
5261
                }
5262
                $deleteOnlyCourseCoaches = true;
5263
            }
5264
5265
            if (!$updateSession) {
5266
                // Create a session.
5267
                $unique_name = false;
5268
                $i = 0;
5269
                // Change session name, verify that session doesn't exist.
5270
                $suffix = null;
5271
                while (!$unique_name) {
5272
                    if ($i > 1) {
5273
                        $suffix = ' - '.$i;
5274
                    }
5275
                    $sql = 'SELECT id FROM '.$tbl_session.'
5276
                                WHERE title = "'.Database::escape_string($session_name).$suffix.'"';
5277
                    $rs = Database::query($sql);
5278
                    if (Database::result($rs, 0, 0)) {
5279
                        $i++;
5280
                    } else {
5281
                        $unique_name = true;
5282
                        $session_name .= $suffix;
5283
                    }
5284
                }
5285
5286
                $sessionParams = [
5287
                    'title' => $session_name,
5288
                    'access_start_date' => $dateStart,
5289
                    'access_end_date' => $dateEnd,
5290
                    'display_start_date' => $displayAccessStartDate,
5291
                    'display_end_date' => $displayAccessEndDate,
5292
                    'coach_access_start_date' => $coachAccessStartDate,
5293
                    'coach_access_end_date' => $coachAccessEndDate,
5294
                    'visibility' => $visibilityAfterExpirationPerSession,
5295
                    'nbr_users' => 0,
5296
                    'nbr_courses' => 0,
5297
                    'nbr_classes' => 0,
5298
                    'status' => 0,
5299
                    'duration' => 0,
5300
                ];
5301
5302
                if (!empty($extraParams)) {
5303
                    $sessionParams = array_merge($sessionParams, $extraParams);
5304
                }
5305
                // Creating the session.
5306
                $session_id = Database::insert($tbl_session, $sessionParams);
5307
                $session = api_get_session_entity($session_id);
5308
                if ($session_id) {
5309
5310
                    $em = Database::getManager();
5311
                    $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5312
                    $defaultUser = $em->contains($defaultUser) ? $defaultUser : $em->merge($defaultUser);
5313
5314
                    $session->addUserInSession(Session::GENERAL_COACH, $coach);
5315
                    $session->addUserInSession(Session::GENERAL_COACH, $defaultUser);
5316
                    $em->flush();
5317
5318
                    foreach ($enreg as $key => $value) {
5319
                        if ('extra_' === substr($key, 0, 6)) { //an extra field
5320
                            self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5321
                        }
5322
                    }
5323
                    if ($debug) {
5324
                        $logger->debug("Session created: #$session_id - $session_name");
5325
                    }
5326
                } else {
5327
                    if ($debug) {
5328
                        $message = "Sessions - Session NOT created: $session_name";
5329
                        $logger->debug($message);
5330
                        $report[] = $message;
5331
                    }
5332
                }
5333
                $session_counter++;
5334
            } else {
5335
                $sessionId = null;
5336
                if (isset($extraFields) && !empty($extraFields) && !empty($enreg['extra_'.$extraFieldId])) {
5337
                    $sessionId = self::getSessionIdFromOriginalId($enreg['extra_'.$extraFieldId], $extraFieldId);
5338
                    if (empty($sessionId)) {
5339
                        $my_session_result = false;
5340
                    } else {
5341
                        $my_session_result = true;
5342
                    }
5343
                } else {
5344
                    $my_session_result = self::get_session_by_name($enreg['SessionName']);
5345
                }
5346
5347
                if (false === $my_session_result) {
5348
                    // One more check
5349
                    $sessionExistsWithName = self::get_session_by_name($session_name);
5350
                    if ($sessionExistsWithName) {
5351
                        if ($debug) {
5352
                            $message = "Skip Session - Trying to update a session, but name already exists: $session_name";
5353
                            $logger->debug($message);
5354
                            $report[] = $message;
5355
                        }
5356
                        continue;
5357
                    }
5358
5359
                    $sessionParams = [
5360
                        'title' => $session_name,
5361
                        'access_start_date' => $dateStart,
5362
                        'access_end_date' => $dateEnd,
5363
                        'display_start_date' => $displayAccessStartDate,
5364
                        'display_end_date' => $displayAccessEndDate,
5365
                        'coach_access_start_date' => $coachAccessStartDate,
5366
                        'coach_access_end_date' => $coachAccessEndDate,
5367
                        'visibility' => $visibilityAfterExpirationPerSession,
5368
                        'nbr_users' => 0,
5369
                        'nbr_courses' => 0,
5370
                        'nbr_classes' => 0,
5371
                        'status' => 0,
5372
                        'duration' => 0,
5373
                    ];
5374
5375
                    if (!empty($extraParams)) {
5376
                        $sessionParams = array_merge($sessionParams, $extraParams);
5377
                    }
5378
                    $session_id = Database::insert($tbl_session, $sessionParams);
5379
5380
                    if ($session_id) {
5381
                        $session = api_get_session_entity($session_id);
5382
5383
                        $session
5384
                            ->addUserInSession(Session::GENERAL_COACH, $coach)
5385
                            ->addUserInSession(Session::GENERAL_COACH, $defaultUser)
5386
                        ;
5387
                        Database::getManager()->flush();
5388
5389
                        foreach ($enreg as $key => $value) {
5390
                            if ('extra_' == substr($key, 0, 6)) { //an extra field
5391
                                self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5392
                            }
5393
                        }
5394
                        if ($debug) {
5395
                            $logger->debug("Sessions - #$session_id created: $session_name");
5396
                        }
5397
5398
                        // Delete session-user relation only for students
5399
                        $sql = "DELETE FROM $tbl_session_user
5400
                                    WHERE session_id = '$session_id' AND relation_type = ".Session::STUDENT;
5401
                        Database::query($sql);
5402
5403
                        $sql = "DELETE FROM $tbl_session_course WHERE session_id = '$session_id'";
5404
                        Database::query($sql);
5405
5406
                        // Delete session-course-user relationships students and coaches.
5407
                        if ($updateCourseCoaches) {
5408
                            $sql = "DELETE FROM $tbl_session_course_user
5409
                                        WHERE session_id = '$session_id' AND status in (".Session::STUDENT.", ".Session::COURSE_COACH.")";
5410
                            Database::query($sql);
5411
                        } else {
5412
                            // Delete session-course-user relation ships *only* for students.
5413
                            $sql = "DELETE FROM $tbl_session_course_user
5414
                                        WHERE session_id = '$session_id' AND status =".Session::STUDENT;
5415
                            Database::query($sql);
5416
                        }
5417
                        if ($deleteOnlyCourseCoaches) {
5418
                            $sql = "DELETE FROM $tbl_session_course_user
5419
                                        WHERE session_id = '$session_id' AND status = ".Session::COURSE_COACH;
5420
                            Database::query($sql);
5421
                        }
5422
                    }
5423
                } else {
5424
                    // Updating the session.
5425
                    $params = [
5426
                        'access_start_date' => $dateStart,
5427
                        'access_end_date' => $dateEnd,
5428
                        'display_start_date' => $displayAccessStartDate,
5429
                        'display_end_date' => $displayAccessEndDate,
5430
                        'coach_access_start_date' => $coachAccessStartDate,
5431
                        'coach_access_end_date' => $coachAccessEndDate,
5432
                        'visibility' => $visibilityAfterExpirationPerSession,
5433
                        'session_category_id' => $session_category_id,
5434
                    ];
5435
5436
                    if (!empty($sessionDescription)) {
5437
                        $params['description'] = $sessionDescription;
5438
                    }
5439
5440
                    if (!empty($fieldsToAvoidUpdate)) {
5441
                        foreach ($fieldsToAvoidUpdate as $field) {
5442
                            unset($params[$field]);
5443
                        }
5444
                    }
5445
5446
                    if (isset($sessionId) && !empty($sessionId)) {
5447
                        $session_id = $sessionId;
5448
                        if (!empty($enreg['SessionName'])) {
5449
                            $sessionExistsWithName = self::get_session_by_name($session_name);
5450
                            if (false === $sessionExistsWithName) {
5451
                                $sessionName = Database::escape_string($enreg['SessionName']);
5452
                                $sql = "UPDATE $tbl_session SET title = '$sessionName' WHERE id = $session_id";
5453
                                Database::query($sql);
5454
                                $logger->debug(
5455
                                    "Session #$session_id name IS updated with: '$session_name' External id: ".$enreg['extra_'.$extraFieldId]
5456
                                );
5457
                            } else {
5458
                                $sessionExistsBesidesMe = self::sessionNameExistBesidesMySession(
5459
                                    $session_id,
5460
                                    $session_name
5461
                                );
5462
                                if (true === $sessionExistsBesidesMe) {
5463
                                    if ($debug) {
5464
                                        $message = "Skip Session. Error when update session Session #$session_id Name: '$session_name'. Other session has the same name. External id: ".$enreg['extra_'.$extraFieldId];
5465
                                        $logger->debug($message);
5466
                                        $report[] = $message;
5467
                                    }
5468
                                    continue;
5469
                                } else {
5470
                                    if ($debug) {
5471
                                        $logger->debug(
5472
                                            "Session #$session_id name is not updated because it didn't change (but update of other session values will continue) Name: '$session_name' External id: ".$enreg['extra_'.$extraFieldId]
5473
                                        );
5474
                                    }
5475
                                }
5476
                            }
5477
                        }
5478
                    } else {
5479
                        $my_session_result = self::get_session_by_name($session_name);
5480
                        $session_id = $my_session_result['id'];
5481
                    }
5482
5483
                    if ($debug) {
5484
                        $logger->debug("Session #$session_id to be updated: '$session_name'");
5485
                    }
5486
5487
                    if ($session_id) {
5488
                        $sessionInfo = api_get_session_info($session_id);
5489
                        $params['show_description'] = $sessionInfo['show_description'] ?? intval($showDescription);
5490
5491
                        if (!empty($daysCoachAccessBeforeBeginning) && !empty($daysCoachAccessAfterBeginning)) {
5492
                            if (empty($sessionInfo['nb_days_access_before_beginning']) ||
5493
                                (!empty($sessionInfo['nb_days_access_before_beginning']) &&
5494
                                    $sessionInfo['nb_days_access_before_beginning'] < $daysCoachAccessBeforeBeginning)
5495
                            ) {
5496
                                $params['coach_access_start_date'] = $coachBefore;
5497
                            }
5498
5499
                            if (empty($sessionInfo['nb_days_access_after_end']) ||
5500
                                (!empty($sessionInfo['nb_days_access_after_end']) &&
5501
                                    $sessionInfo['nb_days_access_after_end'] < $daysCoachAccessAfterBeginning)
5502
                            ) {
5503
                                $params['coach_access_end_date'] = $coachAfter;
5504
                            }
5505
                        }
5506
5507
                        Database::update($tbl_session, $params, ['id = ?' => $session_id]);
5508
                        Database::delete(
5509
                            $tbl_session_user,
5510
                            ['session_id = ? AND relation_type = ?' => [$session_id, Session::GENERAL_COACH]]
5511
                        );
5512
5513
                        $em = Database::getManager();
5514
                        $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5515
                        api_get_session_entity($session_id)->addUserInSession(Session::GENERAL_COACH, $coach);
5516
                        $em->flush();
5517
5518
                        foreach ($enreg as $key => $value) {
5519
                            if ('extra_' == substr($key, 0, 6)) { //an extra field
5520
                                self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5521
                            }
5522
                        }
5523
5524
                        if ($debug) {
5525
                            $logger->debug("Session updated #$session_id");
5526
                        }
5527
5528
                        // Delete session-user relation only for students
5529
                        $sql = "DELETE FROM $tbl_session_user
5530
                                    WHERE session_id = '$session_id' AND relation_type = ".Session::STUDENT;
5531
                        Database::query($sql);
5532
5533
                        $sql = "DELETE FROM $tbl_session_course WHERE session_id = '$session_id'";
5534
                        Database::query($sql);
5535
5536
                        // Delete session-course-user relationships students and coaches.
5537
                        if ($updateCourseCoaches) {
5538
                            $sql = "DELETE FROM $tbl_session_course_user
5539
                                        WHERE session_id = '$session_id' AND status in (".Session::STUDENT.", ".Session::COURSE_COACH.")";
5540
                            Database::query($sql);
5541
                        } else {
5542
                            // Delete session-course-user relation ships *only* for students.
5543
                            $sql = "DELETE FROM $tbl_session_course_user
5544
                                        WHERE session_id = '$session_id' AND status = ".Session::STUDENT;
5545
                            Database::query($sql);
5546
                        }
5547
5548
                        if ($deleteOnlyCourseCoaches) {
5549
                            $sql = "DELETE FROM $tbl_session_course_user
5550
                                        WHERE session_id = '$session_id' AND status = ".Session::COURSE_COACH;
5551
                            Database::query($sql);
5552
                        }
5553
                    } else {
5554
                        if ($debug) {
5555
                            $logger->debug(
5556
                                "Sessions - Session not found"
5557
                            );
5558
                        }
5559
                    }
5560
                }
5561
                $session_counter++;
5562
            }
5563
5564
            $sessionList[] = $session_id;
5565
5566
            // Adding the relationship "Session - User" for students
5567
            $userList = [];
5568
            if (is_array($users)) {
5569
                $extraFieldValueCareer = new ExtraFieldValue('career');
5570
                $careerList = isset($enreg['extra_careerid']) && !empty($enreg['extra_careerid']) ? $enreg['extra_careerid'] : [];
5571
                $careerList = str_replace(['[', ']'], '', $careerList);
5572
                if (!empty($careerList)) {
5573
                    $careerList = explode(',', $careerList);
5574
                    $finalCareerIdList = [];
5575
                    foreach ($careerList as $careerId) {
5576
                        $realCareerIdList = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
5577
                            'external_career_id',
5578
                            $careerId
5579
                        );
5580
                        if (isset($realCareerIdList['item_id'])) {
5581
                            $finalCareerIdList[] = $realCareerIdList['item_id'];
5582
                        }
5583
                    }
5584
                }
5585
5586
                foreach ($users as $user) {
5587
                    $user_id = UserManager::get_user_id_from_username($user);
5588
                    if (false !== $user_id) {
5589
                        if (!empty($finalCareerIdList)) {
5590
                            foreach ($finalCareerIdList as $careerId) {
5591
                                UserManager::addUserCareer($user_id, $careerId);
5592
                            }
5593
                        }
5594
5595
                        $userEntity = api_get_user_entity($user_id);
5596
                        $sessionEntity = api_get_session_entity($session_id);
5597
                        $sessionEntity->addUserInSession(Session::STUDENT, $userEntity);
5598
5599
                        if ($debug) {
5600
                            $logger->debug("Adding User #$user_id ($user) to session #$session_id");
5601
                        }
5602
                        $user_counter++;
5603
                    }
5604
                }
5605
            }
5606
5607
            if ($deleteUsersNotInList) {
5608
                // Getting user in DB in order to compare to the new list.
5609
                $usersListInDatabase = self::get_users_by_session($session_id, 0);
5610
                if (!empty($usersListInDatabase)) {
5611
                    if (empty($userList)) {
5612
                        foreach ($usersListInDatabase as $userInfo) {
5613
                            self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5614
                        }
5615
                    } else {
5616
                        foreach ($usersListInDatabase as $userInfo) {
5617
                            if (!in_array($userInfo['user_id'], $userList)) {
5618
                                self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5619
                            }
5620
                        }
5621
                    }
5622
                }
5623
            }
5624
5625
            // See BT#6449
5626
            $onlyAddFirstCoachOrTeacher = false;
5627
            if ($sessionWithCoursesModifier) {
5628
                if (count($courses) >= 2) {
5629
                    // Only first teacher in course session;
5630
                    $onlyAddFirstCoachOrTeacher = true;
5631
                    // Remove all teachers from course.
5632
                    $removeAllTeachersFromCourse = false;
5633
                }
5634
            }
5635
5636
            foreach ($courses as $course) {
5637
                $courseArray = bracketsToArray($course);
5638
                $course_code = $courseArray[0];
5639
5640
                if (CourseManager::course_exists($course_code)) {
5641
                    $courseInfo = api_get_course_info($course_code);
5642
                    $courseId = $courseInfo['real_id'];
5643
5644
                    // Adding the course to a session.
5645
                    $sql = "INSERT IGNORE INTO $tbl_session_course
5646
                                SET c_id = '$courseId', session_id='$session_id'";
5647
                    Database::query($sql);
5648
5649
                    self::installCourse($session_id, $courseInfo['real_id']);
5650
5651
                    if ($debug) {
5652
                        $logger->debug("Adding course '$course_code' to session #$session_id");
5653
                    }
5654
5655
                    $course_counter++;
5656
                    $course_coaches = array_values(
5657
                        array_filter(
5658
                            array_map('trim', explode(',', (string)($courseArray[1] ?? ''))),
5659
                            'strlen'
5660
                        )
5661
                    );
5662
                    $course_users = array_values(
5663
                        array_filter(
5664
                            array_map('trim', explode(',', (string)($courseArray[2] ?? ''))),
5665
                            'strlen'
5666
                        )
5667
                    );
5668
5669
                    // Checking if the flag is set TeachersWillBeAddedAsCoachInAllCourseSessions (course_edit.php)
5670
                    $addTeachersToSession = true;
5671
5672
                    if (array_key_exists('add_teachers_to_sessions_courses', $courseInfo)) {
5673
                        $addTeachersToSession = $courseInfo['add_teachers_to_sessions_courses'];
5674
                    }
5675
5676
                    // If any user provided for a course, use the users array.
5677
                    if (empty($course_users)) {
5678
                        if (!empty($userList)) {
5679
                            self::subscribe_users_to_session_course(
5680
                                $userList,
5681
                                $session_id,
5682
                                $course_code
5683
                            );
5684
                            if ($debug) {
5685
                                $msg = "Adding student list ".implode(', #', $userList)." to course: '$course_code' and session #$session_id";
5686
                                $logger->debug($msg);
5687
                            }
5688
                        }
5689
                    }
5690
5691
                    // Adding coaches to session course user.
5692
                    if (!empty($course_coaches)) {
5693
                        $savedCoaches = [];
5694
                        // only edit if add_teachers_to_sessions_courses is set.
5695
                        if ($addTeachersToSession) {
5696
                            if ($addOriginalCourseTeachersAsCourseSessionCoaches) {
5697
                                // Adding course teachers as course session teachers.
5698
                                $alreadyAddedTeachers = CourseManager::get_teacher_list_from_course_code(
5699
                                    $course_code
5700
                                );
5701
5702
                                if (!empty($alreadyAddedTeachers)) {
5703
                                    $teachersToAdd = [];
5704
                                    foreach ($alreadyAddedTeachers as $user) {
5705
                                        $teachersToAdd[] = $user['username'];
5706
                                    }
5707
                                    $course_coaches = array_merge(
5708
                                        $course_coaches,
5709
                                        $teachersToAdd
5710
                                    );
5711
                                }
5712
                            }
5713
5714
                            foreach ($course_coaches as $course_coach) {
5715
                                $coach_id = UserManager::get_user_id_from_username($course_coach);
5716
                                if (false !== $coach_id) {
5717
                                    // Just insert new coaches
5718
                                    self::updateCoaches(
5719
                                        $session_id,
5720
                                        $courseId,
5721
                                        [$coach_id],
5722
                                        false
5723
                                    );
5724
5725
                                    if ($debug) {
5726
                                        $logger->debug("Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
5727
                                    }
5728
                                    $savedCoaches[] = $coach_id;
5729
                                } else {
5730
                                    $badCoach = trim((string)$course_coach);
5731
                                    $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
5732
                                }
5733
                            }
5734
                        }
5735
5736
                        // Custom courses/session coaches
5737
                        $teacherToAdd = null;
5738
                        // Only one coach is added.
5739
                        if (true == $onlyAddFirstCoachOrTeacher) {
5740
                            if ($debug) {
5741
                                $logger->debug("onlyAddFirstCoachOrTeacher : true");
5742
                            }
5743
5744
                            foreach ($course_coaches as $course_coach) {
5745
                                $coach_id = UserManager::get_user_id_from_username($course_coach);
5746
                                if (false !== $coach_id) {
5747
                                    $teacherToAdd = $coach_id;
5748
                                    break;
5749
                                }
5750
                            }
5751
5752
                            // Un subscribe everyone that's not in the list.
5753
                            $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5754
                            if (!empty($teacherList)) {
5755
                                foreach ($teacherList as $teacher) {
5756
                                    if ($teacherToAdd != $teacher['user_id']) {
5757
                                        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5758
                                                    WHERE
5759
                                                        user_id = ".$teacher['user_id']." AND
5760
                                                        c_id = '".$courseId."'
5761
                                                    ";
5762
5763
                                        $result = Database::query($sql);
5764
                                        $rows = Database::num_rows($result);
5765
                                        if ($rows > 0) {
5766
                                            $userCourseData = Database::fetch_assoc($result);
5767
                                            if (!empty($userCourseData)) {
5768
                                                $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5769
                                            }
5770
                                        }
5771
5772
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5773
                                                    WHERE
5774
                                                        user_id = ".$teacher['user_id']." AND
5775
                                                        c_id = '".$courseInfo['real_id']."'
5776
                                                    ";
5777
5778
                                        $result = Database::query($sql);
5779
                                        while ($groupData = Database::fetch_assoc($result)) {
5780
                                            $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5781
                                        }
5782
5783
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5784
                                                    WHERE
5785
                                                        user_id = ".$teacher['user_id']." AND
5786
                                                        c_id = '".$courseInfo['real_id']."'
5787
                                                    ";
5788
5789
                                        $result = Database::query($sql);
5790
                                        while ($groupData = Database::fetch_assoc($result)) {
5791
                                            $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5792
                                        }
5793
5794
                                        CourseManager::unsubscribe_user(
5795
                                            $teacher['user_id'],
5796
                                            $course_code
5797
                                        );
5798
5799
                                        if ($debug) {
5800
                                            $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5801
                                        }
5802
                                    }
5803
                                }
5804
                            }
5805
5806
                            if (!empty($teacherToAdd)) {
5807
                                self::updateCoaches(
5808
                                    $session_id,
5809
                                    $courseId,
5810
                                    [$teacherToAdd],
5811
                                    true
5812
                                );
5813
5814
                                if ($debug) {
5815
                                    $logger->debug("Add coach #$teacherToAdd to course $courseId and session $session_id");
5816
                                }
5817
5818
                                $userCourseCategory = '';
5819
                                if (isset($teacherBackupList[$teacherToAdd]) &&
5820
                                    isset($teacherBackupList[$teacherToAdd][$course_code])
5821
                                ) {
5822
                                    $courseUserData = $teacherBackupList[$teacherToAdd][$course_code];
5823
                                    $userCourseCategory = $courseUserData['user_course_cat'];
5824
                                }
5825
5826
                                CourseManager::subscribeUser(
5827
                                    $teacherToAdd,
5828
                                    $courseId,
5829
                                    COURSEMANAGER,
5830
                                    0,
5831
                                    $userCourseCategory
5832
                                );
5833
5834
                                if ($debug) {
5835
                                    $logger->debug("Subscribe user #$teacherToAdd as teacher in course $course_code with user userCourseCategory $userCourseCategory");
5836
                                }
5837
5838
                                if (isset($groupBackup['user'][$teacherToAdd]) &&
5839
                                    isset($groupBackup['user'][$teacherToAdd][$course_code]) &&
5840
                                    !empty($groupBackup['user'][$teacherToAdd][$course_code])
5841
                                ) {
5842
                                    foreach ($groupBackup['user'][$teacherToAdd][$course_code] as $data) {
5843
                                        GroupManager::subscribeUsers(
5844
                                            $teacherToAdd,
5845
                                            api_get_group_entity($data['group_id']),
5846
                                            $data['c_id']
5847
                                        );
5848
                                    }
5849
                                }
5850
5851
                                if (isset($groupBackup['tutor'][$teacherToAdd]) &&
5852
                                    isset($groupBackup['tutor'][$teacherToAdd][$course_code]) &&
5853
                                    !empty($groupBackup['tutor'][$teacherToAdd][$course_code])
5854
                                ) {
5855
                                    foreach ($groupBackup['tutor'][$teacherToAdd][$course_code] as $data) {
5856
                                        GroupManager::subscribeTutors(
5857
                                            $teacherToAdd,
5858
                                            api_get_group_entity($data['group_id']),
5859
                                            $data['c_id']
5860
                                        );
5861
                                    }
5862
                                }
5863
                            }
5864
                        }
5865
5866
                        // See BT#6449#note-195
5867
                        // All coaches are added.
5868
                        if ($removeAllTeachersFromCourse) {
5869
                            if ($debug) {
5870
                                $logger->debug("removeAllTeachersFromCourse true");
5871
                            }
5872
                            $teacherToAdd = null;
5873
                            foreach ($course_coaches as $course_coach) {
5874
                                $coach_id = UserManager::get_user_id_from_username(
5875
                                    $course_coach
5876
                                );
5877
                                if (false !== $coach_id) {
5878
                                    $teacherToAdd[] = $coach_id;
5879
                                }
5880
                            }
5881
5882
                            if (!empty($teacherToAdd)) {
5883
                                // Deleting all course teachers and adding the only coach as teacher.
5884
                                $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5885
5886
                                if (!empty($teacherList)) {
5887
                                    foreach ($teacherList as $teacher) {
5888
                                        if (!in_array($teacher['user_id'], $teacherToAdd)) {
5889
                                            $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5890
                                                        WHERE
5891
                                                            user_id = ".$teacher['user_id']." AND
5892
                                                            c_id = '".$courseId."'
5893
                                                        ";
5894
5895
                                            $result = Database::query($sql);
5896
                                            $rows = Database::num_rows($result);
5897
                                            if ($rows > 0) {
5898
                                                $userCourseData = Database::fetch_assoc($result);
5899
                                                if (!empty($userCourseData)) {
5900
                                                    $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5901
                                                }
5902
                                            }
5903
5904
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5905
                                                        WHERE
5906
                                                            user_id = ".$teacher['user_id']." AND
5907
                                                            c_id = '".$courseInfo['real_id']."'
5908
                                                        ";
5909
5910
                                            $result = Database::query($sql);
5911
                                            while ($groupData = Database::fetch_assoc($result)) {
5912
                                                $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5913
                                            }
5914
5915
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5916
                                                        WHERE
5917
                                                            user_id = ".$teacher['user_id']." AND
5918
                                                            c_id = '".$courseInfo['real_id']."'
5919
                                                        ";
5920
5921
                                            $result = Database::query($sql);
5922
                                            while ($groupData = Database::fetch_assoc($result)) {
5923
                                                $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5924
                                            }
5925
5926
                                            CourseManager::unsubscribe_user(
5927
                                                $teacher['user_id'],
5928
                                                $course_code
5929
                                            );
5930
5931
                                            if ($debug) {
5932
                                                $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5933
                                            }
5934
                                        }
5935
                                    }
5936
                                }
5937
5938
                                foreach ($teacherToAdd as $teacherId) {
5939
                                    $userCourseCategory = '';
5940
                                    if (isset($teacherBackupList[$teacherId]) &&
5941
                                        isset($teacherBackupList[$teacherId][$course_code])
5942
                                    ) {
5943
                                        $courseUserData = $teacherBackupList[$teacherId][$course_code];
5944
                                        $userCourseCategory = $courseUserData['user_course_cat'];
5945
                                    }
5946
5947
                                    CourseManager::subscribeUser(
5948
                                        $teacherId,
5949
                                        $courseInfo['real_id'],
5950
                                        COURSEMANAGER,
5951
                                        0,
5952
                                        $userCourseCategory
5953
                                    );
5954
5955
                                    if ($debug) {
5956
                                        $logger->debug("Add user as teacher #".$teacherId." in base course: $course_code with userCourseCategory: $userCourseCategory");
5957
                                    }
5958
5959
                                    if (isset($groupBackup['user'][$teacherId]) &&
5960
                                        isset($groupBackup['user'][$teacherId][$course_code]) &&
5961
                                        !empty($groupBackup['user'][$teacherId][$course_code])
5962
                                    ) {
5963
                                        foreach ($groupBackup['user'][$teacherId][$course_code] as $data) {
5964
                                            GroupManager::subscribeUsers(
5965
                                                $teacherId,
5966
                                                api_get_group_entity($data['group_id']),
5967
                                                $data['c_id']
5968
                                            );
5969
                                        }
5970
                                    }
5971
5972
                                    if (isset($groupBackup['tutor'][$teacherId]) &&
5973
                                        isset($groupBackup['tutor'][$teacherId][$course_code]) &&
5974
                                        !empty($groupBackup['tutor'][$teacherId][$course_code])
5975
                                    ) {
5976
                                        foreach ($groupBackup['tutor'][$teacherId][$course_code] as $data) {
5977
                                            GroupManager::subscribeTutors(
5978
                                                $teacherId,
5979
                                                api_get_group_entity($data['group_id']),
5980
                                                $data['c_id']
5981
                                            );
5982
                                        }
5983
                                    }
5984
                                }
5985
                            }
5986
                        }
5987
5988
                        // Continue default behaviour.
5989
                        if (false == $onlyAddFirstCoachOrTeacher) {
5990
                            // Checking one more time see BT#6449#note-149
5991
                            $coaches = self::getCoachesByCourseSession($session_id, $courseId);
5992
                            // Update coaches if only there's 1 course see BT#6449#note-189
5993
                            if (empty($coaches) || 1 == count($courses)) {
5994
                                foreach ($course_coaches as $course_coach) {
5995
                                    $course_coach = trim($course_coach);
5996
                                    $coach_id = UserManager::get_user_id_from_username($course_coach);
5997
                                    if (false !== $coach_id) {
5998
                                        // Just insert new coaches
5999
                                        self::updateCoaches(
6000
                                            $session_id,
6001
                                            $courseId,
6002
                                            [$coach_id],
6003
                                            false
6004
                                        );
6005
6006
                                        if ($debug) {
6007
                                            $logger->debug("Sessions - Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
6008
                                        }
6009
                                        $savedCoaches[] = $coach_id;
6010
                                    } else {
6011
                                        $badCoach = trim((string)$course_coach);
6012
                                        $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
6013
                                    }
6014
                                }
6015
                            }
6016
                        }
6017
                    }
6018
6019
                    // Adding Students, updating relationship "Session - Course - User".
6020
                    $course_users = array_filter($course_users);
6021
                    if (!empty($course_users)) {
6022
                        foreach ($course_users as $user) {
6023
                            $user_id = UserManager::get_user_id_from_username($user);
6024
6025
                            if (false !== $user_id) {
6026
                                self::subscribe_users_to_session_course(
6027
                                    [$user_id],
6028
                                    $session_id,
6029
                                    $course_code
6030
                                );
6031
                                if ($debug) {
6032
                                    $logger->debug("Adding student: user #$user_id ($user) to course: '$course_code' and session #$session_id");
6033
                                }
6034
                            } else {
6035
                                $badUser = trim((string)$user);
6036
                                $error_message .= get_lang("This user doesn't exist").': "'.$badUser.'"'.$eol;
6037
                            }
6038
                        }
6039
                    }
6040
                    $inserted_in_course[$course_code] = $courseInfo['title'];
6041
                }
6042
            }
6043
            $access_url_id = api_get_current_access_url_id();
6044
            UrlManager::add_session_to_url($session_id, $access_url_id);
6045
            $sql = "UPDATE $tbl_session SET nbr_users = '$user_counter', nbr_courses = '$course_counter'
6046
                        WHERE id = '$session_id'";
6047
            Database::query($sql);
6048
6049
            self::addClassesByName($session_id, $classes, false);
6050
6051
            if ($debug) {
6052
                $logger->debug("End process session #$session_id -------------------- ");
6053
            }
6054
        }
6055
6056
        if (!empty($report)) {
6057
            if ($debug) {
6058
                $logger->debug("--Summary--");
6059
                foreach ($report as $line) {
6060
                    $logger->debug($line);
6061
                }
6062
            }
6063
        }
6064
6065
        return [
6066
            'error_message' => $error_message,
6067
            'session_counter' => $session_counter,
6068
            'session_list' => $sessionList,
6069
        ];
6070
    }
6071
6072
    /**
6073
     * Imports sessions from an XML file and returns the result of the operation.
6074
     */
6075
    public static function importXML(
6076
        string $file,
6077
        bool $updateSession = false,
6078
        int $defaultUserId = null,
6079
        bool $sendMail = false,
6080
        int $sessionVisibility = SESSION_VISIBLE,
6081
        array &$insertedInCourse = [],
6082
        ?string &$errorMessage = ''
6083
    ): array {
6084
        $defaultUserId = $defaultUserId ?? api_get_user_id();
6085
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
6086
        $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
6087
        $tblSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
6088
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6089
6090
        $sessionCounter = 0;
6091
        $sessionList = [];
6092
6093
        $content = file_get_contents($file);
6094
        $content = api_utf8_encode_xml($content);
6095
        $root = @simplexml_load_string($content);
6096
6097
        if (!is_object($root)) {
6098
            $errorMessage .= get_lang('XML document is not valid');
6099
            return [];
6100
        }
6101
6102
        // === USERS ===
6103
        if (isset($root->Users->User)) {
6104
            foreach ($root->Users->User as $nodeUser) {
6105
                $username = trim(api_utf8_decode($nodeUser->Username));
6106
                $password = api_utf8_decode($nodeUser->Password);
6107
                $firstname = api_utf8_decode($nodeUser->Firstname);
6108
                $lastname = api_utf8_decode($nodeUser->Lastname);
6109
                $email = trim(api_utf8_decode($nodeUser->Email));
6110
                $officialCode = trim(api_utf8_decode($nodeUser->OfficialCode));
6111
                $phone = trim(api_utf8_decode($nodeUser->Phone));
6112
                $statusStr = strtolower(trim(api_utf8_decode($nodeUser->Status)));
6113
                $status = $statusStr === 'teacher' ? 1 : 5;
6114
6115
                if (Container::getUserRepository()->isUsernameAvailable($username)) {
6116
                    if (empty($password)) {
6117
                        $password = api_generate_password();
6118
                    }
6119
                    UserManager::create_user(
6120
                        $firstname,
6121
                        $lastname,
6122
                        $status,
6123
                        $email,
6124
                        $username,
6125
                        $password,
6126
                        $officialCode,
6127
                        null,
6128
                        $phone,
6129
                        null,
6130
                        [UserAuthSource::PLATFORM],
6131
                        null,
6132
                        1,
6133
                        0,
6134
                        null,
6135
                        null,
6136
                        $sendMail
6137
                    );
6138
                } else {
6139
                    $userId = UserManager::get_user_id_from_username($username);
6140
                    if ($userId) {
6141
                        UserManager::update_user(
6142
                            $userId,
6143
                            $firstname,
6144
                            $lastname,
6145
                            $username,
6146
                            $password,
6147
                            [],
6148
                            $email,
6149
                            $status,
6150
                            $officialCode,
6151
                            $phone,
6152
                            null,
6153
                            null,
6154
                            1,
6155
                            null,
6156
                            0
6157
                        );
6158
                    }
6159
                }
6160
            }
6161
        }
6162
6163
        // === COURSES ===
6164
        if (isset($root->Courses->Course)) {
6165
            foreach ($root->Courses->Course as $nodeCourse) {
6166
                $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6167
                $courseTitle = api_utf8_decode($nodeCourse->CourseTitle ?: $courseCode);
6168
                $courseLang = api_utf8_decode($nodeCourse->CourseLanguage);
6169
                $teacherUsername = trim(api_utf8_decode($nodeCourse->CourseTeacher));
6170
6171
                $teacherId = UserManager::get_user_id_from_username($teacherUsername) ?: $defaultUserId;
6172
6173
                if (!CourseManager::course_exists($courseCode)) {
6174
                    CourseManager::create_course([
6175
                        'wanted_code' => $courseCode,
6176
                        'title' => $courseTitle,
6177
                        'course_language' => $courseLang,
6178
                        'user_id' => $defaultUserId,
6179
                        'teachers' => $teacherId,
6180
                    ]);
6181
                }
6182
            }
6183
        }
6184
6185
        // === SESSIONS ===
6186
        if (isset($root->Session)) {
6187
            foreach ($root->Session as $nodeSession) {
6188
                $sessionName = trim(api_utf8_decode($nodeSession->SessionName));
6189
                $coachUsername = trim(api_utf8_decode($nodeSession->Coach));
6190
                $coachId = UserManager::get_user_id_from_username($coachUsername) ?: $defaultUserId;
6191
                $dateStart = api_utf8_decode($nodeSession->DateStart);
6192
                $dateEnd = api_utf8_decode($nodeSession->DateEnd);
6193
                $sessionCategoryId = (int) trim(api_utf8_decode($nodeSession->SessionCategory));
6194
                $categoryExists = false;
6195
                if (!empty($sessionCategoryId)) {
6196
                    $result = Database::select(
6197
                        'id',
6198
                        Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
6199
                        ['where' => ['id = ?' => $sessionCategoryId]],
6200
                        'first'
6201
                    );
6202
6203
                    $categoryExists = !empty($result);
6204
                }
6205
                if (!$categoryExists) {
6206
                    $sessionCategoryId = null;
6207
                }
6208
                $visibilityStr = strtolower(api_utf8_decode($nodeSession->VisibilityAfterExpiration));
6209
                $visibility = match ($visibilityStr) {
6210
                    'read_only' => SESSION_VISIBLE_READ_ONLY,
6211
                    'not_accessible' => SESSION_INVISIBLE,
6212
                    default => $sessionVisibility,
6213
                };
6214
6215
                // Normalize dates
6216
                $dateStart = date('Y-m-d H:i:s', strtotime($dateStart));
6217
                $dateEnd = date('Y-m-d H:i:s', strtotime($dateEnd));
6218
6219
                $sessionId = null;
6220
                $mySession = SessionManager::get_session_by_name($sessionName);
6221
6222
                if ($updateSession && $mySession) {
6223
                    $sessionId = $mySession['id'];
6224
                    Database::update($tblSession, [
6225
                        'access_start_date' => $dateStart,
6226
                        'access_end_date' => $dateEnd,
6227
                        'visibility' => $visibility,
6228
                        'session_category_id' => $sessionCategoryId,
6229
                    ], ['id = ?' => $sessionId]);
6230
6231
                    Database::query("DELETE FROM $tblSessionUser WHERE session_id = $sessionId");
6232
                    Database::query("DELETE FROM $tblSessionCourse WHERE session_id = $sessionId");
6233
                    Database::query("DELETE FROM $tblSessionCourseUser WHERE session_id = $sessionId");
6234
                } else {
6235
                    $sessionId = Database::insert($tblSession, [
6236
                        'title' => $sessionName,
6237
                        'access_start_date' => $dateStart,
6238
                        'access_end_date' => $dateEnd,
6239
                        'visibility' => $visibility,
6240
                        'nbr_users' => 0,
6241
                        'nbr_courses' => 0,
6242
                        'nbr_classes' => 0,
6243
                        'status' => 0,
6244
                        'duration' => 0,
6245
                        'session_category_id' => $sessionCategoryId,
6246
                    ]);
6247
                }
6248
6249
                if ($sessionId) {
6250
                    Database::insert($tblSessionUser, [
6251
                        'user_id' => $coachId,
6252
                        'session_id' => $sessionId,
6253
                        'registered_at' => api_get_utc_datetime(),
6254
                        'relation_type' => Session::GENERAL_COACH,
6255
                        'duration' => 0,
6256
                    ], false, ['ignore' => true]);
6257
6258
                    Database::insert($tblSessionUser, [
6259
                        'user_id' => $defaultUserId,
6260
                        'session_id' => $sessionId,
6261
                        'registered_at' => api_get_utc_datetime(),
6262
                        'relation_type' => Session::SESSION_ADMIN,
6263
                        'duration' => 0,
6264
                    ], false, ['ignore' => true]);
6265
                    $sessionCounter++;
6266
                    $sessionList[] = $sessionId;
6267
                }
6268
6269
                // Add Users to session
6270
                foreach ($nodeSession->User as $nodeUser) {
6271
                    $username = UserManager::purify_username(api_utf8_decode($nodeUser));
6272
                    $userId = UserManager::get_user_id_from_username($username);
6273
                    if ($userId) {
6274
                        Database::insert($tblSessionUser, [
6275
                            'user_id' => $userId,
6276
                            'session_id' => $sessionId,
6277
                            'relation_type' => Session::STUDENT,
6278
                            'duration' => 0,
6279
                            'registered_at' => api_get_utc_datetime(),
6280
                        ], false, ['ignore' => true]);
6281
                    }
6282
                }
6283
6284
                // Add Courses to session
6285
                foreach ($nodeSession->Course as $nodeCourse) {
6286
                    $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6287
                    $courseInfo = api_get_course_info($courseCode);
6288
                    if ($courseInfo) {
6289
                        $courseId = $courseInfo['real_id'];
6290
                        Database::insert($tblSessionCourse, [
6291
                            'c_id' => $courseId,
6292
                            'session_id' => $sessionId,
6293
                            'nbr_users' => 0,
6294
                            'position' => 0,
6295
                        ]);
6296
                        $courseCoachUsernames = explode(',', $nodeCourse->Coach);
6297
                        foreach ($courseCoachUsernames as $coachUname) {
6298
                            $coachId = UserManager::get_user_id_from_username(trim($coachUname));
6299
                            if ($coachId) {
6300
                                Database::insert($tblSessionCourseUser, [
6301
                                    'user_id' => $coachId,
6302
                                    'c_id' => $courseId,
6303
                                    'session_id' => $sessionId,
6304
                                    'status' => Session::COURSE_COACH,
6305
                                    'visibility' => 1,
6306
                                    'legal_agreement' => 0,
6307
                                    'progress' => 0,
6308
                                ]);
6309
                            }
6310
                        }
6311
6312
                        // Users in the course
6313
                        $userCounter = 0;
6314
                        foreach ($nodeCourse->User as $userNode) {
6315
                            $username = UserManager::purify_username(api_utf8_decode($userNode));
6316
                            $userId = UserManager::get_user_id_from_username($username);
6317
                            if ($userId) {
6318
                                Database::insert($tblSessionUser, [
6319
                                    'user_id' => $userId,
6320
                                    'session_id' => $sessionId,
6321
                                    'registered_at' => api_get_utc_datetime(),
6322
                                    'duration' => 0,
6323
                                    'relation_type' => Session::STUDENT
6324
                                ], false, ['ignore' => true]);
6325
                                Database::insert($tblSessionCourseUser, [
6326
                                    'user_id' => $userId,
6327
                                    'c_id' => $courseId,
6328
                                    'session_id' => $sessionId,
6329
                                    'status' => Session::STUDENT,
6330
                                    'visibility' => 1,
6331
                                    'legal_agreement' => 0,
6332
                                    'progress' => 0,
6333
                                ]);
6334
                                $userCounter++;
6335
                            }
6336
                        }
6337
6338
                        Database::update(
6339
                            $tblSessionCourse,
6340
                            ['nbr_users' => $userCounter],
6341
                            ['c_id = ? AND session_id = ?' => [$courseId, $sessionId]],
6342
                        );
6343
                    }
6344
                }
6345
6346
                Database::update($tblSession, [
6347
                    'nbr_users' => count($nodeSession->User),
6348
                    'nbr_courses' => count($nodeSession->Course),
6349
                ], ['id = ?' => $sessionId]);
6350
6351
                UrlManager::add_session_to_url($sessionId, api_get_current_access_url_id());
6352
            }
6353
        }
6354
6355
        return [
6356
            'session_counter' => $sessionCounter,
6357
            'session_list' => $sessionList,
6358
        ];
6359
    }
6360
6361
    /**
6362
     * Normalizes the end date format to include time if missing.
6363
     */
6364
    private static function normalizeDateEnd(string $date): string
6365
    {
6366
        $dt = new \DateTime(trim($date));
6367
        if ($dt->format('H:i:s') === '00:00:00') {
6368
            $dt->setTime(23, 59, 59);
6369
        }
6370
        return $dt->format('Y-m-d H:i:s');
6371
    }
6372
6373
    /**
6374
     * @param int $sessionId
6375
     * @param int $courseId
6376
     *
6377
     * @return array
6378
     */
6379
    public static function getCoachesByCourseSession($sessionId, $courseId)
6380
    {
6381
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6382
        $sessionId = (int) $sessionId;
6383
        $courseId = (int) $courseId;
6384
6385
        $sql = "SELECT user_id FROM $table
6386
                WHERE
6387
                    session_id = '$sessionId' AND
6388
                    c_id = '$courseId' AND
6389
                    status = ".Session::COURSE_COACH;
6390
        $result = Database::query($sql);
6391
6392
        $coaches = [];
6393
        if (Database::num_rows($result) > 0) {
6394
            while ($row = Database::fetch_array($result)) {
6395
                $coaches[] = $row['user_id'];
6396
            }
6397
        }
6398
6399
        return $coaches;
6400
    }
6401
6402
    /**
6403
     * @param int    $sessionId
6404
     * @param int    $courseId
6405
     * @param string $separator
6406
     *
6407
     * @return string
6408
     */
6409
    public static function getCoachesByCourseSessionToString(
6410
        $sessionId,
6411
        $courseId,
6412
        $separator = ''
6413
    ) {
6414
        $coaches = self::getCoachesByCourseSession($sessionId, $courseId);
6415
        $list = [];
6416
        if (!empty($coaches)) {
6417
            foreach ($coaches as $coachId) {
6418
                $userInfo = api_get_user_info($coachId);
6419
                if ($userInfo) {
6420
                    $list[] = $userInfo['complete_name'];
6421
                }
6422
            }
6423
        }
6424
6425
        $separator = empty($separator) ? CourseManager::USER_SEPARATOR : $separator;
6426
6427
        return array_to_string($list, $separator);
6428
    }
6429
6430
    /**
6431
     * Get all coaches added in the session - course relationship.
6432
     *
6433
     * @param int $sessionId
6434
     *
6435
     * @return array
6436
     */
6437
    public static function getCoachesBySession($sessionId)
6438
    {
6439
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6440
        $sessionId = intval($sessionId);
6441
6442
        $sql = "SELECT DISTINCT user_id
6443
                FROM $table
6444
                WHERE session_id = '$sessionId' AND status = ".Session::COURSE_COACH;
6445
        $result = Database::query($sql);
6446
6447
        $coaches = [];
6448
        if (Database::num_rows($result) > 0) {
6449
            while ($row = Database::fetch_array($result)) {
6450
                $coaches[] = $row['user_id'];
6451
            }
6452
        }
6453
6454
        return $coaches;
6455
    }
6456
6457
    /**
6458
     * @param int $userId
6459
     *
6460
     * @return array
6461
     */
6462
    public static function getAllCoursesFromAllSessionFromDrh($userId)
6463
    {
6464
        $sessions = self::get_sessions_followed_by_drh($userId);
6465
        $coursesFromSession = [];
6466
        if (!empty($sessions)) {
6467
            foreach ($sessions as $session) {
6468
                $courseList = self::get_course_list_by_session_id($session['id']);
6469
                foreach ($courseList as $course) {
6470
                    $coursesFromSession[] = $course['code'];
6471
                }
6472
            }
6473
        }
6474
6475
        return $coursesFromSession;
6476
    }
6477
6478
    /**
6479
     * getAllCoursesFromAllSessions.
6480
     *
6481
     * @return array
6482
     */
6483
    public static function getAllCoursesFromAllSessions()
6484
    {
6485
        $sessions = self::get_sessions_list();
6486
        $coursesFromSession = [];
6487
        if (!empty($sessions)) {
6488
            foreach ($sessions as $session) {
6489
                $courseList = self::get_course_list_by_session_id($session['id']);
6490
                foreach ($courseList as $course) {
6491
                    $coursesFromSession[$course['code'].':'.$session['id']] = $course['visual_code'].' - '.$course['title'].' ('.$session['title'].')';
6492
                }
6493
            }
6494
        }
6495
6496
        return $coursesFromSession;
6497
    }
6498
6499
    /**
6500
     * Return user id list or count of users depending of the $getCount parameter.
6501
     *
6502
     * @param string $status
6503
     * @param int    $userId
6504
     * @param bool   $getCount
6505
     * @param int    $from
6506
     * @param int    $numberItems
6507
     * @param string $column
6508
     * @param string $direction
6509
     * @param string $keyword
6510
     * @param string $active
6511
     * @param string $lastConnectionDate
6512
     * @param array  $sessionIdList
6513
     * @param array  $studentIdList
6514
     * @param int    $filterByStatus
6515
     *
6516
     * @return array|int
6517
     */
6518
    public static function getAllUsersFromCoursesFromAllSessionFromStatus(
6519
        $status,
6520
        $userId,
6521
        $getCount = false,
6522
        $from = null,
6523
        $numberItems = null,
6524
        $column = '',
6525
        $direction = 'asc',
6526
        $keyword = null,
6527
        $active = null,
6528
        $lastConnectionDate = null,
6529
        $sessionIdList = [],
6530
        $studentIdList = [],
6531
        $filterByStatus = null
6532
    ) {
6533
        $filterByStatus = (int) $filterByStatus;
6534
        $userId = (int) $userId;
6535
6536
        if (empty($column)) {
6537
            $column = 'u.lastname';
6538
            if (api_is_western_name_order()) {
6539
                $column = 'u.firstname';
6540
            }
6541
        }
6542
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
6543
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
6544
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
6545
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6546
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
6547
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6548
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6549
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
6550
6551
        $direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : 'asc';
6552
        $column = Database::escape_string($column);
6553
6554
        $urlId = api_get_current_access_url_id();
6555
6556
        $sessionConditions = '';
6557
        $courseConditions = '';
6558
        $userConditions = ' AND u.active <> '.USER_SOFT_DELETED.' ';
6559
6560
        if (isset($active)) {
6561
            $active = (int) $active;
6562
            $userConditions .= " AND active = $active";
6563
        }
6564
6565
        $courseList = CourseManager::get_courses_followed_by_drh($userId, DRH);
6566
        if (!empty($courseList)) {
6567
            $courseIdList = array_column($courseList, 'id');
6568
            $courseConditions = ' AND c.id IN ("'.implode('","', $courseIdList).'")';
6569
        }
6570
6571
        $userConditionsFromDrh = '';
6572
6573
        // Classic DRH
6574
        if (empty($studentIdList)) {
6575
            $studentListSql = UserManager::get_users_followed_by_drh(
6576
                $userId,
6577
                $filterByStatus,
6578
                true,
6579
                false
6580
            );
6581
            if (!empty($studentListSql)) {
6582
                $studentIdList = array_keys($studentListSql);
6583
                $studentListSql = "'".implode("','", $studentIdList)."'";
6584
            }
6585
        } else {
6586
            $studentIdList = array_map('intval', $studentIdList);
6587
            $studentListSql = "'".implode("','", $studentIdList)."'";
6588
        }
6589
        if (!empty($studentListSql)) {
6590
            $userConditionsFromDrh = " AND u.id IN ($studentListSql) ";
6591
        }
6592
6593
        switch ($status) {
6594
            case 'admin':
6595
            case 'drh':
6596
                break;
6597
            case 'drh_all':
6598
                // Show all by DRH
6599
                if (empty($sessionIdList)) {
6600
                    $sessionListFollowed = self::get_sessions_followed_by_drh(
6601
                        $userId,
6602
                        null,
6603
                        null,
6604
                        false,
6605
                        true
6606
                    );
6607
6608
                    if (!empty($sessionListFollowed)) {
6609
                        $sessionIdList = array_column($sessionListFollowed, 'id');
6610
                    }
6611
                }
6612
6613
                if (!empty($sessionIdList)) {
6614
                    $sessionIdList = array_map('intval', $sessionIdList);
6615
                    $sessionsListSql = "'".implode("','", $sessionIdList)."'";
6616
                    $sessionConditions = " AND s.id IN ($sessionsListSql) ";
6617
                }
6618
6619
                break;
6620
            case 'teacher':
6621
            case 'session_admin':
6622
                $generalCoachedSessions = array_map(
6623
                    fn(Session $session) => $session->getId(),
6624
                    api_get_user_entity($userId)->getSessionsAsGeneralCoach()
6625
                );
6626
6627
                $sessionConditions = " AND s.IN (".implode(',', $generalCoachedSessions).") ";
6628
                $userConditionsFromDrh = '';
6629
                break;
6630
        }
6631
6632
        $select = 'SELECT DISTINCT u.*, u.id as user_id';
6633
        $masterSelect = 'SELECT DISTINCT id, id as user_id FROM ';
6634
6635
        if ($getCount) {
6636
            $select = 'SELECT DISTINCT u.id, u.id as user_id';
6637
            $masterSelect = 'SELECT COUNT(DISTINCT(id)) as count FROM ';
6638
        }
6639
6640
        if (!empty($filterByStatus)) {
6641
            $userConditions .= " AND u.status = $filterByStatus";
6642
        }
6643
6644
        if (!empty($lastConnectionDate)) {
6645
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
6646
            $userConditions .= " AND u.last_login <= '$lastConnectionDate' ";
6647
        }
6648
6649
        if (!empty($keyword)) {
6650
            $keyword = Database::escape_string($keyword);
6651
            $userConditions .= " AND (
6652
                u.username LIKE '%$keyword%' OR
6653
                u.firstname LIKE '%$keyword%' OR
6654
                u.lastname LIKE '%$keyword%' OR
6655
                u.official_code LIKE '%$keyword%' OR
6656
                u.email LIKE '%$keyword%'
6657
            )";
6658
        }
6659
6660
        $where = " WHERE
6661
                   access_url_id = $urlId
6662
                   $userConditions
6663
        ";
6664
6665
        $userUnion = '';
6666
        if (!empty($userConditionsFromDrh)) {
6667
            $userUnion = "
6668
            UNION (
6669
                $select
6670
                FROM $tbl_user u
6671
                INNER JOIN $tbl_user_rel_access_url url
6672
                ON (url.user_id = u.id)
6673
                $where
6674
                $userConditionsFromDrh
6675
            )";
6676
        }
6677
6678
        $sql = "$masterSelect (
6679
                ($select
6680
                FROM $tbl_session s
6681
                    INNER JOIN $tbl_session_rel_access_url url
6682
                    ON (url.session_id = s.id)
6683
                    INNER JOIN $tbl_session_rel_course_rel_user su
6684
                    ON (s.id = su.session_id)
6685
                    INNER JOIN $tbl_user u
6686
                    ON (u.id = su.user_id)
6687
                    $where
6688
                    $sessionConditions
6689
                    $userConditionsFromDrh
6690
                ) UNION (
6691
                    $select
6692
                    FROM $tbl_course c
6693
                    INNER JOIN $tbl_course_rel_access_url url
6694
                    ON (url.c_id = c.id)
6695
                    INNER JOIN $tbl_course_user cu
6696
                    ON (cu.c_id = c.id)
6697
                    INNER JOIN $tbl_user u
6698
                    ON (u.id = cu.user_id)
6699
                    $where
6700
                    $courseConditions
6701
                    $userConditionsFromDrh
6702
                ) $userUnion
6703
                ) as t1
6704
                ";
6705
6706
        if ($getCount) {
6707
            $result = Database::query($sql);
6708
6709
            $count = 0;
6710
            if (Database::num_rows($result)) {
6711
                $rows = Database::fetch_array($result);
6712
                $count = $rows['count'];
6713
            }
6714
6715
            return $count;
6716
        }
6717
6718
        if (!empty($column) && !empty($direction)) {
6719
            $column = str_replace('u.', '', $column);
6720
            $sql .= " ORDER BY `$column` $direction ";
6721
        }
6722
6723
        $limitCondition = '';
6724
        if (isset($from) && isset($numberItems)) {
6725
            $from = (int) $from;
6726
            $numberItems = (int) $numberItems;
6727
            $limitCondition = "LIMIT $from, $numberItems";
6728
        }
6729
6730
        $sql .= $limitCondition;
6731
        $result = Database::query($sql);
6732
6733
        return Database::store_result($result);
6734
    }
6735
6736
    /**
6737
     * @param int   $sessionId
6738
     * @param int   $courseId
6739
     * @param array $coachList
6740
     * @param bool  $deleteCoachesNotInList
6741
     */
6742
    public static function updateCoaches(
6743
        $sessionId,
6744
        $courseId,
6745
        $coachList,
6746
        $deleteCoachesNotInList = false
6747
    ) {
6748
        $currentCoaches = self::getCoachesByCourseSession($sessionId, $courseId);
6749
6750
        if (!empty($coachList)) {
6751
            foreach ($coachList as $userId) {
6752
                self::set_coach_to_course_session($userId, $sessionId, $courseId);
6753
            }
6754
        }
6755
6756
        if ($deleteCoachesNotInList) {
6757
            if (!empty($coachList)) {
6758
                $coachesToDelete = array_diff($currentCoaches, $coachList);
6759
            } else {
6760
                $coachesToDelete = $currentCoaches;
6761
            }
6762
6763
            if (!empty($coachesToDelete)) {
6764
                foreach ($coachesToDelete as $userId) {
6765
                    self::set_coach_to_course_session(
6766
                        $userId,
6767
                        $sessionId,
6768
                        $courseId,
6769
                        true
6770
                    );
6771
                }
6772
            }
6773
        }
6774
    }
6775
6776
    /**
6777
     * @param array $sessions
6778
     * @param array $sessionsDestination
6779
     *
6780
     * @return array
6781
     */
6782
    public static function copyStudentsFromSession($sessions, $sessionsDestination)
6783
    {
6784
        $messages = [];
6785
        if (!empty($sessions)) {
6786
            foreach ($sessions as $sessionId) {
6787
                $sessionInfo = self::fetch($sessionId);
6788
                $userList = self::get_users_by_session($sessionId, 0);
6789
                if (!empty($userList)) {
6790
                    $newUserList = [];
6791
                    $userToString = null;
6792
                    foreach ($userList as $userInfo) {
6793
                        $newUserList[] = $userInfo['user_id'];
6794
                        $userToString .= $userInfo['firstname'].' '.$userInfo['lastname'].'<br />';
6795
                    }
6796
6797
                    if (!empty($sessionsDestination)) {
6798
                        foreach ($sessionsDestination as $sessionDestinationId) {
6799
                            $sessionDestinationInfo = self::fetch($sessionDestinationId);
6800
                            $messages[] = Display::return_message(
6801
                                sprintf(
6802
                                    get_lang(
6803
                                        'AddingStudentsFromSessionXToSessionY'
6804
                                    ),
6805
                                    $sessionInfo['title'],
6806
                                    $sessionDestinationInfo['title']
6807
                                ),
6808
                                'info',
6809
                                false
6810
                            );
6811
                            if ($sessionId == $sessionDestinationId) {
6812
                                $messages[] = Display::return_message(
6813
                                    sprintf(
6814
                                        get_lang('Session %s skipped'),
6815
                                        $sessionDestinationId
6816
                                    ),
6817
                                    'warning',
6818
                                    false
6819
                                );
6820
                                continue;
6821
                            }
6822
                            $messages[] = Display::return_message(get_lang('Learner list').'<br />'.$userToString, 'info', false);
6823
                            self::subscribeUsersToSession(
6824
                                $sessionDestinationId,
6825
                                $newUserList,
6826
                                SESSION_VISIBLE_READ_ONLY,
6827
                                false
6828
                            );
6829
                        }
6830
                    } else {
6831
                        $messages[] = Display::return_message(get_lang('No destination session provided'), 'warning');
6832
                    }
6833
                } else {
6834
                    $messages[] = Display::return_message(
6835
                        get_lang('No student found for the session').' #'.$sessionInfo['title'],
6836
                        'warning'
6837
                    );
6838
                }
6839
            }
6840
        } else {
6841
            $messages[] = Display::return_message(get_lang('No data available'), 'warning');
6842
        }
6843
6844
        return $messages;
6845
    }
6846
6847
    /**
6848
     * Assign coaches of a session(s) as teachers to a given course (or courses).
6849
     *
6850
     * @param array A list of session IDs
6851
     * @param array A list of course IDs
6852
     *
6853
     * @return string
6854
     */
6855
    public static function copyCoachesFromSessionToCourse($sessions, $courses)
6856
    {
6857
        $coachesPerSession = [];
6858
        foreach ($sessions as $sessionId) {
6859
            $coaches = self::getCoachesBySession($sessionId);
6860
            $coachesPerSession[$sessionId] = $coaches;
6861
        }
6862
6863
        $result = [];
6864
6865
        if (!empty($courses)) {
6866
            foreach ($courses as $courseId) {
6867
                $courseInfo = api_get_course_info_by_id($courseId);
6868
                foreach ($coachesPerSession as $sessionId => $coachList) {
6869
                    CourseManager::updateTeachers(
6870
                        $courseInfo,
6871
                        $coachList,
6872
                        false,
6873
                        false,
6874
                        false
6875
                    );
6876
                    $result[$courseInfo['code']][$sessionId] = $coachList;
6877
                }
6878
            }
6879
        }
6880
        $sessionUrl = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session=';
6881
        $htmlResult = null;
6882
6883
        if (!empty($result)) {
6884
            foreach ($result as $courseCode => $data) {
6885
                $url = api_get_course_url($courseCode);
6886
                $htmlResult .= sprintf(
6887
                    get_lang('Coaches subscribed as teachers in course %s'),
6888
                    Display::url($courseCode, $url, ['target' => '_blank'])
6889
                );
6890
                foreach ($data as $sessionId => $coachList) {
6891
                    $sessionInfo = self::fetch($sessionId);
6892
                    $htmlResult .= '<br />';
6893
                    $htmlResult .= Display::url(
6894
                        get_lang('Session').': '.$sessionInfo['title'].' <br />',
6895
                        $sessionUrl.$sessionId,
6896
                        ['target' => '_blank']
6897
                    );
6898
                    $teacherList = [];
6899
                    foreach ($coachList as $coachId) {
6900
                        $userInfo = api_get_user_info($coachId);
6901
                        $teacherList[] = $userInfo['complete_name'];
6902
                    }
6903
                    if (!empty($teacherList)) {
6904
                        $htmlResult .= implode(', ', $teacherList);
6905
                    } else {
6906
                        $htmlResult .= get_lang('Nothing to add');
6907
                    }
6908
                }
6909
                $htmlResult .= '<br />';
6910
            }
6911
            $htmlResult = Display::return_message($htmlResult, 'normal', false);
6912
        }
6913
6914
        return $htmlResult;
6915
    }
6916
6917
    /**
6918
     * @param string $keyword
6919
     * @param string $active
6920
     * @param string $lastConnectionDate
6921
     * @param array  $sessionIdList
6922
     * @param array  $studentIdList
6923
     * @param int    $filterUserStatus   STUDENT|COURSEMANAGER constants
6924
     *
6925
     * @return array|int
6926
     */
6927
    public static function getCountUserTracking(
6928
        $keyword = null,
6929
        $active = null,
6930
        $lastConnectionDate = null,
6931
        $sessionIdList = [],
6932
        $studentIdList = [],
6933
        $filterUserStatus = null
6934
    ) {
6935
        $userId = api_get_user_id();
6936
        $drhLoaded = false;
6937
6938
        if (api_is_drh()) {
6939
            if (api_drh_can_access_all_session_content()) {
6940
                $count = self::getAllUsersFromCoursesFromAllSessionFromStatus(
6941
                    'drh_all',
6942
                    $userId,
6943
                    true,
6944
                    null,
6945
                    null,
6946
                    null,
6947
                    null,
6948
                    $keyword,
6949
                    $active,
6950
                    $lastConnectionDate,
6951
                    $sessionIdList,
6952
                    $studentIdList,
6953
                    $filterUserStatus
6954
                );
6955
                $drhLoaded = true;
6956
            }
6957
        }
6958
6959
        if (false == $drhLoaded) {
6960
            $count = UserManager::getUsersFollowedByUser(
6961
                $userId,
6962
                $filterUserStatus,
6963
                false,
6964
                false,
6965
                true,
6966
                null,
6967
                null,
6968
                null,
6969
                null,
6970
                $active,
6971
                $lastConnectionDate,
6972
                api_is_student_boss() ? STUDENT_BOSS : COURSEMANAGER,
6973
                $keyword
6974
            );
6975
        }
6976
6977
        return $count;
6978
    }
6979
6980
    /**
6981
     * Get teachers followed by a user.
6982
     *
6983
     * @param int    $userId
6984
     * @param int    $active
6985
     * @param string $lastConnectionDate
6986
     * @param bool   $getCount
6987
     * @param array  $sessionIdList
6988
     *
6989
     * @return array|int
6990
     */
6991
    public static function getTeacherTracking(
6992
        $userId,
6993
        $active = 1,
6994
        $lastConnectionDate = null,
6995
        $getCount = false,
6996
        $sessionIdList = []
6997
    ) {
6998
        $teacherListId = [];
6999
        if (api_is_drh() || api_is_platform_admin()) {
7000
            // Followed teachers by drh
7001
            if (api_drh_can_access_all_session_content()) {
7002
                if (empty($sessionIdList)) {
7003
                    $sessions = self::get_sessions_followed_by_drh($userId);
7004
                    $sessionIdList = [];
7005
                    foreach ($sessions as $session) {
7006
                        $sessionIdList[] = $session['id'];
7007
                    }
7008
                }
7009
7010
                $sessionIdList = array_map('intval', $sessionIdList);
7011
                $sessionToString = implode("', '", $sessionIdList);
7012
7013
                $course = Database::get_main_table(TABLE_MAIN_COURSE);
7014
                $sessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7015
                $courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
7016
7017
                // Select the teachers.
7018
                $sql = "SELECT DISTINCT(cu.user_id)
7019
                        FROM $course c
7020
                        INNER JOIN $sessionCourse src
7021
                        ON c.id = src.c_id
7022
                        INNER JOIN $courseUser cu
7023
                        ON (cu.c_id = c.id)
7024
		                WHERE src.session_id IN ('$sessionToString') AND cu.status = 1";
7025
                $result = Database::query($sql);
7026
                while ($row = Database::fetch_assoc($result)) {
7027
                    $teacherListId[$row['user_id']] = $row['user_id'];
7028
                }
7029
            } else {
7030
                $teacherResult = UserManager::get_users_followed_by_drh($userId, COURSEMANAGER);
7031
                foreach ($teacherResult as $userInfo) {
7032
                    $teacherListId[] = $userInfo['user_id'];
7033
                }
7034
            }
7035
        }
7036
7037
        if (!empty($teacherListId)) {
7038
            $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7039
7040
            $select = "SELECT DISTINCT u.* ";
7041
            if ($getCount) {
7042
                $select = "SELECT count(DISTINCT(u.id)) as count";
7043
            }
7044
7045
            $sql = "$select FROM $tableUser u";
7046
7047
            if (!empty($lastConnectionDate)) {
7048
                $tableLogin = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7049
                //$sql .= " INNER JOIN $tableLogin l ON (l.login_user_id = u.user_id) ";
7050
            }
7051
            $active = intval($active);
7052
            $teacherListId = implode("','", $teacherListId);
7053
            $where = " WHERE u.active = $active AND u.id IN ('$teacherListId') ";
7054
7055
            if (!empty($lastConnectionDate)) {
7056
                $lastConnectionDate = Database::escape_string($lastConnectionDate);
7057
                //$where .= " AND l.login_date <= '$lastConnectionDate' ";
7058
            }
7059
7060
            $sql .= $where;
7061
            $result = Database::query($sql);
7062
            if (Database::num_rows($result)) {
7063
                if ($getCount) {
7064
                    $row = Database::fetch_array($result);
7065
7066
                    return $row['count'];
7067
                } else {
7068
                    return Database::store_result($result, 'ASSOC');
7069
                }
7070
            }
7071
        }
7072
7073
        return 0;
7074
    }
7075
7076
    /**
7077
     * Get the list of course tools that have to be dealt with in case of
7078
     * registering any course to a session.
7079
     *
7080
     * @return array The list of tools to be dealt with (literal names)
7081
     */
7082
    public static function getCourseToolToBeManaged()
7083
    {
7084
        return [
7085
            'courseDescription',
7086
            'courseIntroduction',
7087
        ];
7088
    }
7089
7090
    /**
7091
     * Calls the methods bound to each tool when a course is registered into a session.
7092
     *
7093
     * @param int $sessionId
7094
     * @param int $courseId
7095
     *
7096
     * @return bool
7097
     */
7098
    public static function installCourse($sessionId, $courseId)
7099
    {
7100
        return true;
7101
        $toolList = self::getCourseToolToBeManaged();
0 ignored issues
show
Unused Code introduced by
$toolList = self::getCourseToolToBeManaged() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
7102
7103
        foreach ($toolList as $tool) {
7104
            $method = 'add'.$tool;
7105
            if (method_exists(get_class(), $method)) {
7106
                self::$method($sessionId, $courseId);
7107
            }
7108
        }
7109
    }
7110
7111
    /**
7112
     * Calls the methods bound to each tool when a course is unregistered from
7113
     * a session.
7114
     *
7115
     * @param int $sessionId
7116
     * @param int $courseId
7117
     */
7118
    public static function unInstallCourse($sessionId, $courseId)
7119
    {
7120
        return true;
7121
        $toolList = self::getCourseToolToBeManaged();
0 ignored issues
show
Unused Code introduced by
$toolList = self::getCourseToolToBeManaged() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
7122
7123
        foreach ($toolList as $tool) {
7124
            $method = 'remove'.$tool;
7125
            if (method_exists(get_class(), $method)) {
7126
                self::$method($sessionId, $courseId);
7127
            }
7128
        }
7129
    }
7130
7131
    /**
7132
     * @param array $userSessionList        format see self::importSessionDrhCSV()
7133
     * @param bool  $sendEmail
7134
     * @param bool  $removeOldRelationShips
7135
     */
7136
    public static function subscribeDrhToSessionList(
7137
        $userSessionList,
7138
        $sendEmail,
7139
        $removeOldRelationShips
7140
    ) {
7141
        if (!empty($userSessionList)) {
7142
            foreach ($userSessionList as $userId => $data) {
7143
                $sessionList = [];
7144
                foreach ($data['session_list'] as $sessionInfo) {
7145
                    $sessionList[] = $sessionInfo['session_id'];
7146
                }
7147
                $userInfo = $data['user_info'];
7148
                self::subscribeSessionsToDrh(
7149
                    $userInfo,
7150
                    $sessionList,
7151
                    $sendEmail,
7152
                    $removeOldRelationShips
7153
                );
7154
            }
7155
        }
7156
    }
7157
7158
    /**
7159
     * @param array $userSessionList format see self::importSessionDrhCSV()
7160
     *
7161
     * @return string
7162
     */
7163
    public static function checkSubscribeDrhToSessionList($userSessionList)
7164
    {
7165
        $message = null;
7166
        if (!empty($userSessionList)) {
7167
            if (!empty($userSessionList)) {
7168
                foreach ($userSessionList as $userId => $data) {
7169
                    $userInfo = $data['user_info'];
7170
7171
                    $sessionListSubscribed = self::get_sessions_followed_by_drh($userId);
7172
                    if (!empty($sessionListSubscribed)) {
7173
                        $sessionListSubscribed = array_keys($sessionListSubscribed);
7174
                    }
7175
7176
                    $sessionList = [];
7177
                    if (!empty($data['session_list'])) {
7178
                        foreach ($data['session_list'] as $sessionInfo) {
7179
                            if (in_array($sessionInfo['session_id'], $sessionListSubscribed)) {
7180
                                $sessionList[] = $sessionInfo['session_info']['title'];
7181
                            }
7182
                        }
7183
                    }
7184
7185
                    $message .= '<strong>'.get_lang('User').'</strong>: ';
7186
                    $message .= $userInfo['complete_name_with_username'].' <br />';
7187
7188
                    if (!in_array($userInfo['status'], [DRH]) && !api_is_platform_admin_by_id($userInfo['user_id'])) {
7189
                        $message .= get_lang('Users must have the HR director role').'<br />';
7190
                        continue;
7191
                    }
7192
7193
                    if (!empty($sessionList)) {
7194
                        $message .= '<strong>'.get_lang('Course sessions').':</strong> <br />';
7195
                        $message .= implode(', ', $sessionList).'<br /><br />';
7196
                    } else {
7197
                        $message .= get_lang('No session provided').' <br /><br />';
7198
                    }
7199
                }
7200
            }
7201
        }
7202
7203
        return $message;
7204
    }
7205
7206
    /**
7207
     * @param string $file
7208
     * @param bool   $sendEmail
7209
     * @param bool   $removeOldRelationShips
7210
     *
7211
     * @return string
7212
     */
7213
    public static function importSessionDrhCSV($file, $sendEmail, $removeOldRelationShips)
7214
    {
7215
        $list = Import::csv_reader($file);
7216
7217
        if (!empty($list)) {
7218
            $userSessionList = [];
7219
            foreach ($list as $data) {
7220
                $sessionInfo = [];
7221
                if (isset($data['SessionId'])) {
7222
                    $sessionInfo = api_get_session_info($data['SessionId']);
7223
                }
7224
7225
                if (isset($data['SessionName']) && empty($sessionInfo)) {
7226
                $sessionInfo = self::get_session_by_name($data['SessionName']);
7227
                }
7228
7229
                if (empty($sessionInfo)) {
7230
                    $sessionData = isset($data['SessionName']) ? $data['SessionName'] : $data['SessionId'];
7231
                    Display::addFlash(
7232
                        Display::return_message(get_lang('Session not found.').' - '.$sessionData, 'warning')
7233
                    );
7234
                    continue;
7235
                }
7236
                $userList = explode(',', $data['Username']);
7237
7238
                foreach ($userList as $username) {
7239
                    $userInfo = api_get_user_info_from_username($username);
7240
7241
                if (empty($userInfo)) {
7242
                        Display::addFlash(
7243
                            Display::return_message(get_lang("This user doesn't exist").' - '.$username, 'warning')
7244
                        );
7245
                        continue;
7246
                }
7247
7248
                if (!empty($userInfo) && !empty($sessionInfo)) {
7249
                    $userSessionList[$userInfo['user_id']]['session_list'][] = [
7250
                        'session_id' => $sessionInfo['id'],
7251
                        'session_info' => $sessionInfo,
7252
                    ];
7253
                    $userSessionList[$userInfo['user_id']]['user_info'] = $userInfo;
7254
                    }
7255
                }
7256
            }
7257
7258
            self::subscribeDrhToSessionList($userSessionList, $sendEmail, $removeOldRelationShips);
7259
7260
            return self::checkSubscribeDrhToSessionList($userSessionList);
7261
        }
7262
    }
7263
7264
    /**
7265
     * Courses re-ordering in resume_session.php flag see BT#8316.
7266
     */
7267
    public static function orderCourseIsEnabled()
7268
    {
7269
        $sessionCourseOrder = api_get_setting('session_course_ordering');
7270
        if ('true' === $sessionCourseOrder) {
7271
            return true;
7272
        }
7273
7274
        return false;
7275
    }
7276
7277
    /**
7278
     * @param string $direction (up/down)
7279
     * @param int    $sessionId
7280
     * @param int    $courseId
7281
     *
7282
     * @return bool
7283
     */
7284
    public static function move($direction, $sessionId, $courseId)
7285
    {
7286
        if (!self::orderCourseIsEnabled()) {
7287
            return false;
7288
        }
7289
7290
        $sessionId = intval($sessionId);
7291
        $courseId = intval($courseId);
7292
7293
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7294
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7295
7296
        $position = [];
7297
        $count = 0;
7298
        foreach ($courseList as $course) {
7299
            if ('' == $course['position']) {
7300
                $course['position'] = $count;
7301
            }
7302
            $position[$course['code']] = $course['position'];
7303
            // Saving current order.
7304
            $sql = "UPDATE $table SET position = $count
7305
                    WHERE session_id = $sessionId AND c_id = '".$course['real_id']."'";
7306
            Database::query($sql);
7307
            $count++;
7308
        }
7309
7310
        // Loading new positions.
7311
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7312
7313
        $found = false;
7314
7315
        switch ($direction) {
7316
            case 'up':
7317
                $courseList = array_reverse($courseList);
7318
                break;
7319
            case 'down':
7320
                break;
7321
        }
7322
7323
        foreach ($courseList as $course) {
7324
            if ($found) {
7325
                $nextId = $course['real_id'];
7326
                $nextOrder = $course['position'];
7327
                break;
7328
            }
7329
7330
            if ($courseId == $course['real_id']) {
7331
                $thisCourseCode = $course['real_id'];
7332
                $thisOrder = $course['position'];
7333
                $found = true;
7334
            }
7335
        }
7336
7337
        $sql1 = "UPDATE $table SET position = '".intval($nextOrder)."'
7338
                 WHERE session_id = $sessionId AND c_id =  $thisCourseCode";
7339
        Database::query($sql1);
7340
7341
        $sql2 = "UPDATE $table SET position = '".intval($thisOrder)."'
7342
                 WHERE session_id = $sessionId AND c_id = $nextId";
7343
        Database::query($sql2);
7344
7345
        return true;
7346
    }
7347
7348
    /**
7349
     * @param int $sessionId
7350
     * @param int $courseId
7351
     *
7352
     * @return bool
7353
     */
7354
    public static function moveUp($sessionId, $courseId)
7355
    {
7356
        return self::move('up', $sessionId, $courseId);
7357
    }
7358
7359
    /**
7360
     * @param int    $sessionId
7361
     * @param string $courseCode
7362
     *
7363
     * @return bool
7364
     */
7365
    public static function moveDown($sessionId, $courseCode)
7366
    {
7367
        return self::move('down', $sessionId, $courseCode);
7368
    }
7369
7370
    /**
7371
     * Use the session duration to allow/block user access see BT#8317
7372
     * Needs these DB changes
7373
     * ALTER TABLE session ADD COLUMN duration int;
7374
     * ALTER TABLE session_rel_user ADD COLUMN duration int;.
7375
     */
7376
    public static function durationPerUserIsEnabled()
7377
    {
7378
        return api_get_configuration_value('session_duration_feature');
7379
    }
7380
7381
    /**
7382
     * Returns the number of days the student has left in a session when using
7383
     * sessions durations.
7384
     *
7385
     * @param int $userId
7386
     *
7387
     * @return int
7388
     */
7389
    public static function getDayLeftInSession(array $sessionInfo, $userId)
7390
    {
7391
        $sessionId = $sessionInfo['id'];
7392
        $subscription = self::getUserSession($userId, $sessionId);
7393
        $duration = empty($subscription['duration'])
7394
            ? $sessionInfo['duration']
7395
            : $sessionInfo['duration'] + $subscription['duration'];
7396
7397
        // Get an array with the details of the first access of the student to
7398
        // this session
7399
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
7400
            $sessionId,
7401
            $userId
7402
        );
7403
7404
        $currentTime = time();
7405
7406
        // If no previous access, return false
7407
        if (0 == count($courseAccess)) {
7408
            return $duration;
7409
        }
7410
7411
        $firstAccess = api_strtotime($courseAccess['login_course_date'], 'UTC');
7412
        $endDateInSeconds = $firstAccess + $duration * 24 * 60 * 60;
7413
        $leftDays = round(($endDateInSeconds - $currentTime) / 60 / 60 / 24);
7414
7415
        return $leftDays;
7416
    }
7417
7418
    /**
7419
     * @param int $duration
7420
     * @param int $userId
7421
     * @param int $sessionId
7422
     *
7423
     * @return bool
7424
     */
7425
    public static function editUserSessionDuration($duration, $userId, $sessionId)
7426
    {
7427
        $duration = (int) $duration;
7428
        $userId = (int) $userId;
7429
        $sessionId = (int) $sessionId;
7430
7431
        if (empty($userId) || empty($sessionId)) {
7432
            return false;
7433
        }
7434
7435
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7436
        $parameters = ['duration' => $duration];
7437
        $where = ['session_id = ? AND user_id = ? ' => [$sessionId, $userId]];
7438
        Database::update($table, $parameters, $where);
7439
7440
        return true;
7441
    }
7442
7443
    /**
7444
     * Gets one row from the session_rel_user table.
7445
     *
7446
     * @param int $userId
7447
     * @param int $sessionId
7448
     *
7449
     * @return array
7450
     */
7451
    public static function getUserSession($userId, $sessionId)
7452
    {
7453
        $userId = (int) $userId;
7454
        $sessionId = (int) $sessionId;
7455
7456
        if (empty($userId) || empty($sessionId)) {
7457
            return false;
7458
        }
7459
7460
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7461
        $sql = "SELECT * FROM $table
7462
                WHERE session_id = $sessionId AND user_id = $userId";
7463
        $result = Database::query($sql);
7464
        $values = [];
7465
        if (Database::num_rows($result)) {
7466
            $values = Database::fetch_assoc($result);
7467
        }
7468
7469
        return $values;
7470
    }
7471
7472
    /**
7473
     * Check if user is subscribed inside a session as student.
7474
     *
7475
     * @param int $sessionId The session id
7476
     * @param int $userId    The user id
7477
     *
7478
     * @return bool Whether is subscribed
7479
     */
7480
    public static function isUserSubscribedAsStudent($sessionId, $userId)
7481
    {
7482
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7483
        $sessionId = (int) $sessionId;
7484
        $userId = (int) $userId;
7485
7486
        // COUNT(1) actually returns the number of rows from the table (as if
7487
        // counting the results from the first column)
7488
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7489
                WHERE
7490
                    session_id = $sessionId AND
7491
                    user_id = $userId AND
7492
                    relation_type = ".Session::STUDENT;
7493
7494
        $result = Database::fetch_assoc(Database::query($sql));
7495
7496
        if (!empty($result) && $result['qty'] > 0) {
7497
            return true;
7498
        }
7499
7500
        return false;
7501
    }
7502
7503
    /**
7504
     * Check if user is subscribed inside a session as a HRM.
7505
     *
7506
     * @param int $sessionId The session id
7507
     * @param int $userId    The user id
7508
     *
7509
     * @return bool Whether is subscribed
7510
     */
7511
    public static function isUserSubscribedAsHRM($sessionId, $userId)
7512
    {
7513
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7514
7515
        $sessionId = (int) $sessionId;
7516
        $userId = (int) $userId;
7517
7518
        // COUNT(1) actually returns the number of rows from the table (as if
7519
        // counting the results from the first column)
7520
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7521
                WHERE
7522
                    session_id = $sessionId AND
7523
                    user_id = $userId AND
7524
                    relation_type = ".Session::DRH;
7525
7526
        $result = Database::fetch_assoc(Database::query($sql));
7527
7528
        if (!empty($result) && $result['qty'] > 0) {
7529
            return true;
7530
        }
7531
7532
        return false;
7533
    }
7534
7535
    /**
7536
     * Get the session coached by a user (general coach and course-session coach).
7537
     *
7538
     * @param int  $coachId                       The coach id
7539
     * @param bool $checkSessionRelUserVisibility Check the session visibility
7540
     * @param bool $asPlatformAdmin               The user is a platform admin and we want all sessions
7541
     *
7542
     * @return array The session list
7543
     */
7544
    public static function getSessionsCoachedByUser(
7545
        $coachId,
7546
        $checkSessionRelUserVisibility = false,
7547
        $asPlatformAdmin = false
7548
    ) {
7549
        // Get all sessions where $coachId is the general coach
7550
        $sessions = self::get_sessions_by_general_coach($coachId, $asPlatformAdmin);
7551
        // Get all sessions where $coachId is the course - session coach
7552
        $courseSessionList = self::getCoursesListByCourseCoach($coachId);
7553
        $sessionsByCoach = [];
7554
        if (!empty($courseSessionList)) {
7555
            foreach ($courseSessionList as $userCourseSubscription) {
7556
                $session = $userCourseSubscription->getSession();
7557
                $sessionsByCoach[$session->getId()] = api_get_session_info(
7558
                    $session->getId()
7559
                );
7560
            }
7561
        }
7562
7563
        if (!empty($sessionsByCoach)) {
7564
            $sessions = array_merge($sessions, $sessionsByCoach);
7565
        }
7566
7567
        // Remove repeated sessions
7568
        if (!empty($sessions)) {
7569
            $cleanSessions = [];
7570
            foreach ($sessions as $session) {
7571
                $cleanSessions[$session['id']] = $session;
7572
            }
7573
            $sessions = $cleanSessions;
7574
        }
7575
7576
        if ($checkSessionRelUserVisibility) {
7577
            if (!empty($sessions)) {
7578
                $newSessions = [];
7579
                foreach ($sessions as $session) {
7580
                    $visibility = api_get_session_visibility($session['id']);
7581
                    if (SESSION_INVISIBLE == $visibility) {
7582
                        continue;
7583
                    }
7584
                    $newSessions[] = $session;
7585
                }
7586
                $sessions = $newSessions;
7587
            }
7588
        }
7589
7590
        return $sessions;
7591
    }
7592
7593
    /**
7594
     * Check if the course belongs to the session.
7595
     *
7596
     * @param int    $sessionId  The session id
7597
     * @param string $courseCode The course code
7598
     *
7599
     * @return bool
7600
     */
7601
    public static function sessionHasCourse($sessionId, $courseCode)
7602
    {
7603
        $sessionId = (int) $sessionId;
7604
        $courseCode = Database::escape_string($courseCode);
7605
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7606
        $sessionRelCourseTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7607
7608
        $sql = "SELECT COUNT(1) AS qty
7609
                FROM $courseTable c
7610
                INNER JOIN $sessionRelCourseTable src
7611
                ON c.id = src.c_id
7612
                WHERE src.session_id = $sessionId
7613
                AND c.code = '$courseCode'  ";
7614
7615
        $result = Database::query($sql);
7616
7617
        if (false !== $result) {
7618
            $data = Database::fetch_assoc($result);
7619
7620
            if ($data['qty'] > 0) {
7621
                return true;
7622
            }
7623
        }
7624
7625
        return false;
7626
    }
7627
7628
    /**
7629
     * Calculate the total user time in the platform.
7630
     *
7631
     * @param int    $userId The user id
7632
     * @param string $from   Optional. From date
7633
     * @param string $until  Optional. Until date
7634
     *
7635
     * @return string The time (hh:mm:ss)
7636
     */
7637
    public static function getTotalUserTimeInPlatform($userId, $from = '', $until = '')
7638
    {
7639
        $userId = (int) $userId;
7640
        $trackLoginTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7641
        $whereConditions = [
7642
            'login_user_id = ? ' => $userId,
7643
        ];
7644
7645
        if (!empty($from) && !empty($until)) {
7646
            $whereConditions["AND (login_date >= '?' "] = $from;
7647
            $whereConditions["AND logout_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
7648
        }
7649
7650
        $trackResult = Database::select(
7651
            'SEC_TO_TIME(SUM(UNIX_TIMESTAMP(logout_date) - UNIX_TIMESTAMP(login_date))) as total_time',
7652
            $trackLoginTable,
7653
            [
7654
                'where' => $whereConditions,
7655
            ],
7656
            'first'
7657
        );
7658
7659
        if (false != $trackResult) {
7660
            return $trackResult['total_time'] ? $trackResult['total_time'] : '00:00:00';
7661
        }
7662
7663
        return '00:00:00';
7664
    }
7665
7666
    /**
7667
     * Get the courses list by a course coach.
7668
     *
7669
     * @param int $coachId The coach id
7670
     *
7671
     * @return array (id, user_id, session_id, c_id, visibility, status, legal_agreement)
7672
     */
7673
    public static function getCoursesListByCourseCoach($coachId)
7674
    {
7675
        $entityManager = Database::getManager();
7676
        $repo = $entityManager->getRepository(SessionRelCourseRelUser::class);
7677
7678
        return $repo->findBy([
7679
            'user' => $coachId,
7680
            'status' => Session::COURSE_COACH,
7681
        ]);
7682
    }
7683
7684
    /**
7685
     * Get the count of user courses in session.
7686
     *
7687
     * @param int $sessionId
7688
     * @param int $courseId
7689
     *
7690
     * @return array
7691
     */
7692
    public static function getTotalUserCoursesInSession($sessionId, $courseId = 0)
7693
    {
7694
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7695
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7696
7697
        $sessionId = (int) $sessionId;
7698
7699
        if (empty($sessionId)) {
7700
            return [];
7701
        }
7702
7703
        $courseCondition = '';
7704
        if (!empty($courseId)) {
7705
            $courseId = (int) $courseId;
7706
            $courseCondition = "  c_id = $courseId AND ";
7707
        }
7708
7709
        $sql = "SELECT
7710
                    COUNT(u.id) as count,
7711
                    u.id,
7712
                    scu.status status_in_session,
7713
                    u.status user_status
7714
                FROM $table scu
7715
                INNER JOIN $tableUser u
7716
                ON scu.user_id = u.id
7717
                WHERE
7718
                  $courseCondition
7719
                  scu.session_id = ".$sessionId."
7720
                GROUP BY u.id";
7721
7722
        $result = Database::query($sql);
7723
7724
        $list = [];
7725
        while ($data = Database::fetch_assoc($result)) {
7726
            $list[] = $data;
7727
        }
7728
7729
        return $list;
7730
    }
7731
7732
    /**
7733
     * Returns list of a few data from session (name, short description, start
7734
     * date, end date) and the given extra fields if defined based on a
7735
     * session category Id.
7736
     *
7737
     * @param int    $categoryId  The internal ID of the session category
7738
     * @param string $target      Value to search for in the session field values
7739
     * @param array  $extraFields A list of fields to be scanned and returned
7740
     *
7741
     * @return mixed
7742
     */
7743
    public static function getShortSessionListAndExtraByCategory(
7744
        $categoryId,
7745
        $target,
7746
        $extraFields = null,
7747
        $publicationDate = null
7748
    ) {
7749
        $categoryId = (int) $categoryId;
7750
        $sessionList = [];
7751
        // Check if categoryId is valid
7752
        if ($categoryId > 0) {
7753
            $target = Database::escape_string($target);
7754
            $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
7755
            $sfTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7756
            $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7757
            // Join session field and session field values tables
7758
            $joinTable = $sfTable.' sf INNER JOIN '.$sfvTable.' sfv ON sf.id = sfv.field_id';
7759
            $fieldsArray = [];
7760
            foreach ($extraFields as $field) {
7761
                $fieldsArray[] = Database::escape_string($field);
7762
            }
7763
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7764
            if (isset($publicationDate)) {
7765
                $publicationDateString = $publicationDate->format('Y-m-d H:i:s');
7766
                $wherePublication = " AND id NOT IN (
7767
                    SELECT sfv.item_id FROM $joinTable
7768
                    WHERE
7769
                        sf.item_type = $extraFieldType AND
7770
                        ((sf.variable = 'publication_start_date' AND sfv.field_value > '$publicationDateString' and sfv.field_value != '') OR
7771
                        (sf.variable = 'publication_end_date' AND sfv.field_value < '$publicationDateString' and sfv.field_value != ''))
7772
                )";
7773
            }
7774
            // Get the session list from session category and target
7775
            $sessionList = Database::select(
7776
                'id, title, access_start_date, access_end_date',
7777
                $sTable,
7778
                [
7779
                    'where' => [
7780
                        "session_category_id = ? AND id IN (
7781
                            SELECT sfv.item_id FROM $joinTable
7782
                            WHERE
7783
                                sf.item_type = $extraFieldType AND
7784
                                sfv.item_id = session.id AND
7785
                                sf.variable = 'target' AND
7786
                                sfv.field_value = ?
7787
                        ) $wherePublication" => [$categoryId, $target],
7788
                    ],
7789
                ]
7790
            );
7791
            $whereFieldVariables = [];
7792
            $whereFieldIds = [];
7793
            if (
7794
                is_array($fieldsArray) &&
7795
                count($fieldsArray) > 0
7796
            ) {
7797
                $whereParams = '?';
7798
                for ($i = 1; $i < count($fieldsArray); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
7799
                    $whereParams .= ', ?';
7800
                }
7801
                $whereFieldVariables = ' variable IN ( '.$whereParams.' )';
7802
                $whereFieldIds = 'field_id IN ( '.$whereParams.' )';
7803
            }
7804
            // Get session fields
7805
            $extraField = new ExtraFieldModel('session');
7806
            $questionMarks = substr(str_repeat('?, ', count($fieldsArray)), 0, -2);
7807
            $fieldsList = $extraField->get_all([
7808
                ' variable IN ( '.$questionMarks.' )' => $fieldsArray,
7809
            ]);
7810
            // Index session fields
7811
            foreach ($fieldsList as $field) {
7812
                $fields[$field['id']] = $field['variable'];
7813
            }
7814
            // Get session field values
7815
            $extra = new ExtraFieldValue('session');
7816
            $questionMarksFields = substr(str_repeat('?, ', count($fields)), 0, -2);
7817
            $sessionFieldValueList = $extra->get_all(['where' => ['field_id IN ( '.$questionMarksFields.' )' => array_keys($fields)]]);
7818
            // Add session fields values to session list
7819
            foreach ($sessionList as $id => &$session) {
7820
                foreach ($sessionFieldValueList as $sessionFieldValue) {
7821
                    // Match session field values to session
7822
                    if ($sessionFieldValue['item_id'] == $id) {
7823
                        // Check if session field value is set in session field list
7824
                        if (isset($fields[$sessionFieldValue['field_id']])) {
7825
                            // Avoid overwriting the session's ID field
7826
                            if ('id' != $fields[$sessionFieldValue['field_id']]) {
7827
                                $var = $fields[$sessionFieldValue['field_id']];
7828
                                $val = $sessionFieldValue['value'];
7829
                                // Assign session field value to session
7830
                                $session[$var] = $val;
7831
                            }
7832
                        }
7833
                    }
7834
                }
7835
            }
7836
        }
7837
7838
        return $sessionList;
7839
    }
7840
7841
    /**
7842
     * Return the Session Category id searched by name.
7843
     *
7844
     * @param string $categoryName Name attribute of session category used for search query
7845
     * @param bool   $force        boolean used to get even if something is wrong (e.g not unique name)
7846
     *
7847
     * @return int|array If success, return category id (int), else it will return an array
7848
     *                   with the next structure:
7849
     *                   array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7850
     */
7851
    public static function getSessionCategoryIdByName($categoryName, $force = false)
7852
    {
7853
        // Start error result
7854
        $errorResult = ['error' => true, 'errorMessage' => get_lang('There was an error.')];
7855
        $categoryName = Database::escape_string($categoryName);
7856
        // Check if is not empty category name
7857
        if (!empty($categoryName)) {
7858
            $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
7859
            // Get all session category with same name
7860
            $result = Database::select(
7861
                'id',
7862
                $sessionCategoryTable,
7863
                [
7864
                    'where' => [
7865
                        'title = ?' => $categoryName,
7866
                    ],
7867
                ]
7868
            );
7869
            // Check the result
7870
            if ($result < 1) {
7871
                // If not found any result, update error message
7872
                $errorResult['errorMessage'] = 'Not found any session category name '.$categoryName;
7873
            } elseif (count($result) > 1 && !$force) {
7874
                // If found more than one result and force is disabled, update error message
7875
                $errorResult['errorMessage'] = 'Found many session categories';
7876
            } elseif (1 == count($result) || $force) {
7877
                // If found just one session category or force option is enabled
7878
7879
                return key($result);
7880
            }
7881
        } else {
7882
            // category name is empty, update error message
7883
            $errorResult['errorMessage'] = 'Not valid category name';
7884
        }
7885
7886
        return $errorResult;
7887
    }
7888
7889
    /**
7890
     * Return all data from sessions (plus extra field, course and coach data) by category id.
7891
     *
7892
     * @param int $sessionCategoryId session category id used to search sessions
7893
     *
7894
     * @return array If success, return session list and more session related data, else it will return an array
7895
     *               with the next structure:
7896
     *               array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7897
     */
7898
    public static function getSessionListAndExtraByCategoryId($sessionCategoryId)
7899
    {
7900
        // Start error result
7901
        $errorResult = [
7902
            'error' => true,
7903
            'errorMessage' => get_lang('There was an error.'),
7904
        ];
7905
7906
        $sessionCategoryId = intval($sessionCategoryId);
7907
        // Check if session category id is valid
7908
        if ($sessionCategoryId > 0) {
7909
            // Get table names
7910
            $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
7911
            $sessionFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7912
            $sessionFieldValueTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7913
            $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7914
            $userTable = Database::get_main_table(TABLE_MAIN_USER);
7915
            $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7916
7917
            // Get all data from all sessions whit the session category specified
7918
            $sessionList = Database::select(
7919
                '*',
7920
                $sessionTable,
7921
                [
7922
                    'where' => [
7923
                        'session_category_id = ?' => $sessionCategoryId,
7924
                    ],
7925
                ]
7926
            );
7927
7928
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7929
7930
            // Check if session list query had result
7931
            if (!empty($sessionList)) {
7932
                // implode all session id
7933
                $sessionIdsString = '('.implode(', ', array_keys($sessionList)).')';
7934
                // Get all field variables
7935
                $sessionFieldList = Database::select(
7936
                    'id, variable',
7937
                    $sessionFieldTable,
7938
                    ['item_type = ? ' => [$extraFieldType]]
7939
                );
7940
7941
                // Get all field values
7942
                $sql = "SELECT item_id, field_id, value FROM
7943
                        $sessionFieldValueTable v INNER JOIN $sessionFieldTable f
7944
                        ON (f.id = v.field_id)
7945
                        WHERE
7946
                            item_id IN $sessionIdsString AND
7947
                            item_type = $extraFieldType
7948
                ";
7949
                $result = Database::query($sql);
7950
                $sessionFieldValueList = Database::store_result($result, 'ASSOC');
7951
7952
                // Check if session field values had result
7953
                if (!empty($sessionFieldValueList)) {
7954
                    $sessionFieldValueListBySession = [];
7955
                    foreach ($sessionFieldValueList as $key => $sessionFieldValue) {
7956
                        // Create an array to index ids to session id
7957
                        $sessionFieldValueListBySession[$sessionFieldValue['item_id']][] = $key;
7958
                    }
7959
                }
7960
                // Query used to find course-coaches from sessions
7961
                $sql = "SELECT
7962
                            scu.session_id,
7963
                            c.id AS course_id,
7964
                            c.code AS course_code,
7965
                            c.title AS course_title,
7966
                            u.username AS coach_username,
7967
                            u.firstname AS coach_firstname,
7968
                            u.lastname AS coach_lastname
7969
                        FROM $courseTable c
7970
                        INNER JOIN $sessionCourseUserTable scu ON c.id = scu.c_id
7971
                        INNER JOIN $userTable u ON scu.user_id = u.id
7972
                        WHERE scu.status = ".Session::COURSE_COACH." AND scu.session_id IN $sessionIdsString
7973
                        ORDER BY scu.session_id ASC ";
7974
                $res = Database::query($sql);
7975
                $sessionCourseList = Database::store_result($res, 'ASSOC');
7976
                // Check if course list had result
7977
                if (!empty($sessionCourseList)) {
7978
                    foreach ($sessionCourseList as $key => $sessionCourse) {
7979
                        // Create an array to index ids to session_id
7980
                        $sessionCourseListBySession[$sessionCourse['session_id']][] = $key;
7981
                    }
7982
                }
7983
                // Join lists
7984
                if (is_array($sessionList)) {
7985
                    foreach ($sessionList as $id => &$row) {
7986
                        if (
7987
                            !empty($sessionFieldValueListBySession) &&
7988
                            is_array($sessionFieldValueListBySession[$id])
7989
                        ) {
7990
                            // If have an index array for session extra fields, use it to join arrays
7991
                            foreach ($sessionFieldValueListBySession[$id] as $key) {
7992
                                $row['extra'][$key] = [
7993
                                    'field_name' => $sessionFieldList[$sessionFieldValueList[$key]['field_id']]['variable'],
7994
                                    'value' => $sessionFieldValueList[$key]['value'],
7995
                                ];
7996
                            }
7997
                        }
7998
                        if (
7999
                            !empty($sessionCourseListBySession) &&
8000
                            is_array($sessionCourseListBySession[$id])
8001
                        ) {
8002
                            // If have an index array for session course coach, use it to join arrays
8003
                            foreach ($sessionCourseListBySession[$id] as $key) {
8004
                                $row['course'][$key] = [
8005
                                    'course_id' => $sessionCourseList[$key]['course_id'],
8006
                                    'course_code' => $sessionCourseList[$key]['course_code'],
8007
                                    'course_title' => $sessionCourseList[$key]['course_title'],
8008
                                    'coach_username' => $sessionCourseList[$key]['coach_username'],
8009
                                    'coach_firstname' => $sessionCourseList[$key]['coach_firstname'],
8010
                                    'coach_lastname' => $sessionCourseList[$key]['coach_lastname'],
8011
                                ];
8012
                            }
8013
                        }
8014
                    }
8015
                }
8016
8017
                return $sessionList;
8018
            } else {
8019
                // Not found result, update error message
8020
                $errorResult['errorMessage'] = 'Not found any session for session category id '.$sessionCategoryId;
8021
            }
8022
        }
8023
8024
        return $errorResult;
8025
    }
8026
8027
    /**
8028
     * Return session description from session id.
8029
     *
8030
     * @param int $sessionId
8031
     *
8032
     * @return string
8033
     */
8034
    public static function getDescriptionFromSessionId($sessionId)
8035
    {
8036
        // Init variables
8037
        $sessionId = (int) $sessionId;
8038
        $description = '';
8039
        // Check if session id is valid
8040
        if ($sessionId > 0) {
8041
            // Select query from session id
8042
            $rows = Database::select(
8043
                'description',
8044
                Database::get_main_table(TABLE_MAIN_SESSION),
8045
                [
8046
                    'where' => [
8047
                        'id = ?' => $sessionId,
8048
                    ],
8049
                ]
8050
            );
8051
8052
            // Check if select query result is not empty
8053
            if (!empty($rows)) {
8054
                // Get session description
8055
                $description = $rows[0]['description'];
8056
            }
8057
        }
8058
8059
        return $description;
8060
    }
8061
8062
    /**
8063
     * Get a session list filtered by name, description or any of the given extra fields.
8064
     *
8065
     * @param string $term                 The term to search
8066
     * @param array  $extraFieldsToInclude Extra fields to include in the session data
8067
     *
8068
     * @return array The list
8069
     */
8070
    public static function searchSession($term, $extraFieldsToInclude = [])
8071
    {
8072
        $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
8073
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
8074
        $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8075
        $term = Database::escape_string($term);
8076
        $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
8077
        if (is_array($extraFieldsToInclude) && count($extraFieldsToInclude) > 0) {
8078
            $resultData = Database::select('*', $sTable, [
8079
                'where' => [
8080
                    "title LIKE %?% " => $term,
8081
                    " OR description LIKE %?% " => $term,
8082
                    " OR id IN (
8083
                    SELECT item_id
8084
                    FROM $sfvTable v INNER JOIN $extraFieldTable e
8085
                    ON (v.field_id = e.id)
8086
                    WHERE field_value LIKE %?% AND item_type = $extraFieldType
8087
                ) " => $term,
8088
                ],
8089
            ]);
8090
        } else {
8091
            $resultData = Database::select('*', $sTable, [
8092
                'where' => [
8093
                    "title LIKE %?% " => $term,
8094
                    "OR description LIKE %?% " => $term,
8095
                ],
8096
            ]);
8097
8098
            return $resultData;
8099
        }
8100
8101
        foreach ($resultData as $id => &$session) {
8102
            $session['extra'] = self::getFilteredExtraFields($id, $extraFieldsToInclude);
8103
        }
8104
8105
        return $resultData;
8106
    }
8107
8108
    /**
8109
     * @param int   $sessionId
8110
     * @param array $extraFieldsToInclude (empty means all)
8111
     *
8112
     * @return array
8113
     */
8114
    public static function getFilteredExtraFields($sessionId, $extraFieldsToInclude = [])
8115
    {
8116
        $extraData = [];
8117
        $variables = [];
8118
        $variablePlaceHolders = [];
8119
8120
        foreach ($extraFieldsToInclude as $sessionExtraField) {
8121
            $variablePlaceHolders[] = "?";
8122
            $variables[] = Database::escape_string($sessionExtraField);
8123
        }
8124
8125
        $sessionExtraField = new ExtraFieldModel('session');
8126
        $fieldList = $sessionExtraField->get_all(empty($extraFieldsToInclude) ? [] : [
8127
            "variable IN ( ".implode(", ", $variablePlaceHolders)." ) " => $variables,
8128
        ]);
8129
8130
        if (empty($fieldList)) {
8131
            return [];
8132
        }
8133
8134
        $fields = [];
8135
8136
        // Index session fields
8137
        foreach ($fieldList as $field) {
8138
            $fields[$field['id']] = $field['variable'];
8139
        }
8140
8141
        // Get session field values
8142
        $extra = new ExtraFieldValue('session');
8143
        $sessionFieldValueList = [];
8144
        foreach (array_keys($fields) as $fieldId) {
8145
            $sessionFieldValue = $extra->get_values_by_handler_and_field_id($sessionId, $fieldId);
8146
            if (false != $sessionFieldValue) {
8147
                $sessionFieldValueList[$fieldId] = $sessionFieldValue;
8148
            }
8149
        }
8150
8151
        foreach ($sessionFieldValueList as $sessionFieldValue) {
8152
            // Match session field values to session
8153
            if ($sessionFieldValue['item_id'] != $sessionId) {
8154
                continue;
8155
            }
8156
8157
            // Check if session field value is set in session field list
8158
            if (!isset($fields[$sessionFieldValue['field_id']])) {
8159
                continue;
8160
            }
8161
8162
            $extrafieldVariable = $fields[$sessionFieldValue['field_id']];
8163
            $extrafieldValue = $sessionFieldValue['value'];
8164
8165
            $extraData[] = [
8166
                'variable' => $extrafieldVariable,
8167
                'value' => $extrafieldValue,
8168
            ];
8169
        }
8170
8171
        return $extraData;
8172
    }
8173
8174
    /**
8175
     * @param int $sessionId
8176
     *
8177
     * @return bool
8178
     */
8179
    public static function isValidId($sessionId)
8180
    {
8181
        $sessionId = (int) $sessionId;
8182
        if ($sessionId > 0) {
8183
            $rows = Database::select(
8184
                'id',
8185
                Database::get_main_table(TABLE_MAIN_SESSION),
8186
                ['where' => ['id = ?' => $sessionId]]
8187
            );
8188
            if (!empty($rows)) {
8189
                return true;
8190
            }
8191
        }
8192
8193
        return false;
8194
    }
8195
8196
    /**
8197
     * Get list of sessions based on users of a group for a group admin.
8198
     *
8199
     * @param int $userId The user id
8200
     *
8201
     * @return array
8202
     */
8203
    public static function getSessionsFollowedForGroupAdmin($userId)
8204
    {
8205
        $sessionList = [];
8206
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
8207
        $sessionUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8208
        $userGroup = new UserGroupModel();
8209
        $userIdList = $userGroup->getGroupUsersByUser($userId);
8210
8211
        if (empty($userIdList)) {
8212
            return [];
8213
        }
8214
8215
        $sql = "SELECT DISTINCT s.*
8216
                FROM $sessionTable s
8217
                INNER JOIN $sessionUserTable sru
8218
                ON s.id = sru.id_session
8219
                WHERE
8220
                    (sru.id_user IN (".implode(', ', $userIdList).")
8221
                    AND sru.relation_type = ".Session::STUDENT."
8222
                )";
8223
8224
        if (api_is_multiple_url_enabled()) {
8225
            $sessionAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8226
            $accessUrlId = api_get_current_access_url_id();
8227
8228
            if (-1 != $accessUrlId) {
8229
                $sql = "SELECT DISTINCT s.*
8230
                        FROM $sessionTable s
8231
                        INNER JOIN $sessionUserTable sru ON s.id = sru.id_session
8232
                        INNER JOIN $sessionAccessUrlTable srau ON s.id = srau.session_id
8233
                        WHERE
8234
                            srau.access_url_id = $accessUrlId
8235
                            AND (
8236
                                sru.id_user IN (".implode(', ', $userIdList).")
8237
                                AND sru.relation_type = ".Session::STUDENT."
8238
                            )";
8239
            }
8240
        }
8241
8242
        $result = Database::query($sql);
8243
        while ($row = Database::fetch_assoc($result)) {
8244
            $sessionList[] = $row;
8245
        }
8246
8247
        return $sessionList;
8248
    }
8249
8250
    public static function getSessionVisibility(Session $session) : string
8251
    {
8252
        switch ($session->getVisibility()) {
8253
            case 1:
8254
                return get_lang('Read only');
8255
            case 2:
8256
                return get_lang('Visible');
8257
            case 3:
8258
                return api_ucfirst(get_lang('invisible'));
8259
        }
8260
8261
        return '';
8262
    }
8263
8264
    /**
8265
     * Returns a human readable string.
8266
     *
8267
     * @return array
8268
     */
8269
    public static function parseSessionDates(Session $session, bool $showTime = false)
8270
    {
8271
        $displayDates = self::convertSessionDateToString(
8272
            $session->getDisplayStartDate(),
8273
            $session->getDisplayEndDate(),
8274
            $showTime,
8275
            true
8276
        );
8277
        $accessDates = self::convertSessionDateToString(
8278
            $session->getAccessStartDate(),
8279
            $session->getAccessEndDate(),
8280
            $showTime,
8281
            true
8282
        );
8283
8284
        $coachDates = self::convertSessionDateToString(
8285
            $session->getCoachAccessStartDate(),
8286
            $session->getCoachAccessEndDate(),
8287
            $showTime,
8288
            true
8289
        );
8290
8291
        return [
8292
            'access' => $accessDates,
8293
            'display' => $displayDates,
8294
            'coach' => $coachDates,
8295
        ];
8296
    }
8297
8298
    /**
8299
     * @throws Exception
8300
     */
8301
    public static function setForm(FormValidator $form, Session $session = null, $fromSessionId = null): array
8302
    {
8303
        $categoriesList = self::get_all_session_category();
8304
8305
        $categoriesOptions = [
8306
            '0' => get_lang('none'),
8307
        ];
8308
8309
        if (false != $categoriesList) {
8310
            foreach ($categoriesList as $categoryItem) {
8311
                $categoriesOptions[$categoryItem['id']] = $categoryItem['title'];
8312
            }
8313
        }
8314
8315
        // Database Table Definitions
8316
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8317
8318
        $form->addText(
8319
            'title',
8320
            get_lang('Session name'),
8321
            true,
8322
            ['maxlength' => 150, 'aria-label' => get_lang('Session name')]
8323
        );
8324
        $form->addRule('title', get_lang('Session title already exists'), 'callback', 'check_session_name');
8325
8326
        if (!api_is_platform_admin() && api_is_teacher()) {
8327
            $form->addSelectFromCollection(
8328
                'coach_username',
8329
                [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8330
                [api_get_user_entity()],
8331
                [
8332
                    'id' => 'coach_username',
8333
                    'style' => 'width:370px;',
8334
                    'multiple' => true,
8335
                ],
8336
                false,
8337
                'getFullname'
8338
            );
8339
        } else {
8340
            $sql = "SELECT COUNT(1) FROM $tbl_user WHERE active <> ".USER_SOFT_DELETED." AND status = 1";
8341
            $rs = Database::query($sql);
8342
            $countUsers = (int) Database::result($rs, 0, '0');
8343
8344
            if ($countUsers < 1) {
8345
                $orderClause = 'ORDER BY ';
8346
                $orderClause .= api_sort_by_first_name() ? 'firstname, lastname, username' : 'lastname, firstname, username';
8347
8348
                $sql = "SELECT id as user_id, lastname, firstname, username
8349
                        FROM $tbl_user
8350
                        WHERE active <> -1 AND status = '1' ".
8351
                        $orderClause;
8352
8353
                if (api_is_multiple_url_enabled()) {
8354
                    $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
8355
                    $accessUrlId = api_get_current_access_url_id();
8356
                    if (-1 != $accessUrlId) {
8357
                        $sql = "SELECT user.id as user_id, username, lastname, firstname
8358
                        FROM $tbl_user user
8359
                        INNER JOIN $userRelAccessUrlTable url_user
8360
                        ON (url_user.user_id = user.id)
8361
                        WHERE
8362
                            user.active <> -1 AND
8363
                            access_url_id = $accessUrlId AND
8364
                            status = 1 "
8365
                            .$orderClause;
8366
                    }
8367
                }
8368
8369
                $result = Database::query($sql);
8370
                $coachesList = Database::store_result($result);
8371
                $coachesOptions = [];
8372
                foreach ($coachesList as $coachItem) {
8373
                    $coachesOptions[$coachItem['user_id']] =
8374
                        api_get_person_name($coachItem['firstname'], $coachItem['lastname']).' ('.$coachItem['username'].')';
8375
                }
8376
8377
                $form->addSelect(
8378
                    'coach_username',
8379
                    [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8380
                    $coachesOptions,
8381
                    [
8382
                        'id' => 'coach_username',
8383
                        'style' => 'width:370px;',
8384
                        'multiple' => true,
8385
                    ]
8386
                );
8387
            } else {
8388
                $coaches = [];
8389
8390
                if ($session) {
8391
                    foreach ($session->getGeneralCoaches() as $coach) {
8392
                        $coaches[$coach->getId()] = $coach->getFullName();
8393
                    }
8394
                }
8395
8396
                $form->addSelectAjax(
8397
                    'coach_username',
8398
                    [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8399
                    $coaches,
8400
                    [
8401
                        'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_general_coach',
8402
                        'width' => '100%',
8403
                        'id' => 'coach_username',
8404
                        'multiple' => true,
8405
                    ]
8406
                );
8407
            }
8408
        }
8409
8410
        $form->addHtml('<div id="ajax_list_coachs"></div>');
8411
8412
        $form->addButtonAdvancedSettings('advanced_params');
8413
        $form->addElement('html', '<div id="advanced_params_options" style="'.(isset($fromSessionId) ? 'display:block' : 'display:none').'">');
8414
8415
        if (null === $session) {
8416
            $form->addSelectAjax(
8417
                'session_template',
8418
                get_lang('Session template'),
8419
                [],
8420
                [
8421
                    'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_template_session',
8422
                    'id' => 'system_template',
8423
                ]
8424
            );
8425
        }
8426
8427
        if (isset($fromSessionId)) {
8428
            $session = api_get_session_entity($fromSessionId);
8429
        }
8430
        $form->addSelect(
8431
            'session_category',
8432
            get_lang('Sessions categories'),
8433
            $categoriesOptions,
8434
            [
8435
                'id' => 'session_category',
8436
            ]
8437
        );
8438
8439
        $statusList = self::getStatusList();
8440
        $form->addSelect(
8441
            'status',
8442
            get_lang('Session status'),
8443
            $statusList,
8444
            [
8445
                'id' => 'status',
8446
            ]
8447
        );
8448
8449
        $form->addHtmlEditor(
8450
            'description',
8451
            get_lang('Description'),
8452
            false,
8453
            false,
8454
            [
8455
                'ToolbarSet' => 'Minimal',
8456
            ]
8457
        );
8458
8459
        $form->addElement('checkbox', 'show_description', null, get_lang('Show description'));
8460
8461
        $visibilityGroup = [];
8462
        $visibilityGroup[] = $form->createElement(
8463
            'select',
8464
            'session_visibility',
8465
            null,
8466
            [
8467
                SESSION_VISIBLE_READ_ONLY => get_lang('Read only'),
8468
                SESSION_VISIBLE => get_lang('Accessible'),
8469
                SESSION_INVISIBLE => api_ucfirst(get_lang('Not accessible')),
8470
            ],
8471
            []
8472
        );
8473
        $form->addGroup(
8474
            $visibilityGroup,
8475
            'visibility_group',
8476
            get_lang('Visibility after end date'),
8477
            null,
8478
            false
8479
        );
8480
8481
        $options = [
8482
            0 => get_lang('By duration'),
8483
            1 => get_lang('By dates'),
8484
        ];
8485
8486
        $form->addSelect('access', get_lang('Access'), $options, [
8487
            'onchange' => 'accessSwitcher(this.value)',
8488
            'id' => 'access',
8489
        ]);
8490
8491
        $form->addHtml('<div id="duration_div" style="display:none">');
8492
        $form->addElement(
8493
            'number',
8494
            'duration',
8495
            [
8496
                get_lang('Session duration'),
8497
                get_lang("The session duration allows you to set a number of days of access starting from the first access date of the user to the session. This way, you can set a session to 'last for 15 days' instead of starting at a fixed date for all students."),
8498
            ],
8499
            [
8500
                'maxlength' => 50,
8501
            ]
8502
        );
8503
8504
        $form->addHtml('</div>');
8505
        $form->addHtml('<div id="date_fields" style="display:none">');
8506
8507
        // Dates
8508
        $form->addDateTimePicker(
8509
            'access_start_date',
8510
            [get_lang('Access start date'), get_lang('Date on which the session is made available to all')],
8511
            ['id' => 'access_start_date']
8512
        );
8513
8514
        $form->addDateTimePicker(
8515
            'access_end_date',
8516
            [get_lang('Access end date'), get_lang('Date on which the session is closed')],
8517
            ['id' => 'access_end_date']
8518
        );
8519
8520
        $form->addRule(
8521
            ['access_start_date', 'access_end_date'],
8522
            get_lang('Start date must be before the end date'),
8523
            'compare_datetime_text',
8524
            '< allow_empty'
8525
        );
8526
8527
        $form->addDateTimePicker(
8528
            'display_start_date',
8529
            [
8530
                get_lang('Start date to display'),
8531
                get_lang('Date that will be shown in the session information as the date on which the session starts'),
8532
            ],
8533
            ['id' => 'display_start_date']
8534
        );
8535
8536
        $form->addDateTimePicker(
8537
            'display_end_date',
8538
            [
8539
                get_lang('End date to display'),
8540
                get_lang('Date that will be shown in the session information as the date on which the session ends'),
8541
            ],
8542
            ['id' => 'display_end_date']
8543
        );
8544
8545
        $form->addRule(
8546
            ['display_start_date', 'display_end_date'],
8547
            get_lang('Start date must be before the end date'),
8548
            'compare_datetime_text',
8549
            '< allow_empty'
8550
        );
8551
8552
        $form->addDateTimePicker(
8553
            'coach_access_start_date',
8554
            [
8555
                get_lang('Access start date for coaches'),
8556
                get_lang('Date on which the session is made available to coaches, so they can prepare it before the students get connected'),
8557
            ],
8558
            ['id' => 'coach_access_start_date']
8559
        );
8560
8561
        $form->addDateTimePicker(
8562
            'coach_access_end_date',
8563
            [
8564
                get_lang('Access end date for coaches'),
8565
                get_lang('Date on which the session is closed to coaches. The additional delay will allow them to export all relevant tracking information'),
8566
            ],
8567
            ['id' => 'coach_access_end_date']
8568
        );
8569
8570
        $form->addRule(
8571
            ['coach_access_start_date', 'coach_access_end_date'],
8572
            get_lang('Start date must be before the end date'),
8573
            'compare_datetime_text',
8574
            '< allow_empty'
8575
        );
8576
8577
        $form->addElement('html', '</div>');
8578
8579
        $form->addCheckBox(
8580
            'send_subscription_notification',
8581
            get_lang('Send an email when a user being subscribed to session'),
8582
        );
8583
8584
        $form->addCheckBox(
8585
            'notify_boss',
8586
            get_lang('Notify subscription of user to student boss')
8587
        );
8588
8589
        // Picture
8590
        $form->addFile(
8591
            'picture',
8592
            get_lang('Add image'),
8593
            ['id' => 'picture', 'class' => 'picture-form', 'crop_image' => true]
8594
        );
8595
        $allowedPictureTypes = api_get_supported_image_extensions(false);
8596
        $form->addRule('picture', get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowedPictureTypes).')', 'filetype', $allowedPictureTypes);
8597
8598
        if ($session && $session->getImage()) {
8599
            if (isset($fromSessionId)) {
8600
                $imageUrl = self::getSessionPictureUrl($session);
8601
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8602
                $form->addHidden('image_session_template', $imageUrl);
8603
8604
            } else {
8605
                $form->addElement('checkbox', 'delete_picture', null, get_lang('Delete picture'));
8606
                $imageUrl = self::getSessionPictureUrl($session);
8607
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8608
            }
8609
        }
8610
8611
        // Extra fields
8612
        $extra_field = new ExtraFieldModel('session');
8613
        $extra = $extra_field->addElements($form, $session ? $session->getId() : 0, ['image']);
8614
8615
        if ('true' === api_get_setting('session.enable_auto_reinscription')) {
8616
            $form->addElement(
8617
                'text',
8618
                'days_before_finishing_for_reinscription',
8619
                get_lang('Days before finishing for re-enrollment'),
8620
                ['maxlength' => 5]
8621
            );
8622
            $form->addRule(
8623
                'days_before_finishing_for_reinscription',
8624
                get_lang('The field must be empty or a positive integer'),
8625
                'regex',
8626
                '/^\d*$/'
8627
            );
8628
        }
8629
8630
        if ('true' === api_get_setting('session.enable_session_replication')) {
8631
            $form->addElement(
8632
                'text',
8633
                'days_before_finishing_to_create_new_repetition',
8634
                get_lang('Days before finishing automated creation of new repetitions'),
8635
                ['maxlength' => 5]
8636
            );
8637
            $form->addRule(
8638
                'days_before_finishing_to_create_new_repetition',
8639
                get_lang('The field must be empty or a positive integer'),
8640
                'regex',
8641
                '/^\d*$/'
8642
            );
8643
        }
8644
8645
        if ('true' === api_get_setting('session.enable_auto_reinscription') || 'true' === api_get_setting('session.enable_session_replication')) {
8646
            $form->addElement(
8647
                'checkbox',
8648
                'last_repetition',
8649
                get_lang('Last repetition')
8650
            );
8651
8652
            $form->addElement(
8653
                'number',
8654
                'validity_in_days',
8655
                get_lang('Validity (days)'),
8656
                [
8657
                    'min' => 0,
8658
                    'max' => 365,
8659
                    'step' => 1,
8660
                    'placeholder' => get_lang('Number of days'),
8661
                ]
8662
            );
8663
8664
            $form->addRule(
8665
                'validity_in_days',
8666
                get_lang('The field must be a positive integer'),
8667
                'numeric',
8668
                null,
8669
                'client'
8670
            );
8671
        }
8672
8673
        /** @var HTML_QuickForm_select $element */
8674
        $element = $form->createElement(
8675
            'select',
8676
            'parent_id',
8677
            get_lang('Parent session'),
8678
            [],
8679
            ['class' => 'form-control']
8680
        );
8681
8682
        $element->addOption(get_lang('None'), 0, []);
8683
        $sessions = SessionManager::getListOfParentSessions();
8684
        $currentSessionId = $session?->getId();
8685
        foreach ($sessions as $id => $title) {
8686
            if ($id !== $currentSessionId) {
8687
                $attributes = [];
8688
                $element->addOption($title, $id, $attributes);
8689
            }
8690
        }
8691
        $element->setSelected($session?->getParentId() ?? 0);
8692
        $form->addElement($element);
8693
8694
        $form->addElement('html', '</div>');
8695
8696
        $js = $extra['jquery_ready_content'];
8697
8698
        return ['js' => $js];
8699
    }
8700
8701
    /**
8702
     * Saves the session picture.
8703
     *
8704
     * @param int    $sessionId
8705
     * @param array  $file
8706
     * @param string $crop
8707
     *
8708
     * @return false
8709
     */
8710
    public static function updateSessionPicture(
8711
        $sessionId,
8712
        $file,
8713
        string $crop = ''
8714
    ) {
8715
        if (empty($file)) {
8716
            return false;
8717
        }
8718
8719
        $sessionRepo = Container::getSessionRepository();
8720
        $assetRepo = Container::getAssetRepository();
8721
8722
        $asset = (new Asset())
8723
            ->setCategory(Asset::SESSION)
8724
            ->setTitle($file['name'])
8725
        ;
8726
        if (!empty($crop)) {
8727
            $asset->setCrop($crop);
8728
        }
8729
        $asset = $assetRepo->createFromRequest($asset, $file);
8730
8731
        /** @var Session $session */
8732
        $session = $sessionRepo->find($sessionId);
8733
        $session->setImage($asset);
8734
        $sessionRepo->update($session);
8735
    }
8736
8737
    /**
8738
     * Deletes de session picture as asset.
8739
     *
8740
     * @param int $sessionId
8741
     */
8742
    public static function deleteAsset(int $sessionId): void
8743
    {
8744
        $sessionRepo = Container::getSessionRepository();
8745
8746
        /** @var Session $session */
8747
        $session = $sessionRepo->find($sessionId);
8748
        $em = Database::getManager();
8749
        if ($session->hasImage()) {
8750
            $asset = $session->getImage();
8751
            $em->remove($asset);
8752
            $em->flush();
8753
        }
8754
    }
8755
8756
    /**
8757
     * Get the session picture url.
8758
     *
8759
     * @param Session $session
8760
     * @return string
8761
     */
8762
    public static function getSessionPictureUrl(Session $session): string
8763
    {
8764
        $assetRepo = Container::getAssetRepository();
8765
        $imageUrl = $assetRepo->getAssetUrl($session->getImage());
8766
8767
        return $imageUrl;
8768
    }
8769
8770
    /**
8771
     * Gets the number of rows in the session table filtered through the given
8772
     * array of parameters.
8773
     *
8774
     * @param array Array of options/filters/keys
8775
     *
8776
     * @return int The number of rows, or false on wrong param
8777
     * @assert ('a') === false
8778
     */
8779
    public static function get_count_admin_complete($options = [])
8780
    {
8781
        if (!is_array($options)) {
8782
            return false;
8783
        }
8784
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
8785
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
8786
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8787
        $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
8788
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
8789
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8790
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
8791
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8792
8793
        $where = 'WHERE 1 = 1 AND u.active <> -1 ';
8794
8795
        if (api_is_session_admin() &&
8796
            'false' == api_get_setting('allow_session_admins_to_see_all_sessions')
8797
        ) {
8798
            $user_id = api_get_user_id();
8799
            $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
8800
        } else {
8801
            $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
8802
        }
8803
8804
        $extraFieldTables = '';
8805
        if (!empty($options['where'])) {
8806
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
8807
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
8808
8809
            $options['where'] = str_replace(
8810
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
8811
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
8812
                $options['where']
8813
            );
8814
8815
            $options['where'] = str_replace(
8816
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
8817
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
8818
                $options['where']
8819
            );
8820
8821
            if (!empty($options['extra'])) {
8822
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
8823
                $options['where'] = str_replace('AND', 'OR', $options['where']);
8824
8825
                foreach ($options['extra'] as $extra) {
8826
                    $options['where'] = str_replace(
8827
                        $extra['field'],
8828
                        'fv.field_id = '.$extra['id'].' AND fvo.option_value',
8829
                        $options['where']
8830
                    );
8831
                    $extraFieldTables = "$tbl_session_field_values fv, $tbl_session_field_options fvo, ";
8832
                }
8833
            }
8834
            $where .= ' AND '.$options['where'];
8835
        }
8836
8837
        $today = api_get_utc_datetime();
8838
        $query_rows = "SELECT count(*) as total_rows, c.title as course_title, s.title,
8839
                        IF (
8840
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
8841
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
8842
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
8843
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
8844
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
8845
                        , 1, 0) as session_active
8846
                       FROM $extraFieldTables $tbl_session s
8847
                       LEFT JOIN  $tbl_session_category sc
8848
                       ON s.session_category_id = sc.id
8849
                       INNER JOIN $tblSessionRelUser sru
8850
                       ON s.id = sru.session_id
8851
                       INNER JOIN $tbl_user u
8852
                       ON sru.user_id = u.id
8853
                       INNER JOIN $sessionCourseUserTable scu
8854
                       ON s.id = scu.session_id
8855
                       INNER JOIN $courseTable c
8856
                       ON c.id = scu.c_id
8857
                       $where ";
8858
8859
        if (api_is_multiple_url_enabled()) {
8860
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8861
            $access_url_id = api_get_current_access_url_id();
8862
            if (-1 != $access_url_id) {
8863
                $where .= " AND ar.access_url_id = $access_url_id ";
8864
                $query_rows = "SELECT count(*) as total_rows
8865
                               FROM $tbl_session s
8866
                               LEFT JOIN  $tbl_session_category sc
8867
                               ON s.session_category_id = sc.id
8868
                               INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
8869
                               INNER JOIN $tbl_user u
8870
                               ON sru.user_id = u.id
8871
                               INNER JOIN $table_access_url_rel_session ar
8872
                               ON ar.session_id = s.id $where ";
8873
            }
8874
        }
8875
8876
        $result = Database::query($query_rows);
8877
        $num = 0;
8878
        if (Database::num_rows($result)) {
8879
            $rows = Database::fetch_array($result);
8880
            $num = $rows['total_rows'];
8881
        }
8882
8883
        return $num;
8884
    }
8885
8886
    /**
8887
     * @param string $listType
8888
     * @param array  $extraFields
8889
     *
8890
     * @return array
8891
     */
8892
    public static function getGridColumns(
8893
        $listType = 'all',
8894
        $extraFields = [],
8895
        $addExtraFields = true
8896
    ) {
8897
        $showCount = ('true' === api_get_setting('session.session_list_show_count_users'));
8898
        // Column config
8899
        $operators = ['cn', 'nc'];
8900
        $date_operators = ['gt', 'ge', 'lt', 'le'];
8901
8902
        switch ($listType) {
8903
            case 'my_space':
8904
                $columns = [
8905
                    get_lang('Title'),
8906
                    get_lang('Date'),
8907
                    get_lang('Number of courses per session'),
8908
                    get_lang('Number of learners by session'),
8909
                    get_lang('Details'),
8910
                ];
8911
8912
                $columnModel = [
8913
                    ['name' => 'title', 'index' => 'title', 'align' => 'left'],
8914
                    ['name' => 'date', 'index' => 'access_start_date', 'align' => 'left'],
8915
                    [
8916
                        'name' => 'course_per_session',
8917
                        'index' => 'course_per_session',
8918
                        'sortable' => 'false',
8919
                        'search' => 'false',
8920
                    ],
8921
                    [
8922
                        'name' => 'student_per_session',
8923
                        'index' => 'student_per_session',
8924
                        'sortable' => 'false',
8925
                        'search' => 'false',
8926
                    ],
8927
                    [
8928
                        'name' => 'actions',
8929
                        'index' => 'actions',
8930
                        'sortable' => 'false',
8931
                        'search' => 'false',
8932
                    ],
8933
                ];
8934
                break;
8935
            case 'all':
8936
            case 'active':
8937
            case 'close':
8938
                $columns = [
8939
                    '#',
8940
                    get_lang('Title'),
8941
                    get_lang('Category'),
8942
                    get_lang('Start date to display'),
8943
                    get_lang('End date to display'),
8944
                    get_lang('Visibility'),
8945
                ];
8946
8947
                $columnModel = [
8948
                    [
8949
                        'name' => 'id',
8950
                        'index' => 's.id',
8951
                        'hidden' => 'true',
8952
                    ],
8953
                    [
8954
                        'name' => 'title',
8955
                        'index' => 's.title',
8956
                        'width' => '300',
8957
                        'align' => 'left',
8958
                        'search' => 'true',
8959
                        'searchoptions' => ['sopt' => $operators],
8960
                    ],
8961
                    [
8962
                        'name' => 'category_name',
8963
                        'index' => 'category_name',
8964
                        'align' => 'left',
8965
                        'search' => 'true',
8966
                        'searchoptions' => ['sopt' => $operators],
8967
                    ],
8968
                    [
8969
                        'name' => 'display_start_date',
8970
                        'index' => 'display_start_date',
8971
                        'align' => 'left',
8972
                        'width' => '200',
8973
                        'search' => 'true',
8974
                        'searchoptions' => [
8975
                            'dataInit' => 'date_pick_today',
8976
                            'sopt' => $date_operators,
8977
                        ],
8978
                    ],
8979
                    [
8980
                        'name' => 'display_end_date',
8981
                        'index' => 'display_end_date',
8982
                        'align' => 'left',
8983
                        'width' => '200',
8984
                        'search' => 'true',
8985
                        'searchoptions' => [
8986
                            'dataInit' => 'date_pick_one_month',
8987
                            'sopt' => $date_operators,
8988
                        ],
8989
                    ],
8990
                    [
8991
                        'name' => 'visibility',
8992
                        'index' => 'visibility',
8993
                        'align' => 'left',
8994
                        'search' => 'false',
8995
                    ],
8996
                ];
8997
8998
                if ($showCount) {
8999
                    $columns[] = get_lang('Users');
9000
                    $columnModel[] = [
9001
                        'name' => 'users',
9002
                        'index' => 'users',
9003
                        'align' => 'left',
9004
                        'width' => '100',
9005
                        'search' => 'false',
9006
                    ];
9007
9008
                    // ofaj
9009
                    $columns[] = get_lang('Teachers');
9010
                    $columnModel[] = [
9011
                        'name' => 'teachers',
9012
                        'index' => 'teachers',
9013
                        'align' => 'left',
9014
                        'search' => 'false',
9015
                    ];
9016
                }
9017
9018
                $columns[] = get_lang('Session status');
9019
                $list = self::getStatusList();
9020
                $listToString = '';
9021
                foreach ($list as $statusId => $status) {
9022
                    $listToString .= $statusId.':'.$status.';';
9023
                }
9024
9025
                $columnModel[] = [
9026
                    'name' => 'status',
9027
                    'index' => 'status',
9028
                    'align' => 'left',
9029
                    'width' => '120',
9030
                    'search' => 'true',
9031
                    'stype' => 'select',
9032
                    // for the bottom bar
9033
                    'searchoptions' => [
9034
                        'defaultValue' => '1',
9035
                        'value' => $listToString,
9036
                    ],
9037
                ];
9038
9039
                break;
9040
9041
            case 'simple':
9042
                $columns = [
9043
                    '#',
9044
                    get_lang('Title'),
9045
                    get_lang('Category'),
9046
                    get_lang('Start date to display'),
9047
                    get_lang('End date to display'),
9048
                    get_lang('Visibility'),
9049
                ];
9050
9051
                $columnModel = [
9052
                    [
9053
                        'name' => 'id',
9054
                        'index' => 's.id',
9055
                        'hidden' => 'true',
9056
                    ],
9057
                    [
9058
                        'name' => 'title',
9059
                        'index' => 's.title',
9060
                        'width' => '300',
9061
                        'align' => 'left',
9062
                        'search' => 'true',
9063
                        'searchoptions' => ['sopt' => $operators],
9064
                    ],
9065
                    [
9066
                        'name' => 'category_name',
9067
                        'index' => 'category_name',
9068
                        'align' => 'left',
9069
                        'search' => 'true',
9070
                        'searchoptions' => ['sopt' => $operators],
9071
                    ],
9072
                    [
9073
                        'name' => 'display_start_date',
9074
                        'index' => 'display_start_date',
9075
                        'align' => 'left',
9076
                        'width' => '200',
9077
                        'search' => 'true',
9078
                        'searchoptions' => [
9079
                            'dataInit' => 'date_pick_today',
9080
                            'sopt' => $date_operators,
9081
                        ],
9082
                    ],
9083
                    [
9084
                        'name' => 'display_end_date',
9085
                        'index' => 'display_end_date',
9086
                        'align' => 'left',
9087
                        'width' => '200',
9088
                        'search' => 'true',
9089
                        'searchoptions' => [
9090
                            'dataInit' => 'date_pick_one_month',
9091
                            'sopt' => $date_operators,
9092
                        ],
9093
                    ],
9094
                    [
9095
                        'name' => 'visibility',
9096
                        'index' => 'visibility',
9097
                        'align' => 'left',
9098
                        'search' => 'false',
9099
                    ],
9100
                ];
9101
9102
                if ($showCount) {
9103
                    $columns[] = get_lang('Users');
9104
                    $columnModel[] = [
9105
                        'name' => 'users',
9106
                        'index' => 'users',
9107
                        'align' => 'left',
9108
                        'width' => '100',
9109
                        'search' => 'false',
9110
                    ];
9111
9112
                    // ofaj
9113
                    $columns[] = get_lang('Teachers');
9114
                    $columnModel[] = [
9115
                        'name' => 'teachers',
9116
                        'index' => 'teachers',
9117
                        'align' => 'left',
9118
                        'search' => 'false',
9119
                    ];
9120
                }
9121
9122
                $columns[] = get_lang('Session status');
9123
                $list = self::getStatusList();
9124
                $listToString = '';
9125
                foreach ($list as $statusId => $status) {
9126
                    $listToString .= $statusId.':'.$status.';';
9127
                }
9128
9129
                $columnModel[] = ['name' => 'status', 'index' => 'status', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
9130
                    // for the bottom bar
9131
                    'searchoptions' => [
9132
                        'defaultValue' => '1',
9133
                        'value' => $listToString,
9134
                    ],
9135
                ];
9136
9137
                break;
9138
            case 'complete':
9139
                $columns = [
9140
                    get_lang('Title'),
9141
                    get_lang('Start date to display'),
9142
                    get_lang('End date to display'),
9143
                    get_lang('Coach'),
9144
                    get_lang('Status'),
9145
                    get_lang('Visibility'),
9146
                    get_lang('Course title'),
9147
                ];
9148
                $columnModel = [
9149
                    [
9150
                        'name' => 'title',
9151
                        'index' => 's.title',
9152
                        'width' => '300',
9153
                        'align' => 'left',
9154
                        'search' => 'true',
9155
                        'searchoptions' => ['sopt' => $operators],
9156
                    ],
9157
                    [
9158
                        'name' => 'display_start_date',
9159
                        'index' => 'display_start_date',
9160
                        'align' => 'left',
9161
                        'width' => '200',
9162
                        'search' => 'true',
9163
                        'searchoptions' => ['dataInit' => 'date_pick_today', 'sopt' => $date_operators],
9164
                    ],
9165
                    [
9166
                        'name' => 'display_end_date',
9167
                        'index' => 'display_end_date',
9168
                        'width' => '200',
9169
                        'align' => 'left',
9170
                        'search' => 'true',
9171
                        'searchoptions' => ['dataInit' => 'date_pick_one_month', 'sopt' => $date_operators],
9172
                    ],
9173
                    [
9174
                        'name' => 'coach_name',
9175
                        'index' => 'coach_name',
9176
                        'align' => 'left',
9177
                        'search' => 'false',
9178
                        'searchoptions' => ['sopt' => $operators],
9179
                    ],
9180
                    [
9181
                        'name' => 'session_active',
9182
                        'index' => 'session_active',
9183
                        'align' => 'left',
9184
                        'search' => 'true',
9185
                        'stype' => 'select',
9186
                        // for the bottom bar
9187
                        'searchoptions' => [
9188
                            'defaultValue' => '1',
9189
                            'value' => '1:'.get_lang('Active').';0:'.get_lang('Inactive'),
9190
                        ],
9191
                        // for the top bar
9192
                        'editoptions' => [
9193
                            'value' => '" ":'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang(
9194
                                    'Inactive'
9195
                                ),
9196
                        ],
9197
                    ],
9198
                    [
9199
                        'name' => 'visibility',
9200
                        'index' => 'visibility',
9201
                        'align' => 'left',
9202
                        'search' => 'false',
9203
                    ],
9204
                    [
9205
                        'name' => 'course_title',
9206
                        'index' => 'course_title',
9207
                        'hidden' => 'true',
9208
                        'search' => 'true',
9209
                        'searchoptions' => ['searchhidden' => 'true', 'sopt' => $operators],
9210
                    ],
9211
                ];
9212
9213
                break;
9214
            case 'replication':
9215
            case 'custom':
9216
                $columns = [
9217
                    '#',
9218
                    get_lang('Title'),
9219
                    get_lang('Category'),
9220
                    get_lang('Start date to display'),
9221
                    get_lang('End date to display'),
9222
                    get_lang('Visibility'),
9223
                ];
9224
                $columnModel = [
9225
                    [
9226
                        'name' => 'id',
9227
                        'index' => 's.id',
9228
                        'hidden' => 'true',
9229
                    ],
9230
                    [
9231
                        'name' => 'title',
9232
                        'index' => 's.title',
9233
                        'width' => '260px',
9234
                        'width' => '300',
9235
                        'align' => 'left',
9236
                        'search' => 'true',
9237
                        'searchoptions' => ['sopt' => $operators],
9238
                    ],
9239
                    [
9240
                        'name' => 'category_name',
9241
                        'index' => 'category_name',
9242
                        'align' => 'left',
9243
                        'search' => 'true',
9244
                        'searchoptions' => ['sopt' => $operators],
9245
                    ],
9246
                    [
9247
                        'name' => 'display_start_date',
9248
                        'index' => 'display_start_date',
9249
                        'align' => 'left',
9250
                        'width' => '200',
9251
                        'search' => 'true',
9252
                        'searchoptions' => [
9253
                            'dataInit' => 'date_pick_today',
9254
                            'sopt' => $date_operators,
9255
                        ],
9256
                    ],
9257
                    [
9258
                        'name' => 'display_end_date',
9259
                        'index' => 'display_end_date',
9260
                        'align' => 'left',
9261
                        'width' => '200',
9262
                        'search' => 'true',
9263
                        'searchoptions' => [
9264
                            'dataInit' => 'date_pick_one_month',
9265
                            'sopt' => $date_operators,
9266
                        ],
9267
                    ],
9268
                    [
9269
                        'name' => 'visibility',
9270
                        'index' => 'visibility',
9271
                        'align' => 'left',
9272
                        'search' => 'false',
9273
                    ],
9274
                ];
9275
9276
                if ($showCount) {
9277
                    $columns[] = get_lang('Users');
9278
                    $columnModel[] = [
9279
                        'name' => 'users',
9280
                        'index' => 'users',
9281
                        'align' => 'left',
9282
                        'width' => '100',
9283
                        'search' => 'false',
9284
                    ];
9285
9286
                    // ofaj
9287
                    $columns[] = get_lang('Teachers');
9288
                    $columnModel[] = [
9289
                        'name' => 'teachers',
9290
                        'index' => 'teachers',
9291
                        'align' => 'left',
9292
                        'search' => 'false',
9293
                    ];
9294
                }
9295
9296
                $columns[] = get_lang('Session status');
9297
                $list = self::getStatusList();
9298
                $listToString = '';
9299
                foreach ($list as $statusId => $status) {
9300
                    $listToString .= $statusId.':'.$status.';';
9301
                }
9302
9303
                $columnModel[] = [
9304
                    'name' => 'status',
9305
                    'index' => 'status',
9306
                    'align' => 'left',
9307
                    'width' => '120',
9308
                    'search' => 'true',
9309
                    'stype' => 'select',
9310
                    // for the bottom bar
9311
                    'searchoptions' => [
9312
                        'defaultValue' => '1',
9313
                        'value' => $listToString,
9314
                    ],
9315
                ];
9316
9317
                break;
9318
        }
9319
9320
        if (!empty($extraFields)) {
9321
            foreach ($extraFields as $field) {
9322
                $columns[] = $field['display_text'];
9323
                $columnModel[] = [
9324
                    'name' => $field['variable'],
9325
                    'index' => $field['variable'],
9326
                    'align' => 'center',
9327
                    'search' => 'false',
9328
                ];
9329
            }
9330
        }
9331
9332
        // Inject extra session fields
9333
        $rules = [];
9334
        if ($addExtraFields) {
9335
            $sessionField = new ExtraFieldModel('session');
9336
            $rules = $sessionField->getRules($columns, $columnModel);
9337
        }
9338
9339
        if (!in_array('actions', array_column($columnModel, 'name'))) {
9340
            $columnModel[] = [
9341
                'name' => 'actions',
9342
                'index' => 'actions',
9343
                'align' => 'left',
9344
                'formatter' => 'action_formatter',
9345
                'sortable' => 'false',
9346
                'search' => 'false',
9347
            ];
9348
            $columns[] = get_lang('Actions');
9349
        }
9350
9351
        $columnName = [];
9352
        foreach ($columnModel as $col) {
9353
            $columnName[] = $col['name'];
9354
        }
9355
9356
        $return = [
9357
            'columns' => $columns,
9358
            'column_model' => $columnModel,
9359
            'rules' => $rules,
9360
            'simple_column_name' => $columnName,
9361
        ];
9362
9363
        return $return;
9364
    }
9365
9366
    /**
9367
     * Converts all dates sent through the param array (given form) to correct dates with timezones.
9368
     *
9369
     * @param array The dates The same array, with times converted
9370
     * @param bool $applyFormat Whether apply the DATE_TIME_FORMAT_SHORT format for sessions
9371
     *
9372
     * @return array The same array, with times converted
9373
     */
9374
    public static function convert_dates_to_local($params, $applyFormat = false)
9375
    {
9376
        if (!is_array($params)) {
9377
            return false;
9378
        }
9379
        $params['display_start_date'] = api_get_local_time($params['display_start_date'], null, null, true);
9380
        $params['display_end_date'] = api_get_local_time($params['display_end_date'], null, null, true);
9381
9382
        $params['access_start_date'] = api_get_local_time($params['access_start_date'], null, null, true);
9383
        $params['access_end_date'] = api_get_local_time($params['access_end_date'], null, null, true);
9384
9385
        $params['coach_access_start_date'] = isset($params['coach_access_start_date']) ? api_get_local_time($params['coach_access_start_date'], null, null, true) : null;
9386
        $params['coach_access_end_date'] = isset($params['coach_access_end_date']) ? api_get_local_time($params['coach_access_end_date'], null, null, true) : null;
9387
9388
        if ($applyFormat) {
9389
            if (isset($params['display_start_date'])) {
9390
                $params['display_start_date'] = api_format_date($params['display_start_date'], DATE_TIME_FORMAT_SHORT);
9391
            }
9392
9393
            if (isset($params['display_end_date'])) {
9394
                $params['display_end_date'] = api_format_date($params['display_end_date'], DATE_TIME_FORMAT_SHORT);
9395
            }
9396
9397
            if (isset($params['access_start_date'])) {
9398
                $params['access_start_date'] = api_format_date($params['access_start_date'], DATE_TIME_FORMAT_SHORT);
9399
            }
9400
9401
            if (isset($params['access_end_date'])) {
9402
                $params['access_end_date'] = api_format_date($params['access_end_date'], DATE_TIME_FORMAT_SHORT);
9403
            }
9404
9405
            if (isset($params['coach_access_start_date'])) {
9406
                $params['coach_access_start_date'] = api_format_date($params['coach_access_start_date'], DATE_TIME_FORMAT_SHORT);
9407
            }
9408
9409
            if (isset($params['coach_access_end_date'])) {
9410
                $params['coach_access_end_date'] = api_format_date($params['coach_access_end_date'], DATE_TIME_FORMAT_SHORT);
9411
            }
9412
        }
9413
9414
        return $params;
9415
    }
9416
9417
    /**
9418
     * Gets the admin session list callback of the session/session_list.php
9419
     * page with all user/details in the right fomat.
9420
     *
9421
     * @param array $options
9422
     *
9423
     * @return array Array of rows results
9424
     * @asset ('a') === false
9425
     */
9426
    public static function get_sessions_admin_complete($options = [])
9427
    {
9428
        if (!is_array($options)) {
9429
            return false;
9430
        }
9431
9432
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
9433
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
9434
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
9435
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9436
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
9437
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
9438
9439
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
9440
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
9441
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
9442
9443
        $where = 'WHERE 1 = 1 ';
9444
9445
        if (!api_is_platform_admin()) {
9446
            if (api_is_session_admin() &&
9447
                'false' == api_get_setting('allow_session_admins_to_manage_all_sessions')
9448
            ) {
9449
                $user_id = api_get_user_id();
9450
                $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
9451
            } else {
9452
                $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
9453
            }
9454
        }
9455
9456
        $coach_name = " CONCAT(u.lastname , ' ', u.firstname) as coach_name ";
9457
        if (api_is_western_name_order()) {
9458
            $coach_name = " CONCAT(u.firstname, ' ', u.lastname) as coach_name ";
9459
        }
9460
9461
        $today = api_get_utc_datetime();
9462
        $injectExtraFields = null;
9463
        $extra_fields_info = [];
9464
9465
        //for now only sessions
9466
        $extra_field = new ExtraFieldModel('session');
9467
        $double_fields = [];
9468
        $extra_field_option = new ExtraFieldOption('session');
9469
9470
        if (isset($options['extra'])) {
9471
            $extra_fields = $options['extra'];
9472
            if (!empty($extra_fields)) {
9473
                foreach ($extra_fields as $extra) {
9474
                    $injectExtraFields .= " IF (fv.field_id = {$extra['id']}, fvo.option_display_text, NULL ) as {$extra['field']} , ";
9475
                    if (isset($extra_fields_info[$extra['id']])) {
9476
                        $info = $extra_fields_info[$extra['id']];
9477
                    } else {
9478
                        $info = $extra_field->get($extra['id']);
9479
                        $extra_fields_info[$extra['id']] = $info;
9480
                    }
9481
9482
                    if (ExtraFieldModel::FIELD_TYPE_DOUBLE_SELECT == $info['value_type']) {
9483
                        $double_fields[$info['id']] = $info;
9484
                    }
9485
                }
9486
            }
9487
        }
9488
9489
        $options_by_double = [];
9490
        foreach ($double_fields as $double) {
9491
            $my_options = $extra_field_option->get_field_options_by_field(
9492
                $double['id'],
9493
                true
9494
            );
9495
            $options_by_double['extra_'.$double['field_variable']] = $my_options;
9496
        }
9497
9498
        //sc.title as category_name,
9499
        $select = "
9500
                SELECT * FROM (
9501
                    SELECT DISTINCT
9502
                        IF (
9503
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
9504
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
9505
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
9506
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
9507
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
9508
                        , 1, 0) as session_active,
9509
                s.title,
9510
                s.nbr_courses,
9511
                s.nbr_users,
9512
                s.display_start_date,
9513
                s.display_end_date,
9514
                $coach_name,
9515
                access_start_date,
9516
                access_end_date,
9517
                s.visibility,
9518
                u.id as user_id,
9519
                $injectExtraFields
9520
                c.title as course_title,
9521
                s.id ";
9522
9523
        if (!empty($options['where'])) {
9524
            if (!empty($options['extra'])) {
9525
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
9526
                $options['where'] = str_replace('AND', 'OR', $options['where']);
9527
                foreach ($options['extra'] as $extra) {
9528
                    $options['where'] = str_replace($extra['field'], 'fv.field_id = '.$extra['id'].' AND fvo.option_value', $options['where']);
9529
                }
9530
            }
9531
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
9532
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
9533
            $options['where'] = str_replace(
9534
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
9535
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
9536
                $options['where']
9537
            );
9538
9539
            $options['where'] = str_replace(
9540
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
9541
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
9542
                $options['where']
9543
            );
9544
9545
            $where .= ' AND '.$options['where'];
9546
        }
9547
9548
        $limit = '';
9549
        if (!empty($options['limit'])) {
9550
            $limit = ' LIMIT '.$options['limit'];
9551
        }
9552
9553
        $query = "$select FROM $tbl_session s
9554
                    LEFT JOIN $tbl_session_field_values fv
9555
                    ON (fv.item_id = s.id)
9556
                    LEFT JOIN $extraFieldTable f
9557
                    ON f.id = fv.field_id
9558
                    LEFT JOIN $tbl_session_field_options fvo
9559
                    ON (fv.field_id = fvo.field_id)
9560
                    LEFT JOIN $tbl_session_rel_course src
9561
                    ON (src.session_id = s.id)
9562
                    LEFT JOIN $tbl_course c
9563
                    ON (src.c_id = c.id)
9564
                    LEFT JOIN $tbl_session_category sc
9565
                    ON (s.session_category_id = sc.id)
9566
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9567
                    INNER JOIN $tbl_user u
9568
                    ON sru.user_id = u.id
9569
                    $where
9570
                    $limit
9571
        ";
9572
9573
        if (api_is_multiple_url_enabled()) {
9574
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
9575
            $access_url_id = api_get_current_access_url_id();
9576
            if (-1 != $access_url_id) {
9577
                $query = "$select
9578
                    FROM $tbl_session s
9579
                    LEFT JOIN $tbl_session_field_values fv
9580
                    ON (fv.item_id = s.id)
9581
                    LEFT JOIN $tbl_session_field_options fvo
9582
                    ON (fv.field_id = fvo.field_id)
9583
                    LEFT JOIN $tbl_session_rel_course src
9584
                    ON (src.session_id = s.id)
9585
                    LEFT JOIN $tbl_course c
9586
                    ON (src.c_id = c.id)
9587
                    LEFT JOIN $tbl_session_category sc
9588
                    ON (s.session_category_id = sc.id)
9589
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9590
                    INNER JOIN $tbl_user u
9591
                    ON sru.user_id = u.id
9592
                    INNER JOIN $table_access_url_rel_session ar
9593
                    ON (ar.session_id = s.id AND ar.access_url_id = $access_url_id)
9594
                    $where
9595
                    $limit
9596
                ";
9597
            }
9598
        }
9599
9600
        $query .= ') AS s';
9601
9602
        if (!empty($options['order'])) {
9603
            $query .= ' ORDER BY '.$options['order'];
9604
        }
9605
9606
        $result = Database::query($query);
9607
9608
        $acceptIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
9609
9610
        $errorIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
9611
9612
        $formatted_sessions = [];
9613
        if (Database::num_rows($result)) {
9614
            $sessions = Database::store_result($result, 'ASSOC');
9615
            foreach ($sessions as $session) {
9616
                $session_id = $session['id'];
9617
                $session['title'] = Display::url($session['title'], "resume_session.php?id_session=".$session['id']);
9618
                $session['coach_name'] = Display::url($session['coach_name'], "user_information.php?user_id=".$session['user_id']);
9619
                if (1 == $session['session_active']) {
9620
                    $session['session_active'] = $acceptIcon;
9621
                } else {
9622
                    $session['session_active'] = $errorIcon;
9623
                }
9624
9625
                $session = self::convert_dates_to_local($session);
9626
9627
                switch ($session['visibility']) {
9628
                    case SESSION_VISIBLE_READ_ONLY: //1
9629
                        $session['visibility'] = get_lang('Read only');
9630
                        break;
9631
                    case SESSION_VISIBLE:           //2
9632
                    case SESSION_AVAILABLE:         //4
9633
                        $session['visibility'] = get_lang('Visible');
9634
                        break;
9635
                    case SESSION_INVISIBLE:         //3
9636
                        $session['visibility'] = api_ucfirst(get_lang('invisible'));
9637
                        break;
9638
                }
9639
9640
                // Cleaning double selects
9641
                foreach ($session as $key => &$value) {
9642
                    if (isset($options_by_double[$key]) || isset($options_by_double[$key.'_second'])) {
9643
                        $options = explode('::', $value);
9644
                    }
9645
                    $original_key = $key;
9646
9647
                    if (false === strpos($key, '_second')) {
9648
                    } else {
9649
                        $key = str_replace('_second', '', $key);
9650
                    }
9651
9652
                    if (isset($options_by_double[$key])) {
9653
                        if (isset($options[0])) {
9654
                            if (isset($options_by_double[$key][$options[0]])) {
9655
                                if (false === strpos($original_key, '_second')) {
9656
                                    $value = $options_by_double[$key][$options[0]]['option_display_text'];
9657
                                } else {
9658
                                    $value = $options_by_double[$key][$options[1]]['option_display_text'];
9659
                                }
9660
                            }
9661
                        }
9662
                    }
9663
                }
9664
9665
                // Magic filter
9666
                if (isset($formatted_sessions[$session_id])) {
9667
                    $formatted_sessions[$session_id] = self::compareArraysToMerge(
9668
                        $formatted_sessions[$session_id],
9669
                        $session
9670
                    );
9671
                } else {
9672
                    $formatted_sessions[$session_id] = $session;
9673
                }
9674
            }
9675
        }
9676
9677
        return $formatted_sessions;
9678
    }
9679
9680
    /**
9681
     * Compare two arrays.
9682
     *
9683
     * @param array $array1
9684
     * @param array $array2
9685
     *
9686
     * @return array
9687
     */
9688
    public static function compareArraysToMerge($array1, $array2)
9689
    {
9690
        if (empty($array2)) {
9691
            return $array1;
9692
        }
9693
        foreach ($array1 as $key => $item) {
9694
            if (!isset($array1[$key])) {
9695
                //My string is empty try the other one
9696
                if (isset($array2[$key]) && !empty($array2[$key])) {
9697
                    $array1[$key] = $array2[$key];
9698
                }
9699
            }
9700
        }
9701
9702
        return $array1;
9703
    }
9704
9705
    /**
9706
     * Get link to the admin page for this session.
9707
     *
9708
     * @param int $id Session ID
9709
     *
9710
     * @return mixed URL to the admin page to manage the session, or false on error
9711
     */
9712
    public static function getAdminPath($id)
9713
    {
9714
        $id = (int) $id;
9715
        $session = self::fetch($id);
9716
        if (empty($session)) {
9717
            return false;
9718
        }
9719
9720
        return api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$id;
9721
    }
9722
9723
    /**
9724
     * Get link to the user page for this session.
9725
     * If a course is provided, build the link to the course.
9726
     *
9727
     * @param int $id       Session ID
9728
     * @param int $courseId Course ID (optional) in case the link has to send straight to the course
9729
     *
9730
     * @return mixed URL to the page to use the session, or false on error
9731
     */
9732
    public static function getPath($id, $courseId = 0)
9733
    {
9734
        $id = (int) $id;
9735
        $session = self::fetch($id);
9736
        if (empty($session)) {
9737
            return false;
9738
        }
9739
        if (empty($courseId)) {
9740
            return api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$id;
9741
        } else {
9742
            $courseInfo = api_get_course_info_by_id($courseId);
9743
            if ($courseInfo) {
9744
                return $courseInfo['course_public_url'].'?id_session='.$id;
9745
            }
9746
        }
9747
9748
        return false;
9749
    }
9750
9751
    /**
9752
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9753
     * where course id_course is in sessions id_session1, id_session2
9754
     * for course where user is coach
9755
     * i.e. coach for the course or
9756
     * main coach for a session the course is in
9757
     * for a session category (or woth no session category if empty).
9758
     *
9759
     * @param int $userId
9760
     *
9761
     * @return array
9762
     */
9763
    public static function getSessionCourseForUser($userId)
9764
    {
9765
        // list of COURSES where user is COURSE session coach
9766
        $listCourseCourseCoachSession = self::getCoursesForCourseSessionCoach($userId);
9767
        // list of courses where user is MAIN session coach
9768
        $listCourseMainCoachSession = self::getCoursesForMainSessionCoach($userId);
9769
        // merge these 2 array
9770
        $listResCourseSession = $listCourseCourseCoachSession;
9771
        foreach ($listCourseMainCoachSession as $courseId2 => $listSessionId2) {
9772
            if (isset($listResCourseSession[$courseId2])) {
9773
                // if sessionId array exists for this course
9774
                // same courseId, merge the list of session
9775
                foreach ($listCourseMainCoachSession[$courseId2] as $i => $sessionId2) {
9776
                    if (!in_array($sessionId2, $listResCourseSession[$courseId2])) {
9777
                        $listResCourseSession[$courseId2][] = $sessionId2;
9778
                    }
9779
                }
9780
            } else {
9781
                $listResCourseSession[$courseId2] = $listSessionId2;
9782
            }
9783
        }
9784
9785
        return $listResCourseSession;
9786
    }
9787
9788
    /**
9789
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9790
     * where course id_course is in sessions id_session1, id_session2.
9791
     *
9792
     * @param int $userId
9793
     *
9794
     * @return array
9795
     */
9796
    public static function getCoursesForCourseSessionCoach($userId)
9797
    {
9798
        $userId = (int) $userId;
9799
        $listResCourseSession = [];
9800
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9801
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9802
9803
        $sql = "SELECT session_id, c_id, c.id
9804
                FROM $tblSessionRelCourseRelUser srcru
9805
                LEFT JOIN $tblCourse c
9806
                ON c.id = srcru.c_id
9807
                WHERE
9808
                    srcru.user_id = $userId AND
9809
                    srcru.status = ".Session::COURSE_COACH;
9810
9811
        $res = Database::query($sql);
9812
9813
        while ($data = Database::fetch_assoc($res)) {
9814
            if (api_get_session_visibility($data['session_id'])) {
9815
                if (!isset($listResCourseSession[$data['id']])) {
9816
                    $listResCourseSession[$data['id']] = [];
9817
                }
9818
                $listResCourseSession[$data['id']][] = $data['session_id'];
9819
            }
9820
        }
9821
9822
        return $listResCourseSession;
9823
    }
9824
9825
    /**
9826
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9827
     * where course id_course is in sessions id_session1, id_session2.
9828
     *
9829
     * @param $userId
9830
     *
9831
     * @return array
9832
     */
9833
    public static function getCoursesForMainSessionCoach($userId)
9834
    {
9835
        $userId = (int) $userId;
9836
        $user = api_get_user_entity($userId);
9837
        $listResCourseSession = [];
9838
9839
        $sessions = $user->getSessionsAsGeneralCoach();
9840
9841
        foreach ($sessions as $session) {
9842
            $sessionId = $session->getId();
9843
            $listCoursesInSession = self::getCoursesInSession($sessionId);
9844
            foreach ($listCoursesInSession as $i => $courseId) {
9845
                if (api_get_session_visibility($sessionId)) {
9846
                    if (!isset($listResCourseSession[$courseId])) {
9847
                        $listResCourseSession[$courseId] = [];
9848
                    }
9849
                    $listResCourseSession[$courseId][] = $sessionId;
9850
                }
9851
            }
9852
        }
9853
9854
        return $listResCourseSession;
9855
    }
9856
9857
    /**
9858
     * Return an array of course_id used in session $sessionId.
9859
     *
9860
     * @param $sessionId
9861
     *
9862
     * @return array
9863
     */
9864
    public static function getCoursesInSession($sessionId)
9865
    {
9866
        if (empty($sessionId)) {
9867
            return [];
9868
        }
9869
9870
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9871
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9872
9873
        // list of course in this session
9874
        $sql = "SELECT session_id, c.id
9875
                FROM $tblSessionRelCourse src
9876
                LEFT JOIN $tblCourse c
9877
                ON c.id = src.c_id
9878
                WHERE session_id = ".intval($sessionId);
9879
        $res = Database::query($sql);
9880
9881
        $listResultsCourseId = [];
9882
        while ($data = Database::fetch_assoc($res)) {
9883
            $listResultsCourseId[] = $data['id'];
9884
        }
9885
9886
        return $listResultsCourseId;
9887
    }
9888
9889
    /**
9890
     * Return an array of courses in session for user
9891
     * and for each courses the list of session that use this course for user.
9892
     *
9893
     * [0] => array
9894
     *      userCatId
9895
     *      userCatTitle
9896
     *      courseInUserCatList
9897
     *          [0] => array
9898
     *              courseId
9899
     *              title
9900
     *              courseCode
9901
     *              sessionCatList
9902
     *                  [0] => array
9903
     *                      catSessionId
9904
     *                      catSessionName
9905
     *                      sessionList
9906
     *                          [0] => array
9907
     *                              sessionId
9908
     *                              sessionName
9909
     *
9910
     * @param int $userId
9911
     *
9912
     * @return array
9913
     */
9914
    public static function getNamedSessionCourseForCoach($userId)
9915
    {
9916
        $listResults = [];
9917
        $listCourseSession = self::getSessionCourseForUser($userId);
9918
        foreach ($listCourseSession as $courseId => $listSessionId) {
9919
            // Course info
9920
            $courseInfo = api_get_course_info_by_id($courseId);
9921
            $listOneCourse = [];
9922
            $listOneCourse['courseId'] = $courseId;
9923
            $listOneCourse['title'] = $courseInfo['title'];
9924
            //$listOneCourse['courseCode'] = $courseInfo['code'];
9925
            $listOneCourse['course'] = $courseInfo;
9926
            $listOneCourse['sessionCatList'] = [];
9927
            $listCat = [];
9928
            foreach ($listSessionId as $i => $sessionId) {
9929
                // here we got all session for this course
9930
                // lets check there session categories
9931
                $sessionInfo = self::fetch($sessionId);
9932
                $catId = $sessionInfo['session_category_id'];
9933
                if (!isset($listCat[$catId])) {
9934
                    $listCatInfo = self::get_session_category($catId);
9935
                    if ($listCatInfo) {
9936
                        $listCat[$catId] = [];
9937
                        $listCat[$catId]['catSessionId'] = $catId;
9938
                        $listCat[$catId]['catSessionName'] = $listCatInfo['title'];
9939
                        $listCat[$catId]['sessionList'] = [];
9940
                    }
9941
                }
9942
                $listSessionInfo = self::fetch($sessionId);
9943
                $listSessionIdName = [
9944
                    'sessionId' => $sessionId,
9945
                    'sessionName' => $listSessionInfo['title'],
9946
                ];
9947
                $listCat[$catId]['sessionList'][] = $listSessionIdName;
9948
            }
9949
            // sort $listCat by catSessionName
9950
            usort($listCat, 'self::compareBySessionName');
9951
            // in each catSession sort sessionList by sessionName
9952
            foreach ($listCat as $i => $listCatSessionInfo) {
9953
                $listSessionList = $listCatSessionInfo['sessionList'];
9954
                usort($listSessionList, 'self::compareCatSessionInfo');
9955
                $listCat[$i]['sessionList'] = $listSessionList;
9956
            }
9957
9958
            $listOneCourse['sessionCatList'] = $listCat;
9959
            //$listResults[$userCatId]['courseInUserCatList'][] = $listOneCourse;
9960
        }
9961
9962
        // sort by user course cat
9963
        uasort($listResults, 'self::compareByUserCourseCat');
9964
9965
        // sort by course title
9966
        foreach ($listResults as $userCourseCatId => $tabCoursesInCat) {
9967
            $courseInUserCatList = $tabCoursesInCat['courseInUserCatList'];
9968
            uasort($courseInUserCatList, 'self::compareByCourse');
9969
            $listResults[$userCourseCatId]['courseInUserCatList'] = $courseInUserCatList;
9970
        }
9971
9972
        return $listResults;
9973
    }
9974
9975
    /**
9976
     * @param int $userId
9977
     * @param int $courseId
9978
     *
9979
     * @return array
9980
     */
9981
    public static function searchCourseInSessionsFromUser($userId, $courseId)
9982
    {
9983
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9984
        $userId = (int) $userId;
9985
        $courseId = (int) $courseId;
9986
        if (empty($userId) || empty($courseId)) {
9987
            return [];
9988
        }
9989
9990
        $sql = "SELECT * FROM $table
9991
                WHERE c_id = $courseId AND user_id = $userId";
9992
        $result = Database::query($sql);
9993
9994
        return Database::store_result($result, 'ASSOC');
9995
    }
9996
9997
    /**
9998
     * Subscribe and redirect to session after inscription.
9999
     */
10000
    public static function redirectToSession()
10001
    {
10002
        $sessionId = (int) ChamiloSession::read('session_redirect');
10003
        $onlyOneCourseSessionToRedirect = ChamiloSession::read('only_one_course_session_redirect');
10004
        if ($sessionId) {
10005
            $sessionInfo = api_get_session_info($sessionId);
10006
            if (!empty($sessionInfo)) {
10007
                $userId = api_get_user_id();
10008
                $response = self::isUserSubscribedAsStudent($sessionId, $userId);
10009
                if ($response) {
10010
                    $urlToRedirect = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
10011
                    if (!empty($onlyOneCourseSessionToRedirect)) {
10012
                        $urlToRedirect = api_get_path(WEB_PATH).
10013
                            'courses/'.$onlyOneCourseSessionToRedirect.'/index.php?id_session='.$sessionId;
10014
                    }
10015
10016
                    header('Location: '.$urlToRedirect);
10017
                    exit;
10018
                }
10019
            }
10020
        }
10021
    }
10022
10023
    /**
10024
     * @return int
10025
     */
10026
    public static function getCountUsersInCourseSession(Course $course, Session $session)
10027
    {
10028
        $url = api_get_url_entity(api_get_current_access_url_id());
10029
10030
        return Database::getManager()
10031
            ->createQuery("
10032
                SELECT COUNT(scu)
10033
                FROM ChamiloCoreBundle:SessionRelCourseRelUser scu
10034
                INNER JOIN ChamiloCoreBundle:SessionRelUser su
10035
                    WITH scu.user = su.user
10036
                    AND scu.session = su.session
10037
                INNER JOIN ChamiloCoreBundle:AccessUrlRelUser a
10038
                    WITH a.user = su.user
10039
                WHERE
10040
                    scu.course = :course AND
10041
                    su.relationType <> :relationType AND
10042
                    scu.session = :session AND
10043
                    a.url = :url
10044
            ")
10045
            ->setParameters([
10046
                'course' => $course->getId(),
10047
                'relationType' => Session::DRH,
10048
                'session' => $session->getId(),
10049
                'url' => $url,
10050
            ])
10051
            ->getSingleScalarResult();
10052
    }
10053
10054
    /**
10055
     * Get course IDs where user in not subscribed in session.
10056
     *
10057
     * @return array
10058
     */
10059
    public static function getAvoidedCoursesInSession(User $user, Session $session)
10060
    {
10061
        $courseIds = [];
10062
10063
        /** @var SessionRelCourse $sessionCourse */
10064
        foreach ($session->getCourses() as $sessionCourse) {
10065
            /** @var Course $course */
10066
            $course = $sessionCourse->getCourse();
10067
10068
            if ($session->getUserInCourse($user, $course)->count()) {
10069
                continue;
10070
            }
10071
10072
            $courseIds[] = $course->getId();
10073
        }
10074
10075
        return $courseIds;
10076
    }
10077
10078
    /**
10079
     * @param int             $userId
10080
     * @param int             $sessionId
10081
     * @param ExtraFieldValue $extraFieldValue
10082
     * @param string          $collapsableLink
10083
     *
10084
     * @return array
10085
     */
10086
    public static function getCollapsableData($userId, $sessionId, $extraFieldValue, $collapsableLink)
10087
    {
10088
        $collapsed = 0;
10089
10090
        // Get default collapsed value in extra field
10091
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($sessionId, 'collapsed');
10092
        if (!empty($value) && isset($value['value'])) {
10093
            $collapsed = $value['value'];
10094
        }
10095
10096
        $userRelSession = self::getUserSession($userId, $sessionId);
10097
10098
        if ($userRelSession) {
10099
            if (isset($userRelSession['collapsed']) && '' != $userRelSession['collapsed']) {
10100
                $collapsed = $userRelSession['collapsed'];
10101
            }
10102
        } else {
10103
            return ['collapsed' => $collapsed, 'collapsable_link' => '&nbsp;'];
10104
        }
10105
10106
        $link = $collapsableLink.'&session_id='.$sessionId.'&value=1';
10107
        $image = '<i class="fa fa-folder-open"></i>';
10108
        if (1 == $collapsed) {
10109
            $link = $collapsableLink.'&session_id='.$sessionId.'&value=0';
10110
            $image = '<i class="fa fa-folder"></i>';
10111
        }
10112
10113
        $link = Display::url(
10114
            $image,
10115
            $link
10116
        );
10117
10118
        return ['collapsed' => $collapsed, 'collapsable_link' => $link];
10119
    }
10120
10121
    /**
10122
     * Converts "start date" and "end date" to "From start date to end date" string.
10123
     *
10124
     * @param string|DateTime $startDate
10125
     * @param string|DateTime $endDate
10126
     * @param bool   $showTime
10127
     * @param bool   $dateHuman
10128
     *
10129
     * @return string
10130
     */
10131
    public static function convertSessionDateToString($startDate, $endDate, $showTime, $dateHuman)
10132
    {
10133
        // api_get_local_time returns empty if date is invalid like 0000-00-00 00:00:00
10134
        $startDateToLocal = api_get_local_time(
10135
            $startDate,
10136
            null,
10137
            null,
10138
            true,
10139
            $showTime,
10140
            $dateHuman
10141
        );
10142
        $endDateToLocal = api_get_local_time(
10143
            $endDate,
10144
            null,
10145
            null,
10146
            true,
10147
            $showTime,
10148
            $dateHuman
10149
        );
10150
10151
        $format = $showTime ? DATE_TIME_FORMAT_LONG_24H : DATE_FORMAT_LONG_NO_DAY;
10152
10153
        $result = '';
10154
        if (!empty($startDateToLocal) && !empty($endDateToLocal)) {
10155
            $result = sprintf(
10156
                get_lang('From %s to %s'),
10157
                api_format_date($startDateToLocal, $format),
10158
                api_format_date($endDateToLocal, $format)
10159
            );
10160
        } else {
10161
            if (!empty($startDateToLocal)) {
10162
                $result = get_lang('From').' '.api_format_date($startDateToLocal, $format);
10163
            }
10164
            if (!empty($endDateToLocal)) {
10165
                $result = get_lang('Until').' '.api_format_date($endDateToLocal, $format);
10166
            }
10167
        }
10168
        if (empty($result)) {
10169
            $result = get_lang('No time limits');
10170
        }
10171
10172
        return $result;
10173
    }
10174
10175
    /**
10176
     * @param int $id
10177
     */
10178
    public static function getSessionChangeUserReason($id): string
10179
    {
10180
        $reasons = self::getSessionChangeUserReasons();
10181
10182
        return $reasons[$id] ?? '';
10183
    }
10184
10185
    public static function getSessionChangeUserReasons(): array
10186
    {
10187
        return [
10188
            self::SESSION_CHANGE_USER_REASON_SCHEDULE => get_lang('Schedule changed'),
10189
            self::SESSION_CHANGE_USER_REASON_CLASSROOM => get_lang('Classroom changed'),
10190
            self::SESSION_CHANGE_USER_REASON_LOCATION => get_lang('Location changed'),
10191
            //self::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION => get_lang('Enrollment cancelled'),
10192
        ];
10193
    }
10194
10195
    public static function getStatusList()
10196
    {
10197
        return [
10198
            self::STATUS_PLANNED => get_lang('Planned'),
10199
            self::STATUS_PROGRESS => get_lang('In progress'),
10200
            self::STATUS_FINISHED => get_lang('Finished'),
10201
            self::STATUS_CANCELLED => get_lang('Cancelled'),
10202
        ];
10203
    }
10204
10205
    public static function getStatusLabel($status)
10206
    {
10207
        $list = self::getStatusList();
10208
10209
        if (!isset($list[$status])) {
10210
            return get_lang('No status');
10211
        }
10212
10213
        return $list[$status];
10214
    }
10215
10216
    public static function getDefaultSessionTab()
10217
    {
10218
        $default = 'all';
10219
        $view = api_get_setting('session.default_session_list_view');
10220
10221
        if ('false' !== $view && !empty($view)) {
10222
            $default = $view;
10223
        }
10224
10225
        return $default;
10226
    }
10227
10228
    /**
10229
     * @return string
10230
     */
10231
    public static function getSessionListTabs($listType): string
10232
    {
10233
        $tabs = [
10234
            [
10235
                'content' => get_lang('All sessions'),
10236
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=all',
10237
            ],
10238
            [
10239
                'content' => get_lang('Active sessions'),
10240
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=active',
10241
            ],
10242
            [
10243
                'content' => get_lang('Closed sessions'),
10244
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=close',
10245
            ],
10246
            [
10247
                'content' => get_lang('Custom list'),
10248
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=custom',
10249
            ],
10250
            [
10251
                'content' => get_lang('Replication'),
10252
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=replication',
10253
            ],
10254
        ];
10255
        $default = null;
10256
        switch ($listType) {
10257
            case 'all':
10258
                $default = 1;
10259
                break;
10260
            case 'active':
10261
                $default = 2;
10262
                break;
10263
            case 'close':
10264
                $default = 3;
10265
                break;
10266
            case 'custom':
10267
                $default = 4;
10268
                break;
10269
            case 'replication':
10270
                $default = 5;
10271
                break;
10272
        }
10273
10274
        return Display::tabsOnlyLink($tabs, $default);
10275
    }
10276
10277
    /**
10278
     * Check if a session is followed by human resources manager.
10279
     *
10280
     * @param int $sessionId
10281
     * @param int $userId
10282
     *
10283
     * @return bool
10284
     */
10285
    public static function isSessionFollowedByDrh($sessionId, $userId)
10286
    {
10287
        $userId = (int) $userId;
10288
        $sessionId = (int) $sessionId;
10289
10290
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
10291
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
10292
10293
        if (api_is_multiple_url_enabled()) {
10294
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
10295
10296
            $sql = "SELECT s.id FROM $tblSession s
10297
                INNER JOIN $tblSessionRelUser sru ON (sru.session_id = s.id)
10298
                LEFT JOIN $tblSessionRelAccessUrl a ON (s.id = a.session_id)
10299
                WHERE
10300
                    sru.user_id = '$userId' AND
10301
                    sru.session_id = '$sessionId' AND
10302
                    sru.relation_type = '".Session::DRH."' AND
10303
                    access_url_id = ".api_get_current_access_url_id();
10304
        } else {
10305
            $sql = "SELECT s.id FROM $tblSession s
10306
                INNER JOIN $tblSessionRelUser sru ON sru.session_id = s.id
10307
                WHERE
10308
                    sru.user_id = '$userId' AND
10309
                    sru.session_id = '$sessionId' AND
10310
                    sru.relation_type = '".Session::DRH."'";
10311
        }
10312
10313
        $result = Database::query($sql);
10314
10315
        return Database::num_rows($result) > 0;
10316
    }
10317
10318
    /**
10319
     * Add a warning message when session is read-only mode.
10320
     */
10321
    public static function addFlashSessionReadOnly()
10322
    {
10323
        if (api_get_session_id() && !api_is_allowed_to_session_edit()) {
10324
            Display::addFlash(
10325
                Display::return_message(get_lang('The session is read only'), 'warning')
10326
            );
10327
        }
10328
    }
10329
10330
    public static function insertUsersInCourses(array $studentIds, array $courseIds, int $sessionId)
10331
    {
10332
        $session = api_get_session_entity($sessionId);
10333
10334
        foreach ($courseIds as $courseId) {
10335
            self::insertUsersInCourse($studentIds, $courseId, $sessionId, [], false);
10336
        }
10337
10338
        foreach ($studentIds as $studentId) {
10339
            $user = api_get_user_entity($studentId);
10340
10341
            $session->addUserInSession(Session::STUDENT, $user);
10342
        }
10343
    }
10344
10345
    /**
10346
     * @throws \Doctrine\ORM\Exception\ORMException
10347
     */
10348
    public static function insertUsersInCourse(
10349
        array $studentIds,
10350
        int $courseId,
10351
        int $sessionId,
10352
        array $relationInfo = [],
10353
        bool $updateSession = true,
10354
        bool $sendNotification = false
10355
    ) {
10356
        $em = Database::getManager();
10357
        $course = api_get_course_entity($courseId);
10358
        $session = api_get_session_entity($sessionId);
10359
10360
        $relationInfo = array_merge(['visibility' => 0, 'status' => Session::STUDENT], $relationInfo);
10361
10362
        $usersToInsert = [];
10363
        foreach ($studentIds as $studentId) {
10364
            $user = api_get_user_entity($studentId);
10365
            $session->addUserInCourse($relationInfo['status'], $user, $course)
10366
                ->setVisibility($relationInfo['visibility']);
10367
10368
            Event::logUserSubscribedInCourseSession($user, $course, $session);
10369
10370
            if ($updateSession) {
10371
                if (!$session->hasUserInSession($user, Session::STUDENT)) {
10372
                    $session->addUserInSession(Session::STUDENT, $user);
10373
                }
10374
            }
10375
10376
            $usersToInsert[] = $studentId;
10377
        }
10378
10379
        $em->persist($session);
10380
        $em->flush();
10381
10382
        if ($sendNotification && !empty($usersToInsert)) {
10383
            foreach ($usersToInsert as $userId) {
10384
                $user = api_get_user_entity($userId);
10385
                $courseTitle = $course->getTitle();
10386
                $sessionTitle = $session->getTitle();
10387
10388
                $subject = sprintf(get_lang('You have been enrolled in the course %s for the session %s'), $courseTitle, $sessionTitle);
10389
                $message = sprintf(
10390
                    get_lang('Hello %s, you have been enrolled in the course %s for the session %s.'),
10391
                    UserManager::formatUserFullName($user, true),
10392
                    $courseTitle,
10393
                    $sessionTitle
10394
                );
10395
10396
                MessageManager::send_message_simple(
10397
                    $userId,
10398
                    $subject,
10399
                    $message,
10400
                    api_get_user_id(),
10401
                    false,
10402
                    true,
10403
                    false
10404
                );
10405
            }
10406
        }
10407
    }
10408
10409
    public static function getCareersFromSession(int $sessionId): array
10410
    {
10411
        $extraFieldValueSession = new ExtraFieldValue('session');
10412
        $extraFieldValueCareer = new ExtraFieldValue('career');
10413
10414
        $value = $extraFieldValueSession->get_values_by_handler_and_field_variable($sessionId, 'careerid');
10415
        $careers = [];
10416
        if (isset($value['value']) && !empty($value['value'])) {
10417
            $careerList = str_replace(['[', ']'], '', $value['value']);
10418
            $careerList = explode(',', $careerList);
10419
10420
            $careerManager = new Career();
10421
            foreach ($careerList as $career) {
10422
                $careerIdValue = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
10423
                    'external_career_id',
10424
                    $career
10425
                );
10426
                if (isset($careerIdValue['item_id']) && !empty($careerIdValue['item_id'])) {
10427
                    $finalCareerId = $careerIdValue['item_id'];
10428
                    $careerInfo = $careerManager->get($finalCareerId);
10429
                    if (!empty($careerInfo)) {
10430
                        $careers[] = $careerInfo;
10431
                    }
10432
                }
10433
            }
10434
        }
10435
10436
        return $careers;
10437
    }
10438
10439
    public static function getCareerDiagramPerSessionList($sessionList, $userId)
10440
    {
10441
        if (empty($sessionList) || empty($userId)) {
10442
            return '';
10443
        }
10444
10445
        $userId = (int) $userId;
10446
        $content = Display::page_subheader(get_lang('Ongoing training'));
10447
        $content .= '
10448
           <script>
10449
            resizeIframe = function(iFrame) {
10450
                iFrame.height = iFrame.contentWindow.document.body.scrollHeight + 20;
10451
            }
10452
            </script>
10453
        ';
10454
        $careersAdded = [];
10455
        foreach ($sessionList as $sessionId) {
10456
            $visibility = api_get_session_visibility($sessionId, null, false, $userId);
10457
            if (SESSION_AVAILABLE === $visibility) {
10458
                $careerList = self::getCareersFromSession($sessionId);
10459
                if (empty($careerList)) {
10460
                    continue;
10461
                }
10462
                foreach ($careerList as $career) {
10463
                    $careerId = $career['id'];
10464
                    if (!in_array($careerId, $careersAdded)) {
10465
                        $careersAdded[] = $careerId;
10466
                        $careerUrl = api_get_path(WEB_CODE_PATH).'user/career_diagram.php?iframe=1&career_id='.$career['id'].'&user_id='.$userId;
10467
                        $content .= '
10468
                            <iframe
10469
                                onload="resizeIframe(this)"
10470
                                style="width:100%;"
10471
                                border="0"
10472
                                frameborder="0"
10473
                                scrolling="no"
10474
                                src="'.$careerUrl.'"
10475
                            ></iframe>';
10476
                    }
10477
                }
10478
            }
10479
        }
10480
10481
        return $content;
10482
    }
10483
10484
    private static function allowed(?Session $session = null): bool
10485
    {
10486
        if (api_is_platform_admin()) {
10487
            return true;
10488
        }
10489
10490
        if (null === $session) {
10491
            return false;
10492
        }
10493
10494
        $user = api_get_user_entity();
10495
10496
        if (api_is_session_admin() &&
10497
            'true' !== api_get_setting('session.allow_session_admins_to_manage_all_sessions')
10498
        ) {
10499
10500
            if (!$session->hasUserAsSessionAdmin($user)) {
10501
                return false;
10502
            }
10503
        }
10504
10505
        if (api_is_teacher() &&
10506
            'true' === api_get_setting('session.allow_teachers_to_create_sessions')
10507
        ) {
10508
            if (!$session->hasUserAsGeneralCoach($user))  {
10509
                return false;
10510
            }
10511
        }
10512
10513
        return true;
10514
    }
10515
10516
    /**
10517
     * Add classes (by their names) to a session.
10518
     *
10519
     * @param int   $sessionId
10520
     * @param array $classesNames
10521
     * @param bool  $deleteClassSessions Optional. Empty the session list for the usergroup (class)
10522
     */
10523
    private static function addClassesByName($sessionId, $classesNames, $deleteClassSessions = true)
10524
    {
10525
        if (!$classesNames) {
10526
            return;
10527
        }
10528
10529
        $usergroup = new UserGroupModel();
10530
10531
        foreach ($classesNames as $className) {
10532
            if (empty($className)) {
10533
                continue;
10534
            }
10535
10536
            $usergroup->subscribe_sessions_to_usergroup(
10537
                $usergroup->getIdByName($className),
10538
                [$sessionId],
10539
                $deleteClassSessions
10540
            );
10541
        }
10542
    }
10543
10544
    /**
10545
     * @param array $listA
10546
     * @param array $listB
10547
     *
10548
     * @return int
10549
     */
10550
    private static function compareCatSessionInfo($listA, $listB)
10551
    {
10552
        if ($listA['sessionName'] == $listB['sessionName']) {
10553
            return 0;
10554
        } elseif ($listA['sessionName'] > $listB['sessionName']) {
10555
            return 1;
10556
        } else {
10557
            return -1;
10558
        }
10559
    }
10560
10561
    /**
10562
     * @param array $listA
10563
     * @param array $listB
10564
     *
10565
     * @return int
10566
     */
10567
    private static function compareBySessionName($listA, $listB)
10568
    {
10569
        if ('' == $listB['catSessionName']) {
10570
            return -1;
10571
        } elseif ('' == $listA['catSessionName']) {
10572
            return 1;
10573
        } elseif ($listA['catSessionName'] == $listB['catSessionName']) {
10574
            return 0;
10575
        } elseif ($listA['catSessionName'] > $listB['catSessionName']) {
10576
            return 1;
10577
        } else {
10578
            return -1;
10579
        }
10580
    }
10581
10582
    /**
10583
     * @param array $listA
10584
     * @param array $listB
10585
     *
10586
     * @return int
10587
     */
10588
    private static function compareByUserCourseCat($listA, $listB)
10589
    {
10590
        if ($listA['courseInUserCategoryTitle'] == $listB['courseInUserCategoryTitle']) {
10591
            return 0;
10592
        } elseif ($listA['courseInUserCategoryTitle'] > $listB['courseInUserCategoryTitle']) {
10593
            return 1;
10594
        } else {
10595
            return -1;
10596
        }
10597
    }
10598
10599
    /**
10600
     * @param array $listA
10601
     * @param array $listB
10602
     *
10603
     * @return int
10604
     */
10605
    private static function compareByCourse($listA, $listB)
10606
    {
10607
        if ($listA['title'] == $listB['title']) {
10608
            return 0;
10609
        } elseif ($listA['title'] > $listB['title']) {
10610
            return 1;
10611
        } else {
10612
            return -1;
10613
        }
10614
    }
10615
10616
    public static function getGeneralCoachesIdForSession(int $sessionId): array
10617
    {
10618
        return api_get_session_entity($sessionId)
10619
            ->getGeneralCoaches()
10620
            ->map(fn(User $user) => $user->getId())
10621
            ->getValues();
10622
    }
10623
10624
    public static function getGeneralCoachesNamesForSession(int $sessionId): array
10625
    {
10626
        return api_get_session_entity($sessionId)
10627
            ->getGeneralCoaches()
10628
            ->map(fn(User $user) => $user->getFullName())
10629
            ->getValues();
10630
    }
10631
10632
    public static function sessionHasSessionAdmin(int $sessionId, int $userId): bool
10633
    {
10634
        $adminIds = api_get_session_entity($sessionId)
10635
            ->getSessionAdmins()
10636
            ->map(fn(User $user) => $user->getId())
10637
            ->getValues();
10638
10639
        return in_array($userId, $adminIds);
10640
    }
10641
10642
    /**
10643
     * Retrieves all user IDs associated with a session including coaches and students.
10644
     *
10645
     * @param int $sessionId The session ID.
10646
     * @return array An array of user IDs.
10647
     */
10648
    public static function getAllUserIdsInSession(int $sessionId): array
10649
    {
10650
        $users = [];
10651
        $session = api_get_session_entity($sessionId);
10652
        if ($session) {
10653
            $courses = $session->getCourses();
10654
            if (!empty($courses)) {
10655
                foreach ($courses as $sessionRelCourse) {
10656
                    $course = $sessionRelCourse->getCourse();
10657
                    $coachSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::COURSE_COACH);
10658
                    foreach ($coachSubscriptions as $coachSubscription) {
10659
                        $users[]['user_id'] = $coachSubscription->getUser()->getId();
10660
                    }
10661
10662
                    $userCourseSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::STUDENT);
10663
                    foreach ($userCourseSubscriptions as $courseSubscription) {
10664
                        $users[]['user_id'] = $courseSubscription->getUser()->getId();
10665
                    }
10666
10667
                }
10668
            }
10669
10670
            $generalCoachesId = self::getGeneralCoachesIdForSession($sessionId);
10671
            if (!empty($generalCoachesId)) {
10672
                foreach ($generalCoachesId as $generalCoachId) {
10673
                    $users[]['user_id'] = $generalCoachId;
10674
                }
10675
            }
10676
        }
10677
10678
        return $users;
10679
    }
10680
10681
    /**
10682
     * Retrieves a list of parent sessions.
10683
     */
10684
    public static function getListOfParentSessions(): array
10685
    {
10686
        $sessions = [];
10687
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
10688
        $sql = "SELECT id, title FROM $tbl_session ORDER BY title";
10689
        $result = Database::query($sql);
10690
10691
        while ($row = Database::fetch_array($result)) {
10692
            $sessions[$row['id']] = $row['title'];
10693
        }
10694
10695
        return $sessions;
10696
    }
10697
10698
10699
    /**
10700
     * Method to export sessions data as CSV
10701
     */
10702
    public static function exportSessionsAsCSV(array $selectedSessions): void
10703
    {
10704
        $csvData = [];
10705
        $headersGenerated = false;
10706
        $csvHeaders = [];
10707
10708
        foreach ($selectedSessions as $sessionId) {
10709
            $courses = SessionManager::get_course_list_by_session_id($sessionId);
10710
10711
            if (!empty($courses)) {
10712
                foreach ($courses as $course) {
10713
                    $courseCode = $course['course_code'];
10714
                    $courseId = $course['id'];
10715
                    $studentList = CourseManager::get_student_list_from_course_code(
10716
                        $courseCode,
10717
                        true,
10718
                        $sessionId
10719
                    );
10720
10721
                    $userIds = array_keys($studentList);
10722
10723
                    [$generatedHeaders, $csvContent] = self::generateSessionCourseReportData($sessionId, $courseId, $userIds);
10724
10725
                    if (!$headersGenerated) {
10726
                        $csvHeaders = $generatedHeaders;
10727
                        $headersGenerated = true;
10728
                    }
10729
10730
                    foreach ($csvContent as $row) {
10731
                        $csvData[] = $row;
10732
                    }
10733
                }
10734
            }
10735
        }
10736
10737
        if (!empty($csvData)) {
10738
            array_unshift($csvData, $csvHeaders);
10739
            $filename = 'export_session_courses_reports_complete_' . date('Y-m-d_H-i-s') . '.csv';
10740
            Export::arrayToCsvSimple($csvData, $filename);
10741
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10742
        }
10743
    }
10744
10745
    /**
10746
     * Exports session data as a ZIP file with CSVs and sends it for download.
10747
     */
10748
    public static function exportSessionsAsZip(array $sessionList): void
10749
    {
10750
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH) . api_get_unique_id() . '.zip';
10751
        $tempDir = dirname($tempZipFile);
10752
10753
        if (!is_dir($tempDir) || !is_writable($tempDir)) {
10754
            exit("The directory for creating the ZIP file does not exist or lacks write permissions: $tempDir");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10755
        }
10756
10757
        $zip = new \ZipArchive();
10758
        if ($zip->open($tempZipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
10759
            exit("Unable to open the ZIP file for writing: $tempZipFile");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10760
        }
10761
10762
        foreach ($sessionList as $sessionItemId) {
10763
            $courses = SessionManager::get_course_list_by_session_id($sessionItemId);
10764
10765
            if (!empty($courses)) {
10766
                foreach ($courses as $course) {
10767
                    $courseCode = $course['course_code'];
10768
                    $courseId = $course['id'];
10769
                    $studentList = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionItemId);
10770
                    $userIds = array_keys($studentList);
10771
10772
                    [$csvHeaders, $csvContent] = self::generateSessionCourseReportData($sessionItemId, $courseId, $userIds);
10773
                    array_unshift($csvContent, $csvHeaders);
10774
10775
                    $sessionInfo = api_get_session_info($sessionItemId);
10776
                    $courseInfo = api_get_course_info_by_id($courseId);
10777
                    $csvFileName = $sessionInfo['name'] . '_' . $courseInfo['name'] . '.csv';
10778
10779
                    $csvFilePath = Export::arrayToCsvSimple($csvContent, $csvFileName, true);
10780
10781
                    if ($csvFilePath && file_exists($csvFilePath)) {
10782
                        $zip->addFile($csvFilePath, $csvFileName);
10783
                    }
10784
                }
10785
            }
10786
        }
10787
10788
        if (!$zip->close()) {
10789
            exit("Could not close the ZIP file correctly.");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10790
        }
10791
10792
        if (file_exists($tempZipFile)) {
10793
            DocumentManager::file_send_for_download($tempZipFile, true);
10794
            unlink($tempZipFile);
10795
        } else {
10796
            exit("The ZIP file was not created correctly.");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10797
        }
10798
    }
10799
10800
    private static function generateSessionCourseReportData($sessionId, $courseId, $userIds): array
10801
    {
10802
        $em = Database::getManager();
10803
        $sessionRepository = $em->getRepository(Session::class);
10804
        $session = $sessionRepository->find($sessionId);
10805
10806
        if (!$session instanceof Session) {
10807
            throw new \InvalidArgumentException("Invalid session object for session ID $sessionId");
10808
        }
10809
10810
        $courseInfo = api_get_course_info_by_id($courseId);
10811
        $courseCode = $courseInfo['code'];
10812
10813
        $csvHeaders = [
10814
            get_lang('Session name'),
10815
            get_lang('Session access dates'),
10816
            get_lang('Session display dates'),
10817
            get_lang('Course name'),
10818
            get_lang('Official code'),
10819
            get_lang('First name'),
10820
            get_lang('Last name'),
10821
            get_lang('Login'),
10822
            get_lang('Time'),
10823
            get_lang('Course progress'),
10824
            get_lang('Exercise progress'),
10825
            get_lang('Exercise average'),
10826
            get_lang('Score'),
10827
            get_lang('Score') . ' - ' . get_lang('Best attempt'),
10828
            get_lang('Assignments'),
10829
            get_lang('Messages'),
10830
            get_lang('Classes'),
10831
            get_lang('Registration date'),
10832
            get_lang('First access to course'),
10833
            get_lang('Latest access in course'),
10834
        ];
10835
10836
        $csvData = TrackingCourseLog::getUserData(
10837
            null,
10838
            count($userIds),
10839
            null,
10840
            null,
10841
            [],
10842
            true,
10843
            true,
10844
            $courseCode,
10845
            $sessionId,
10846
            true,
10847
            $userIds
10848
        );
10849
10850
        $rawCsvContent = ChamiloSession::read('csv_content');
10851
10852
        if (empty($rawCsvContent)) {
10853
            throw new \RuntimeException("No CSV content found in session for course $courseCode and session $sessionId.");
10854
        }
10855
10856
        $csvContent = [];
10857
        foreach ($rawCsvContent as $row) {
10858
            $alignedRow = [
10859
                $row['session_name'] ?? '',
10860
                $row['session_startdate'] ?? '',
10861
                $row['session_enddate'] ?? '',
10862
                $row['course_name'] ?? '',
10863
                $row['official_code'] ?? '',
10864
                $row['firstname'] ?? '',
10865
                $row['lastname'] ?? '',
10866
                $row['username'] ?? '',
10867
                $row['time'] ?? '',
10868
                $row['average_progress'] ?? '',
10869
                $row['exercise_progress'] ?? '',
10870
                $row['exercise_average'] ?? '',
10871
                $row['student_score'] ?? '',
10872
                $row['student_score_best'] ?? '',
10873
                $row['count_assignments'] ?? '',
10874
                $row['count_messages'] ?? '',
10875
                $row['classes'] ?? '',
10876
                $row['registered_at'] ?? '',
10877
                $row['first_connection'] ?? '',
10878
                $row['last_connection'] ?? '',
10879
            ];
10880
            $csvContent[] = $alignedRow;
10881
        }
10882
10883
        return [$csvHeaders, $csvContent];
10884
    }
10885
}
10886