SessionManager::get_sessions_by_general_coach()   A
last analyzed

Complexity

Conditions 5

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 19
nop 2
dl 0
loc 31
rs 9.3222
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($coachesId)) {
1835
            Display::addFlash(
1836
                Display::return_message(get_lang('You must select a coach'), 'warning')
1837
            );
1838
1839
            return false;
1840
        } elseif (!empty($startDate) &&
1841
            !api_is_valid_date($startDate, 'Y-m-d H:i') &&
1842
            !api_is_valid_date($startDate, 'Y-m-d H:i:s')
1843
        ) {
1844
            Display::addFlash(
1845
                Display::return_message(get_lang('Invalid start date was given.'), 'warning')
1846
            );
1847
1848
            return false;
1849
        } elseif (!empty($endDate) &&
1850
            !api_is_valid_date($endDate, 'Y-m-d H:i') &&
1851
            !api_is_valid_date($endDate, 'Y-m-d H:i:s')
1852
        ) {
1853
            Display::addFlash(
1854
                Display::return_message(get_lang('Invalid end date was given.'), 'warning')
1855
            );
1856
1857
            return false;
1858
        } elseif (!empty($startDate) && !empty($endDate) && $startDate >= $endDate) {
1859
            Display::addFlash(
1860
                Display::return_message(get_lang('The first date should be before the end date'), 'warning')
1861
            );
1862
1863
            return false;
1864
        } else {
1865
            $sessionInfo = self::get_session_by_name($name);
1866
            $exists = false;
1867
            if (!empty($sessionInfo) && (int) $sessionInfo['id'] !== $id) {
1868
                $exists = true;
1869
            }
1870
1871
            if ($exists) {
1872
                Display::addFlash(
1873
                    Display::return_message(get_lang('Session title already exists'), 'warning')
1874
                );
1875
1876
                return false;
1877
            } else {
1878
                $sessionEntity = api_get_session_entity($id);
1879
                $sessionEntity
1880
                    ->setTitle($name)
1881
                    ->setDuration($duration)
1882
                    ->setDescription($description)
1883
                    ->setShowDescription(1 === $showDescription)
1884
                    ->setVisibility($visibility)
1885
                    ->setSendSubscriptionNotification((bool) $sendSubscriptionNotification)
1886
                    ->setNotifyBoss((bool) $notifyBoss)
1887
                    ->setParentId($parentId)
1888
                    ->setDaysToReinscription((int) $daysBeforeFinishingForReinscription)
1889
                    ->setLastRepetition($lastRepetition)
1890
                    ->setDaysToNewRepetition((int) $daysBeforeFinishingToCreateNewRepetition)
1891
                    ->setValidityInDays((int) $validityInDays)
1892
                    ->setAccessStartDate(null)
1893
                    ->setAccessStartDate(null)
1894
                    ->setDisplayStartDate(null)
1895
                    ->setDisplayEndDate(null)
1896
                    ->setCoachAccessStartDate(null)
1897
                    ->setCoachAccessEndDate(null)
1898
                ;
1899
1900
                if ($parentId) {
1901
                    $sessionEntity->setParentId($parentId);
1902
                } else {
1903
                    $sessionEntity->setParentId(null);
1904
                }
1905
1906
                $sessionEntity->setDaysToReinscription($daysBeforeFinishingForReinscription);
1907
                $sessionEntity->setLastRepetition($lastRepetition);
1908
                $sessionEntity->setDaysToNewRepetition($daysBeforeFinishingToCreateNewRepetition);
1909
1910
                $newGeneralCoaches = array_map(
1911
                    fn($coachId) => api_get_user_entity($coachId),
1912
                    $coachesId
1913
                );
1914
                $currentGeneralCoaches = $sessionEntity->getGeneralCoaches();
1915
1916
                foreach ($newGeneralCoaches as $generalCoach) {
1917
                    if (!$sessionEntity->hasUserAsGeneralCoach($generalCoach)) {
1918
                        $sessionEntity->addGeneralCoach($generalCoach);
1919
                    }
1920
                }
1921
1922
                foreach ($currentGeneralCoaches as $generalCoach) {
1923
                    if (!in_array($generalCoach, $newGeneralCoaches, true)) {
1924
                        $sessionEntity->removeGeneralCoach($generalCoach);
1925
                    }
1926
                }
1927
1928
                if (!empty($sessionAdminId)) {
1929
                    $sessionEntity->addSessionAdmin(api_get_user_entity($sessionAdminId));
1930
                }
1931
1932
                if (!empty($startDate)) {
1933
                    $sessionEntity->setAccessStartDate(
1934
                        api_get_utc_datetime($startDate, true, true),
1935
                        true
1936
                    );
1937
                }
1938
1939
                if (!empty($endDate)) {
1940
                    $sessionEntity->setAccessEndDate(
1941
                        api_get_utc_datetime($endDate, true, true),
1942
                        true
1943
                    );
1944
                }
1945
1946
                if (!empty($displayStartDate)) {
1947
                    $sessionEntity->setDisplayStartDate(api_get_utc_datetime($displayStartDate, true, true));
1948
                }
1949
1950
                if (!empty($displayEndDate)) {
1951
                    $sessionEntity->setDisplayEndDate(api_get_utc_datetime($displayEndDate, true, true));
1952
                }
1953
1954
                if (!empty($coachStartDate)) {
1955
                    $sessionEntity->setCoachAccessStartDate(
1956
                        api_get_utc_datetime($coachStartDate, true, true),
1957
                        true,
1958
                        true
1959
                    );
1960
                }
1961
1962
                if (!empty($coachEndDate)) {
1963
                    $sessionEntity->setCoachAccessEndDate(
1964
                        api_get_utc_datetime($coachEndDate, true, true),
1965
                        true,
1966
                        true
1967
                    );
1968
                }
1969
1970
                if (!empty($sessionCategoryId)) {
1971
                    $category = $em->getRepository(SessionCategory::class)->find($sessionCategoryId);
1972
                    $sessionEntity->setCategory($category);
1973
                } else {
1974
                    $sessionEntity->setCategory(null);
1975
                }
1976
                $sessionEntity->setStatus($status);
1977
1978
                $em->flush();
1979
1980
                if (!empty($extraFields)) {
1981
                    $extraFields['item_id'] = $id;
1982
                    $sessionFieldValue = new ExtraFieldValue('session');
1983
                    $sessionFieldValue->saveFieldValues($extraFields);
1984
                }
1985
1986
                return $id;
1987
            }
1988
        }
1989
    }
1990
1991
    /**
1992
     * Delete session.
1993
     *
1994
     * @author Carlos Vargas  from existing code
1995
     *
1996
     * @param array $idChecked an array to delete sessions
1997
     * @param bool  $fromWs    optional, true if the function is called
1998
     *                          by a webservice, false otherwise
1999
     *
2000
     * @return bool
2001
     * */
2002
    public static function delete($idChecked, $fromWs = false)
2003
    {
2004
        $sessionId = null;
2005
        if (is_array($idChecked)) {
2006
            foreach ($idChecked as $sessionId) {
2007
                self::delete($sessionId);
2008
            }
2009
        } else {
2010
            $sessionId = (int) $idChecked;
2011
        }
2012
2013
        if (empty($sessionId)) {
2014
            return false;
2015
        }
2016
2017
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2018
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2019
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2020
        $tblUrlSession = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2021
        $userGroupSessionTable = Database::get_main_table(TABLE_USERGROUP_REL_SESSION);
2022
        $trackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2023
        $trackAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2024
2025
        $ticket = Database::get_main_table(TABLE_TICKET_TICKET);
2026
        $em = Database::getManager();
2027
        $userId = api_get_user_id();
2028
        $user = api_get_user_entity();
2029
2030
        $repo = Container::getSequenceResourceRepository();
2031
        $sequenceResource = $repo->findRequirementForResource(
2032
            $sessionId,
2033
            SequenceResource::SESSION_TYPE
2034
        );
2035
2036
        $sessionEntity = api_get_session_entity($sessionId);
2037
        if (null === $sessionEntity) {
2038
            return false;
2039
        }
2040
2041
        if ($sequenceResource) {
2042
            Display::addFlash(
2043
                Display::return_message(
2044
                    get_lang('There is a sequence resource linked to this session. You must delete this link first.'),
2045
                    'error'
2046
                )
2047
            );
2048
2049
            return false;
2050
        }
2051
2052
        if (self::allowed($sessionEntity) && !$fromWs) {
2053
            if (!$sessionEntity->hasUserAsSessionAdmin($user) && !api_is_platform_admin()) {
2054
                api_not_allowed(true);
2055
            }
2056
        }
2057
2058
        // Delete Picture Session
2059
        SessionManager::deleteAsset($sessionId);
2060
2061
        $sessionName = $sessionEntity->getTitle();
2062
        $em->remove($sessionEntity);
2063
        $em->flush();
2064
2065
        // Delete explicitly from tables not directly related to 'session'
2066
        $tables = [
2067
            'track_e_lastaccess',
2068
            'track_e_default',
2069
            'track_e_exercise_confirmation',
2070
            'track_e_links',
2071
            'track_e_online',
2072
            'track_e_attempt_qualify',
2073
            'track_e_access_complete',
2074
            'track_e_uploads',
2075
            'c_dropbox_file',
2076
            'c_forum_thread_qualify_log',
2077
            'c_dropbox_post',
2078
            'c_survey_answer',
2079
            'c_wiki_mailcue',
2080
            'c_dropbox_category',
2081
            'skill_rel_item',
2082
            'scheduled_announcements',
2083
            'sequence_row_entity',
2084
        ];
2085
2086
        foreach ($tables as $table) {
2087
            Database::delete($table, ['session_id = ?' => $sessionId]);
2088
        }
2089
2090
        // Delete other related tables
2091
        Database::delete($userGroupSessionTable, ['session_id = ?' => $sessionId]);
2092
        Database::delete($tblSessionRelCourse, ['session_id = ?' => $sessionId]);
2093
        Database::delete($tblSessionRelCourseRelUser, ['session_id = ?' => $sessionId]);
2094
        Database::delete($tblSessionRelUser, ['session_id = ?' => $sessionId]);
2095
        Database::delete($tblUrlSession, ['session_id = ?' => $sessionId]);
2096
        Database::delete($trackCourseAccess, ['session_id = ?' => $sessionId]);
2097
        Database::delete($trackAccess, ['session_id = ?' => $sessionId]);
2098
        Database::update($ticket, ['session_id' => null], ['session_id = ?' => $sessionId]);
2099
2100
        $extraFieldValue = new ExtraFieldValue('session');
2101
        $extraFieldValue->deleteValuesByItem($sessionId);
2102
2103
        $repo->deleteSequenceResource($sessionId, SequenceResource::SESSION_TYPE);
2104
2105
        // Add event to system log
2106
        Event::addEvent(
2107
            LOG_SESSION_DELETE,
2108
            LOG_SESSION_ID,
2109
            $sessionName.' - id:'.$sessionId,
2110
            api_get_utc_datetime(),
2111
            $userId
2112
        );
2113
2114
        return true;
2115
    }
2116
2117
    /**
2118
     * @param int $id promotion id
2119
     *
2120
     * @return bool
2121
     */
2122
    public static function clear_session_ref_promotion($id)
2123
    {
2124
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2125
        $id = intval($id);
2126
        $sql = "UPDATE $tbl_session
2127
                SET promotion_id = 0
2128
                WHERE promotion_id = $id";
2129
        if (Database::query($sql)) {
2130
            return true;
2131
        } else {
2132
            return false;
2133
        }
2134
    }
2135
2136
    /**
2137
     * Subscribes students to the given session and optionally (default)
2138
     * unsubscribes previous users.
2139
     *
2140
     * @author Carlos Vargas from existing code
2141
     * @author Julio Montoya. Cleaning code.
2142
     *
2143
     * @param int   $sessionId
2144
     * @param array $userList
2145
     * @param int   $session_visibility
2146
     * @param bool  $empty_users
2147
     * @param bool  $registerUsersToAllCourses
2148
     *
2149
     * @return bool
2150
     */
2151
    public static function subscribeUsersToSession(
2152
        $sessionId,
2153
        $userList,
2154
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2155
        $empty_users = true,
2156
        $registerUsersToAllCourses = true
2157
    ) {
2158
        $sessionId = (int) $sessionId;
2159
2160
        if (empty($sessionId)) {
2161
            return false;
2162
        }
2163
2164
        foreach ($userList as $intUser) {
2165
            if ($intUser != strval(intval($intUser))) {
2166
                return false;
2167
            }
2168
        }
2169
2170
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2171
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2172
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2173
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2174
2175
        $session = api_get_session_entity($sessionId);
2176
2177
        // from function parameter
2178
        if (empty($session_visibility)) {
2179
            $session_visibility = $session->getVisibility();
2180
            //default status loaded if empty
2181
            // by default readonly 1
2182
            if (empty($session_visibility)) {
2183
                $session_visibility = SESSION_VISIBLE_READ_ONLY;
2184
            }
2185
        } elseif (!in_array($session_visibility, [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_INVISIBLE])) {
2186
            $session_visibility = SESSION_VISIBLE_READ_ONLY;
2187
        }
2188
2189
        $sql = "SELECT user_id FROM $tbl_session_rel_course_rel_user
2190
                WHERE session_id = $sessionId AND status = ".Session::STUDENT;
2191
        $result = Database::query($sql);
2192
        $existingUsers = [];
2193
        while ($row = Database::fetch_array($result)) {
2194
            $existingUsers[] = $row['user_id'];
2195
        }
2196
2197
        $sql = "SELECT c_id FROM $tbl_session_rel_course
2198
                WHERE session_id = $sessionId";
2199
        $result = Database::query($sql);
2200
        $course_list = [];
2201
        while ($row = Database::fetch_array($result)) {
2202
            $course_list[] = $row['c_id'];
2203
        }
2204
2205
        if ($session->getSendSubscriptionNotification() && is_array($userList)) {
2206
            foreach ($userList as $user_id) {
2207
                $tplSubject = new Template(
2208
                    null,
2209
                    false,
2210
                    false,
2211
                    false,
2212
                    false,
2213
                    false
2214
                );
2215
                $layoutSubject = $tplSubject->get_template(
2216
                    'mail/subject_subscription_to_session_confirmation.tpl'
2217
                );
2218
                $subject = $tplSubject->fetch($layoutSubject);
2219
                $user_info = api_get_user_info($user_id);
2220
2221
                $tplContent = new Template(
2222
                    null,
2223
                    false,
2224
                    false,
2225
                    false,
2226
                    false,
2227
                    false
2228
                );
2229
                // Variables for default template
2230
                $tplContent->assign('complete_name', stripslashes($user_info['complete_name']));
2231
                $tplContent->assign('session_name', $session->getTitle());
2232
                $tplContent->assign(
2233
                    'session_coaches',
2234
                    $session->getGeneralCoaches()->map(fn(User $coach) => UserManager::formatUserFullName($coach))
2235
                );
2236
                $layoutContent = $tplContent->get_template(
2237
                    'mail/content_subscription_to_session_confirmation.tpl'
2238
                );
2239
                $content = $tplContent->fetch($layoutContent);
2240
2241
                // Send email
2242
                api_mail_html(
2243
                    $user_info['complete_name'],
2244
                    $user_info['mail'],
2245
                    $subject,
2246
                    $content,
2247
                    api_get_person_name(
2248
                        api_get_setting('administratorName'),
2249
                        api_get_setting('administratorSurname')
2250
                    ),
2251
                    api_get_setting('emailAdministrator')
2252
                );
2253
2254
                // Record message in system
2255
                MessageManager::send_message_simple(
2256
                    $user_id,
2257
                    $subject,
2258
                    $content,
2259
                    api_get_user_id(),
2260
                    false,
2261
                    true
2262
                );
2263
            }
2264
        }
2265
2266
        if ($session->getNotifyBoss()) {
2267
            foreach ($userList as $user_id) {
2268
                $studentBossList = UserManager::getStudentBossList($user_id);
2269
2270
                if (!empty($studentBossList)) {
2271
                    $studentBossList = array_column($studentBossList, 'boss_id');
2272
                    foreach ($studentBossList as $bossId) {
2273
                        $boss = api_get_user_entity($bossId);
2274
                        self::notifyBossOfInscription($boss, $session, $user_id);
2275
                    }
2276
                }
2277
            }
2278
        }
2279
2280
        if ($registerUsersToAllCourses) {
2281
            foreach ($course_list as $courseId) {
2282
                // for each course in the session
2283
                $nbr_users = 0;
2284
                $courseId = (int) $courseId;
2285
2286
                $sql = "SELECT DISTINCT user_id
2287
                        FROM $tbl_session_rel_course_rel_user
2288
                        WHERE
2289
                            session_id = $sessionId AND
2290
                            c_id = $courseId AND
2291
                            status = ".Session::STUDENT;
2292
                $result = Database::query($sql);
2293
                $existingUsers = [];
2294
                while ($row = Database::fetch_array($result)) {
2295
                    $existingUsers[] = $row['user_id'];
2296
                }
2297
2298
                // Delete existing users
2299
                if ($empty_users) {
2300
                    foreach ($existingUsers as $existing_user) {
2301
                        if (!in_array($existing_user, $userList)) {
2302
                            self::unSubscribeUserFromCourseSession($existing_user, $courseId, $sessionId);
2303
                        }
2304
                    }
2305
                }
2306
2307
                $usersToSubscribeInCourse = array_filter(
2308
                    $userList,
2309
                    function ($userId) use ($existingUsers) {
2310
                        return !in_array($userId, $existingUsers);
2311
                    }
2312
                );
2313
2314
                self::insertUsersInCourse(
2315
                    $usersToSubscribeInCourse,
2316
                    $courseId,
2317
                    $sessionId,
2318
                    ['visibility' => $session_visibility],
2319
                    false
2320
                );
2321
            }
2322
        }
2323
2324
        // Delete users from the session
2325
        if (true === $empty_users) {
2326
            $sql = "DELETE FROM $tbl_session_rel_user
2327
                    WHERE
2328
                      session_id = $sessionId AND
2329
                      relation_type = ".Session::STUDENT;
2330
            // Don't reset session_rel_user.registered_at of users that will be registered later anyways.
2331
            if (!empty($userList)) {
2332
                $avoidDeleteThisUsers = " AND user_id NOT IN ('".implode("','", $userList)."')";
2333
                $sql .= $avoidDeleteThisUsers;
2334
            }
2335
            Event::addEvent(
2336
                LOG_SESSION_DELETE_USER,
2337
                LOG_USER_ID,
2338
                'all',
2339
                api_get_utc_datetime(),
2340
                api_get_user_id(),
2341
                null,
2342
                $sessionId
2343
            );
2344
            Database::query($sql);
2345
        }
2346
2347
        // Insert missing users into session
2348
        foreach ($userList as $enreg_user) {
2349
            $isUserSubscribed = self::isUserSubscribedAsStudent($sessionId, $enreg_user);
2350
            if (false === $isUserSubscribed) {
2351
                $enreg_user = (int) $enreg_user;
2352
                if ($session->getDuration() > 0) {
2353
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at)
2354
                        VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."')";
2355
                } else {
2356
                    if (null != ($accessStartDate = $session->getAccessStartDate())) {
2357
                        $accessStartDate = "'".$accessStartDate->format('Y-m-d H:i:s')."'";
2358
                    } else {
2359
                        $accessStartDate = "NULL";
2360
                    }
2361
                    if (null != ($accessEndDate = $session->getAccessEndDate())) {
2362
                        $accessEndDate = "'".$accessEndDate->format('Y-m-d H:i:s')."'";
2363
                    } else {
2364
                        $accessEndDate = "NULL";
2365
                    }
2366
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at, access_start_date, access_end_date)
2367
                            VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."', ".$accessStartDate.", ".$accessEndDate.")";
2368
                }
2369
                Database::query($sql);
2370
                Event::addEvent(
2371
                    LOG_SESSION_ADD_USER,
2372
                    LOG_USER_ID,
2373
                    $enreg_user,
2374
                    api_get_utc_datetime(),
2375
                    api_get_user_id(),
2376
                    null,
2377
                    $sessionId
2378
                );
2379
            }
2380
        }
2381
2382
        // update number of users in the session
2383
        $sql = "UPDATE $tbl_session
2384
                SET nbr_users = (SELECT count(user_id) FROM $tbl_session_rel_user WHERE session_id = $sessionId)
2385
                WHERE id = $sessionId";
2386
        Database::query($sql);
2387
2388
        return true;
2389
    }
2390
2391
    /**
2392
     * Sends a notification email to the student's boss when the student is enrolled in a session.
2393
     *
2394
     * @param User $boss The boss of the student to be notified.
2395
     * @param Session $session The session the student has been enrolled in.
2396
     * @param int $userId The ID of the student being enrolled.
2397
     */
2398
    public static function notifyBossOfInscription(User $boss, Session $session, int $userId): void
2399
    {
2400
        $tpl = Container::getTwig();
2401
2402
        $user_info = api_get_user_info($userId);
2403
2404
        $subject = $tpl->render(
2405
            '@ChamiloCore/Mailer/Legacy/subject_subscription_to_boss_notification.html.twig',
2406
            [
2407
                'locale' => $boss->getLocale(),
2408
                'boss_name' => $boss->getFullName(),
2409
                'student_name' => $user_info['complete_name'],
2410
                'session_name' => $session->getTitle(),
2411
            ]
2412
        );
2413
2414
        $content = $tpl->render(
2415
            '@ChamiloCore/Mailer/Legacy/content_subscription_to_boss_notification.html.twig',
2416
            [
2417
                'locale' => $boss->getLocale(),
2418
                'boss_name' => $boss->getFullName(),
2419
                'student_name' => $user_info['complete_name'],
2420
                'session_name' => $session->getTitle(),
2421
            ]
2422
        );
2423
2424
        // Send email
2425
        api_mail_html(
2426
            $boss->getFullName(),
2427
            $boss->getEmail(),
2428
            $subject,
2429
            $content,
2430
            api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname')),
2431
            api_get_setting('emailAdministrator')
2432
        );
2433
2434
        // Record message in system
2435
        MessageManager::send_message_simple(
2436
            $boss->getId(),
2437
            $subject,
2438
            $content,
2439
            api_get_user_id(),
2440
            false,
2441
            true
2442
        );
2443
    }
2444
2445
    /**
2446
     * Returns user list of the current users subscribed in the course-session.
2447
     *
2448
     * @param int   $sessionId
2449
     * @param array $courseInfo
2450
     * @param int   $status
2451
     *
2452
     * @return array
2453
     */
2454
    public static function getUsersByCourseSession(
2455
        $sessionId,
2456
        $courseInfo,
2457
        $status = null
2458
    ) {
2459
        $sessionId = (int) $sessionId;
2460
        $courseId = $courseInfo['real_id'];
2461
2462
        if (empty($sessionId) || empty($courseId)) {
2463
            return [];
2464
        }
2465
2466
        $statusCondition = null;
2467
        if (isset($status) && !is_null($status)) {
2468
            $status = (int) $status;
2469
            $statusCondition = " AND status = $status";
2470
        }
2471
2472
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2473
2474
        $sql = "SELECT DISTINCT user_id
2475
                FROM $table
2476
                WHERE
2477
                    session_id = $sessionId AND
2478
                    c_id = $courseId
2479
                    $statusCondition
2480
                ";
2481
2482
        $result = Database::query($sql);
2483
        $existingUsers = [];
2484
        while ($row = Database::fetch_array($result)) {
2485
            $existingUsers[] = $row['user_id'];
2486
        }
2487
2488
        return $existingUsers;
2489
    }
2490
2491
    /**
2492
     * Returns user list of the current users subscribed in the course-session.
2493
     *
2494
     * @param array $sessionList
2495
     * @param array $courseList
2496
     * @param int   $status
2497
     * @param int   $start
2498
     * @param int   $limit
2499
     *
2500
     * @return array
2501
     */
2502
    public static function getUsersByCourseAndSessionList(
2503
        $sessionList,
2504
        $courseList,
2505
        $status = null,
2506
        $start = null,
2507
        $limit = null
2508
    ) {
2509
        if (empty($sessionList) || empty($courseList)) {
2510
            return [];
2511
        }
2512
        $sessionListToString = implode("','", $sessionList);
2513
        $courseListToString = implode("','", $courseList);
2514
2515
        $statusCondition = null;
2516
        if (isset($status) && !is_null($status)) {
2517
            $status = (int) $status;
2518
            $statusCondition = " AND status = $status";
2519
        }
2520
2521
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2522
2523
        $sql = "SELECT DISTINCT user_id
2524
                FROM $table
2525
                WHERE
2526
                    session_id IN ('$sessionListToString') AND
2527
                    c_id IN ('$courseListToString')
2528
                    $statusCondition
2529
                ";
2530
        if (!is_null($start) && !is_null($limit)) {
2531
            $start = (int) $start;
2532
            $limit = (int) $limit;
2533
            $sql .= "LIMIT $start, $limit";
2534
        }
2535
        $result = Database::query($sql);
2536
        $existingUsers = [];
2537
        while ($row = Database::fetch_array($result)) {
2538
            $existingUsers[] = $row['user_id'];
2539
        }
2540
2541
        return $existingUsers;
2542
    }
2543
2544
    /**
2545
     * Remove a list of users from a course-session.
2546
     *
2547
     * @param array $userList
2548
     * @param int   $sessionId
2549
     * @param array $courseInfo
2550
     * @param int   $status
2551
     * @param bool  $updateTotal
2552
     *
2553
     * @return bool
2554
     */
2555
    public static function removeUsersFromCourseSession(
2556
        $userList,
2557
        $sessionId,
2558
        $courseInfo,
2559
        $status = null,
2560
        $updateTotal = true
2561
    ) {
2562
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2563
        $tableSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2564
        $sessionId = (int) $sessionId;
2565
2566
        if (empty($sessionId) || empty($userList) || empty($courseInfo)) {
2567
            return false;
2568
        }
2569
2570
        $courseId = is_array($courseInfo) ? $courseInfo['real_id'] : $courseInfo;
2571
2572
        $statusCondition = null;
2573
        if (isset($status) && !is_null($status)) {
2574
            $status = (int) $status;
2575
            $statusCondition = " AND status = $status";
2576
        }
2577
2578
        foreach ($userList as $userId) {
2579
            $userId = (int) $userId;
2580
            $sql = "DELETE FROM $table
2581
                    WHERE
2582
                        session_id = $sessionId AND
2583
                        c_id = $courseId AND
2584
                        user_id = $userId
2585
                        $statusCondition
2586
                    ";
2587
            Database::query($sql);
2588
2589
            Event::addEvent(
2590
                LOG_SESSION_DELETE_USER_COURSE,
2591
                LOG_USER_ID,
2592
                $userId,
2593
                api_get_utc_datetime(),
2594
                api_get_user_id(),
2595
                $courseId,
2596
                $sessionId
2597
            );
2598
        }
2599
2600
        if ($updateTotal) {
2601
            // Count users in this session-course relation
2602
            $sql = "SELECT COUNT(user_id) as nbUsers
2603
                    FROM $table
2604
                    WHERE
2605
                        session_id = $sessionId AND
2606
                        c_id = $courseId AND
2607
                        status = ".Session::STUDENT;
2608
            $result = Database::query($sql);
2609
            [$userCount] = Database::fetch_array($result);
2610
2611
            // update the session-course relation to add the users total
2612
            $sql = "UPDATE $tableSessionCourse
2613
                    SET nbr_users = $userCount
2614
                    WHERE
2615
                        session_id = $sessionId AND
2616
                        c_id = $courseId";
2617
            Database::query($sql);
2618
        }
2619
    }
2620
2621
    /**
2622
     * Subscribe a user to an specific course inside a session.
2623
     *
2624
     * @param array  $user_list
2625
     * @param int    $session_id
2626
     * @param string $course_code
2627
     * @param int    $session_visibility
2628
     * @param bool   $removeUsersNotInList
2629
     *
2630
     * @return bool
2631
     */
2632
    public static function subscribe_users_to_session_course(
2633
        $user_list,
2634
        $session_id,
2635
        $course_code,
2636
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2637
        $removeUsersNotInList = false
2638
    ) {
2639
        if (empty($session_id) || empty($course_code)) {
2640
            return false;
2641
        }
2642
2643
        $session_id = (int) $session_id;
2644
        $session_visibility = (int) $session_visibility;
2645
        $course_code = Database::escape_string($course_code);
2646
        $courseInfo = api_get_course_info($course_code);
2647
        $courseId = $courseInfo['real_id'];
2648
        $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseInfo);
2649
        $forums = [];
2650
        if (1 === $subscribe) {
2651
            $forums = get_forums($courseId, $session_id);
2652
        }
2653
2654
        if ($removeUsersNotInList) {
2655
            $currentUsers = self::getUsersByCourseSession($session_id, $courseInfo, 0);
2656
2657
            if (!empty($user_list)) {
2658
                $userToDelete = array_diff($currentUsers, $user_list);
2659
            } else {
2660
                $userToDelete = $currentUsers;
2661
            }
2662
2663
            if (!empty($userToDelete)) {
2664
                self::removeUsersFromCourseSession(
2665
                    $userToDelete,
2666
                    $session_id,
2667
                    $courseInfo,
2668
                    0,
2669
                    true
2670
                );
2671
            }
2672
        }
2673
2674
        self::insertUsersInCourse(
2675
            $user_list,
2676
            $courseId,
2677
            $session_id,
2678
            ['visibility' => $session_visibility],
2679
            true,
2680
            true
2681
        );
2682
    }
2683
2684
    /**
2685
     * Unsubscribe user from session.
2686
     *
2687
     * @param int Session id
2688
     * @param int User id
2689
     *
2690
     * @return bool True in case of success, false in case of error
2691
     */
2692
    public static function unsubscribe_user_from_session($session_id, $user_id)
2693
    {
2694
        $session_id = (int) $session_id;
2695
        $user_id = (int) $user_id;
2696
2697
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2698
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2699
2700
        $sql = "DELETE FROM $tbl_session_rel_user
2701
                WHERE
2702
                    session_id = $session_id AND
2703
                    user_id = $user_id ";
2704
        Database::query($sql);
2705
2706
        // Update number of users
2707
        $sql = "UPDATE $tbl_session
2708
                SET nbr_users = nbr_users - 1
2709
                WHERE id = $session_id ";
2710
        Database::query($sql);
2711
2712
        Event::addEvent(
2713
            LOG_SESSION_DELETE_USER,
2714
            LOG_USER_ID,
2715
            $user_id,
2716
            api_get_utc_datetime(),
2717
            api_get_user_id(),
2718
            null,
2719
            $session_id
2720
        );
2721
2722
        // Get the list of courses related to this session
2723
        $course_list = self::get_course_list_by_session_id($session_id);
2724
        if (!empty($course_list)) {
2725
            foreach ($course_list as $course) {
2726
                self::unSubscribeUserFromCourseSession($user_id, $course['id'], $session_id);
2727
            }
2728
        }
2729
2730
        return true;
2731
    }
2732
2733
    /**
2734
     * @param int $user_id
2735
     * @param int $courseId
2736
     * @param int $session_id
2737
     */
2738
    public static function unSubscribeUserFromCourseSession($user_id, $courseId, $session_id)
2739
    {
2740
        $user_id = (int) $user_id;
2741
        $courseId = (int) $courseId;
2742
        $session_id = (int) $session_id;
2743
2744
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2745
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2746
2747
        // Delete user from course
2748
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2749
                WHERE session_id = $session_id AND c_id = $courseId AND user_id = $user_id";
2750
        $result = Database::query($sql);
2751
2752
        if (Database::affected_rows($result)) {
2753
            // Update number of users in this relation
2754
            $sql = "UPDATE $tbl_session_rel_course SET
2755
                    nbr_users = nbr_users - 1
2756
                    WHERE session_id = $session_id AND c_id = $courseId";
2757
            Database::query($sql);
2758
        }
2759
2760
        Event::addEvent(
2761
            LOG_SESSION_DELETE_USER_COURSE,
2762
            LOG_USER_ID,
2763
            $user_id,
2764
            api_get_utc_datetime(),
2765
            api_get_user_id(),
2766
            $courseId,
2767
            $session_id
2768
        );
2769
    }
2770
2771
    /**
2772
     * Subscribes courses to the given session and optionally (default)
2773
     * unsubscribe previous users.
2774
     *
2775
     * @author Carlos Vargas from existing code
2776
     *
2777
     * @param int   $sessionId
2778
     * @param array $courseList                     List of courses int ids
2779
     * @param bool  $removeExistingCoursesWithUsers Whether to unsubscribe
2780
     *                                              existing courses and users (true, default) or not (false)
2781
     * @param bool  $copyEvaluation                 from base course to session course
2782
     * @param bool  $copyCourseTeachersAsCoach
2783
     * @param bool  $importAssignments
2784
     *
2785
     * @throws Exception
2786
     *
2787
     * @return bool False on failure, true otherwise
2788
     * */
2789
    public static function add_courses_to_session(
2790
        $sessionId,
2791
        $courseList,
2792
        $removeExistingCoursesWithUsers = true,
2793
        $copyEvaluation = false,
2794
        $copyCourseTeachersAsCoach = false,
2795
        $importAssignments = false
2796
    ) {
2797
        $sessionId = (int) $sessionId;
2798
2799
        if (empty($sessionId) || empty($courseList)) {
2800
            return false;
2801
        }
2802
2803
        $session = api_get_session_entity($sessionId);
2804
2805
        if (!$session) {
2806
            return false;
2807
        }
2808
        $sessionVisibility = $session->getVisibility();
2809
2810
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2811
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2812
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2813
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2814
2815
        // Get list of courses subscribed to this session
2816
        $sql = "SELECT c_id
2817
                FROM $tbl_session_rel_course
2818
                WHERE session_id = $sessionId";
2819
        $rs = Database::query($sql);
2820
        $existingCourses = Database::store_result($rs);
2821
        $nbr_courses = count($existingCourses);
2822
2823
        // Get list of users subscribed to this session
2824
        $sql = "SELECT user_id
2825
                FROM $tbl_session_rel_user
2826
                WHERE
2827
                    session_id = $sessionId AND
2828
                    relation_type = ".Session::STUDENT;
2829
        $result = Database::query($sql);
2830
        $user_list = Database::store_result($result);
2831
2832
        // Remove existing courses from the session.
2833
        if (true === $removeExistingCoursesWithUsers && !empty($existingCourses)) {
2834
            foreach ($existingCourses as $existingCourse) {
2835
                if (!in_array($existingCourse['c_id'], $courseList)) {
2836
                    $sql = "DELETE FROM $tbl_session_rel_course
2837
                            WHERE
2838
                                c_id = ".$existingCourse['c_id']." AND
2839
                                session_id = $sessionId";
2840
                    Database::query($sql);
2841
2842
                    $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2843
                            WHERE
2844
                                c_id = ".$existingCourse['c_id']." AND
2845
                                session_id = $sessionId";
2846
                    Database::query($sql);
2847
2848
                    Event::addEvent(
2849
                        LOG_SESSION_DELETE_COURSE,
2850
                        LOG_COURSE_ID,
2851
                        $existingCourse['c_id'],
2852
                        api_get_utc_datetime(),
2853
                        api_get_user_id(),
2854
                        $existingCourse['c_id'],
2855
                        $sessionId
2856
                    );
2857
2858
                    CourseManager::remove_course_ranking($existingCourse['c_id']);
2859
                    $nbr_courses--;
2860
                }
2861
            }
2862
        }
2863
2864
        // Pass through the courses list we want to add to the session
2865
        foreach ($courseList as $courseId) {
2866
            $courseInfo = api_get_course_info_by_id($courseId);
2867
2868
            // If course doesn't exist continue!
2869
            if (empty($courseInfo)) {
2870
                continue;
2871
            }
2872
2873
            $exists = false;
2874
            // check if the course we want to add is already subscribed
2875
            foreach ($existingCourses as $existingCourse) {
2876
                if ($courseId == $existingCourse['c_id']) {
2877
                    $exists = true;
2878
                }
2879
            }
2880
2881
            if (!$exists) {
2882
                // Copy gradebook categories and links (from base course)
2883
                // to the new course session
2884
                if ($copyEvaluation) {
2885
                    $cats = Category::load(null, null, $courseId);
2886
                    if (!empty($cats)) {
2887
                        $sessionCategory = Category:: load(
2888
                            null,
2889
                            null,
2890
                            $courseId,
2891
                            null,
2892
                            null,
2893
                            $sessionId,
2894
                            null
2895
                        );
2896
2897
                        // @todo remove commented code
2898
                        if (empty($sessionCategory)) {
2899
                            // There is no category for this course+session, so create one
2900
                            $cat = new Category();
2901
                            $sessionName = $session->getTitle();
2902
                            $cat->set_name($courseInfo['code'].' - '.get_lang('Session').' '.$sessionName);
2903
                            $cat->set_session_id($sessionId);
2904
                            $cat->setCourseId($courseId);
2905
                            $cat->set_description(null);
2906
                            //$cat->set_user_id($stud_id);
2907
                            $cat->set_parent_id(0);
2908
                            $cat->set_weight(100);
2909
                            $cat->set_visible(0);
2910
                            $cat->set_certificate_min_score(75);
2911
                            $cat->setGenerateCertificates(1);
2912
                            $cat->setIsRequirement(1);
2913
                            $cat->add();
2914
                            $sessionGradeBookCategoryId = $cat->get_id();
2915
                        } else {
2916
                            if (!empty($sessionCategory[0])) {
2917
                                $sessionGradeBookCategoryId = $sessionCategory[0]->get_id();
2918
                            }
2919
                        }
2920
2921
                        $categoryIdList = [];
2922
                        /** @var Category $cat */
2923
                        foreach ($cats as $cat) {
2924
                            $categoryIdList[$cat->get_id()] = $cat->get_id();
2925
                        }
2926
2927
                        $newCategoryIdList = [];
2928
                        foreach ($cats as $cat) {
2929
                            $links = $cat->get_links(
2930
                                null,
2931
                                false,
2932
                                $courseId,
2933
                                $sessionId
2934
                            );
2935
2936
                            //$cat->set_session_id($sessionId);
2937
                            //$oldCategoryId = $cat->get_id();
2938
                            //$newId = $cat->add();
2939
                            //$newCategoryIdList[$oldCategoryId] = $newId;
2940
                            //$parentId = $cat->get_parent_id();
2941
2942
                            /*if (!empty($parentId)) {
2943
                                $newParentId = $newCategoryIdList[$parentId];
2944
                                $cat->set_parent_id($newParentId);
2945
                                $cat->save();
2946
                            }*/
2947
2948
                            if (!empty($links)) {
2949
                                /** @var AbstractLink $link */
2950
                                foreach ($links as $link) {
2951
                                    //$newCategoryId = $newCategoryIdList[$link->get_category_id()];
2952
                                    $link->set_category_id($sessionGradeBookCategoryId);
2953
                                    $link->add();
2954
                                }
2955
                            }
2956
2957
                            $evaluationList = $cat->get_evaluations(
2958
                                null,
2959
                                false,
2960
                                $courseId,
2961
                                $sessionId
2962
                            );
2963
2964
                            if (!empty($evaluationList)) {
2965
                                /** @var Evaluation $evaluation */
2966
                                foreach ($evaluationList as $evaluation) {
2967
                                    //$evaluationId = $newCategoryIdList[$evaluation->get_category_id()];
2968
                                    $evaluation->set_category_id($sessionGradeBookCategoryId);
2969
                                    $evaluation->add();
2970
                                }
2971
                            }
2972
                        }
2973
2974
                        // Create
2975
                        DocumentManager::generateDefaultCertificate(
2976
                            $courseInfo,
2977
                            true,
2978
                            $sessionId
2979
                        );
2980
                    }
2981
                }
2982
2983
                if ($importAssignments) {
2984
                    $repo = Container::getStudentPublicationRepository();
2985
                    $course = api_get_course_entity($courseId);
2986
                    $session = api_get_session_entity($sessionId);
2987
                    $user = api_get_user_entity();
2988
2989
                    $qb = $repo->getResourcesByCourse($course, null);
2990
                    $qb
2991
                        ->andWhere('resource.active = 1')
2992
                        ->andWhere('resource.filetype = :filetype')
2993
                        ->andWhere('resource.publicationParent IS NULL')
2994
                        ->setParameter('filetype', 'folder');
2995
2996
                    $baseAssignments = $qb->getQuery()->getResult();
2997
2998
                    foreach ($baseAssignments as $originalAssignment) {
2999
                        if (!$originalAssignment instanceof CStudentPublication) {
3000
                            continue;
3001
                        }
3002
3003
                        $newAssignment = new CStudentPublication();
3004
                        $newAssignment
3005
                            ->setTitle($originalAssignment->getTitle())
3006
                            ->setDescription($originalAssignment->getDescription() ?? '')
3007
                            ->setActive(1)
3008
                            ->setAccepted(true)
3009
                            ->setFiletype('folder')
3010
                            ->setPostGroupId(0)
3011
                            ->setSentDate(new \DateTime())
3012
                            ->setQualification($originalAssignment->getQualification())
3013
                            ->setWeight($originalAssignment->getWeight())
3014
                            ->setAllowTextAssignment($originalAssignment->getAllowTextAssignment())
3015
                            ->setUser($user)
3016
                            ->setParent($course)
3017
                            ->addCourseLink($course, $session, null);
3018
3019
                        $repo->create($newAssignment);
3020
                    }
3021
                }
3022
                // If the course isn't subscribed yet
3023
                $sql = "INSERT INTO $tbl_session_rel_course (session_id, c_id, nbr_users, position)
3024
                        VALUES ($sessionId, $courseId, 0, 0)";
3025
                Database::query($sql);
3026
3027
                Event::addEvent(
3028
                    LOG_SESSION_ADD_COURSE,
3029
                    LOG_COURSE_ID,
3030
                    $courseId,
3031
                    api_get_utc_datetime(),
3032
                    api_get_user_id(),
3033
                    $courseId,
3034
                    $sessionId
3035
                );
3036
3037
                // We add the current course in the existing courses array,
3038
                // to avoid adding another time the current course
3039
                $existingCourses[] = ['c_id' => $courseId];
3040
                $nbr_courses++;
3041
3042
                // Subscribe all the users from the session to this course inside the session
3043
                self::insertUsersInCourse(
3044
                    array_column($user_list, 'user_id'),
3045
                    $courseId,
3046
                    $sessionId,
3047
                    ['visibility' => $sessionVisibility],
3048
                    false
3049
                );
3050
            }
3051
3052
            if ($copyCourseTeachersAsCoach) {
3053
                $teachers = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
3054
                if (!empty($teachers)) {
3055
                    foreach ($teachers as $teacher) {
3056
                        self::updateCoaches(
3057
                            $sessionId,
3058
                            $courseId,
3059
                            [$teacher['user_id']],
3060
                            false
3061
                        );
3062
                    }
3063
                }
3064
            }
3065
        }
3066
3067
        $sql = "UPDATE $tbl_session SET nbr_courses = $nbr_courses WHERE id = $sessionId";
3068
        Database::query($sql);
3069
3070
        return true;
3071
    }
3072
3073
    /**
3074
     * Unsubscribe course from a session.
3075
     *
3076
     * @param int $session_id
3077
     * @param int $course_id
3078
     *
3079
     * @return bool True in case of success, false otherwise
3080
     */
3081
    public static function unsubscribe_course_from_session($session_id, $course_id)
3082
    {
3083
        $session_id = (int) $session_id;
3084
        $course_id = (int) $course_id;
3085
3086
        if (empty($course_id) || empty($session_id)) {
3087
            return false;
3088
        }
3089
3090
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3091
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3092
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3093
3094
        // Unsubscribe course.
3095
        $sql = "DELETE FROM $tbl_session_rel_course
3096
                WHERE c_id = $course_id AND session_id = $session_id";
3097
        $result = Database::query($sql);
3098
        $nb_affected = Database::affected_rows($result);
3099
3100
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
3101
                WHERE c_id = $course_id AND session_id = $session_id";
3102
        Database::query($sql);
3103
3104
        Event::addEvent(
3105
            LOG_SESSION_DELETE_COURSE,
3106
            LOG_COURSE_ID,
3107
            $course_id,
3108
            api_get_utc_datetime(),
3109
            api_get_user_id(),
3110
            $course_id,
3111
            $session_id
3112
        );
3113
3114
        if ($nb_affected > 0) {
3115
            // Update number of courses in the session
3116
            $sql = "UPDATE $tbl_session SET nbr_courses= nbr_courses - $nb_affected
3117
                    WHERE id = $session_id";
3118
            Database::query($sql);
3119
3120
            return true;
3121
        }
3122
3123
        return false;
3124
    }
3125
3126
    /**
3127
     * Creates a new extra field for a given session.
3128
     *
3129
     * @param string $variable    Field's internal variable name
3130
     * @param int    $fieldType   Field's type
3131
     * @param string $displayText Field's language var name
3132
     * @param string $default     Field's default value
3133
     *
3134
     * @return int new extra field id
3135
     */
3136
    public static function create_session_extra_field(
3137
        $variable,
3138
        $valueType,
3139
        $displayText,
3140
        $default = ''
3141
    ) {
3142
        $extraField = new ExtraFieldModel('session');
3143
        $params = [
3144
            'variable' => $variable,
3145
            'value_type' => $valueType,
3146
            'display_text' => $displayText,
3147
            'default_value' => $default,
3148
        ];
3149
3150
        return $extraField->save($params);
3151
    }
3152
3153
    /**
3154
     * Update an extra field value for a given session.
3155
     *
3156
     * @param int    $sessionId Session ID
3157
     * @param string $variable  Field variable name
3158
     * @param string $value     Optional. Default field value
3159
     *
3160
     * @return bool|int An integer when register a new extra field. And boolean when update the extrafield
3161
     */
3162
    public static function update_session_extra_field_value($sessionId, $variable, $value = '')
3163
    {
3164
        $extraFieldValue = new ExtraFieldValue('session');
3165
        $params = [
3166
            'item_id' => $sessionId,
3167
            'variable' => $variable,
3168
            'value' => $value,
3169
        ];
3170
3171
        return $extraFieldValue->save($params);
3172
    }
3173
3174
    /**
3175
     * Checks the relationship between a session and a course.
3176
     *
3177
     * @param int $session_id
3178
     * @param int $courseId
3179
     *
3180
     * @return bool returns TRUE if the session and the course are related, FALSE otherwise
3181
     * */
3182
    public static function relation_session_course_exist($session_id, $courseId)
3183
    {
3184
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3185
        $return_value = false;
3186
        $sql = "SELECT c_id FROM $tbl_session_course
3187
                WHERE
3188
                  session_id = ".intval($session_id)." AND
3189
                  c_id = ".intval($courseId);
3190
        $result = Database::query($sql);
3191
        $num = Database::num_rows($result);
3192
        if ($num > 0) {
3193
            $return_value = true;
3194
        }
3195
3196
        return $return_value;
3197
    }
3198
3199
    /**
3200
     * Get the session information by name.
3201
     *
3202
     * @param string $name
3203
     *
3204
     * @return mixed false if the session does not exist, array if the session exist
3205
     */
3206
    public static function get_session_by_name($name)
3207
    {
3208
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3209
        $name = Database::escape_string(trim($name));
3210
        if (empty($name)) {
3211
            return false;
3212
        }
3213
3214
        $sql = 'SELECT *
3215
		        FROM '.$tbl_session.'
3216
		        WHERE title = "'.$name.'"';
3217
        $result = Database::query($sql);
3218
        $num = Database::num_rows($result);
3219
        if ($num > 0) {
3220
            return Database::fetch_array($result);
3221
        } else {
3222
            return false;
3223
        }
3224
    }
3225
3226
    /**
3227
     * @param int $sessionId
3228
     * @param int $name
3229
     *
3230
     * @return bool
3231
     */
3232
    public static function sessionNameExistBesidesMySession($sessionId, $name)
3233
    {
3234
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
3235
        $name = Database::escape_string(trim($name));
3236
        $sessionId = (int) $sessionId;
3237
3238
        if (empty($name)) {
3239
            return false;
3240
        }
3241
3242
        $sql = "SELECT *
3243
		        FROM $table
3244
		        WHERE title = '$name' AND id <> $sessionId ";
3245
        $result = Database::query($sql);
3246
        $num = Database::num_rows($result);
3247
        if ($num > 0) {
3248
            return true;
3249
        }
3250
3251
        return false;
3252
    }
3253
3254
    /**
3255
     * Create a session category.
3256
     *
3257
     * @author Jhon Hinojosa <[email protected]>, from existing code
3258
     *
3259
     * @param string        name
3260
     * @param int        year_start
3261
     * @param int        month_start
3262
     * @param int        day_start
3263
     * @param int        year_end
3264
     * @param int        month_end
3265
     * @param int        day_end
3266
     *
3267
     * @return int session ID
3268
     * */
3269
    public static function create_category_session(
3270
        $sname,
3271
        $syear_start,
3272
        $smonth_start,
3273
        $sday_start,
3274
        $syear_end,
3275
        $smonth_end,
3276
        $sday_end
3277
    ) {
3278
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3279
        $name = html_filter(trim($sname));
3280
        $year_start = intval($syear_start);
3281
        $month_start = intval($smonth_start);
3282
        $day_start = intval($sday_start);
3283
        $year_end = intval($syear_end);
3284
        $month_end = intval($smonth_end);
3285
        $day_end = intval($sday_end);
3286
3287
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3288
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3289
3290
        if (empty($name)) {
3291
            $msg = get_lang('Please give a name to the sessions category');
3292
3293
            return $msg;
3294
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3295
            $msg = get_lang('Invalid start date was given.');
3296
3297
            return $msg;
3298
        } elseif (!$month_end && !$day_end && !$year_end) {
3299
            $date_end = '';
3300
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3301
            $msg = get_lang('Invalid end date was given.');
3302
3303
            return $msg;
3304
        } elseif ($date_start >= $date_end) {
3305
            $msg = get_lang('The first date should be before the end date');
3306
3307
            return $msg;
3308
        }
3309
3310
        $access_url_id = api_get_current_access_url_id();
3311
        $params = [
3312
            'title' => $name,
3313
            'date_start' => $date_start,
3314
            'access_url_id' => $access_url_id,
3315
        ];
3316
3317
        if (!empty($date_end)) {
3318
            $params['date_end'] = $date_end;
3319
        }
3320
3321
        $id = Database::insert($tbl_session_category, $params);
3322
3323
        // Add event to system log
3324
        $user_id = api_get_user_id();
3325
        Event::addEvent(
3326
            LOG_SESSION_CATEGORY_CREATE,
3327
            LOG_SESSION_CATEGORY_ID,
3328
            $id,
3329
            api_get_utc_datetime(),
3330
            $user_id
3331
        );
3332
3333
        return $id;
3334
    }
3335
3336
    /**
3337
     * Edit a sessions category.
3338
     *
3339
     * @author Jhon Hinojosa <[email protected]>,from existing code
3340
     *
3341
     * @param int        id
3342
     * @param string        name
3343
     * @param int        year_start
3344
     * @param int        month_start
3345
     * @param int        day_start
3346
     * @param int        year_end
3347
     * @param int        month_end
3348
     * @param int        day_end
3349
     *
3350
     * @return bool
3351
     *              The parameter id is a primary key
3352
     * */
3353
    public static function edit_category_session(
3354
        $id,
3355
        $sname,
3356
        $syear_start,
3357
        $smonth_start,
3358
        $sday_start,
3359
        $syear_end,
3360
        $smonth_end,
3361
        $sday_end
3362
    ) {
3363
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3364
        $name = html_filter(trim($sname));
3365
        $year_start = intval($syear_start);
3366
        $month_start = intval($smonth_start);
3367
        $day_start = intval($sday_start);
3368
        $year_end = intval($syear_end);
3369
        $month_end = intval($smonth_end);
3370
        $day_end = intval($sday_end);
3371
        $id = intval($id);
3372
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3373
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3374
3375
        if (empty($name)) {
3376
            $msg = get_lang('Please give a name to the sessions category');
3377
3378
            return $msg;
3379
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3380
            $msg = get_lang('Invalid start date was given.');
3381
3382
            return $msg;
3383
        } elseif (!$month_end && !$day_end && !$year_end) {
3384
            $date_end = null;
3385
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3386
            $msg = get_lang('Invalid end date was given.');
3387
3388
            return $msg;
3389
        } elseif ($date_start >= $date_end) {
3390
            $msg = get_lang('The first date should be before the end date');
3391
3392
            return $msg;
3393
        }
3394
        if (null != $date_end) {
3395
            $sql = "UPDATE $tbl_session_category
3396
                    SET
3397
                        title = '".Database::escape_string($name)."',
3398
                        date_start = '$date_start' ,
3399
                        date_end = '$date_end'
3400
                    WHERE id= $id";
3401
        } else {
3402
            $sql = "UPDATE $tbl_session_category SET
3403
                        title = '".Database::escape_string($name)."',
3404
                        date_start = '$date_start',
3405
                        date_end = NULL
3406
                    WHERE id= $id";
3407
        }
3408
        $result = Database::query($sql);
3409
3410
        return $result ? true : false;
3411
    }
3412
3413
    /**
3414
     * Delete sessions categories.
3415
     *
3416
     * @param array|int $categoryId
3417
     * @param bool      $deleteSessions Optional. Include delete session.
3418
     * @param bool      $fromWs         Optional. True if the function is called by a webservice, false otherwise.
3419
     *
3420
     * @return bool Nothing, or false on error
3421
     *              The parameters is a array to delete sessions
3422
     *
3423
     * @author Jhon Hinojosa <[email protected]>, from existing code
3424
     */
3425
    public static function delete_session_category($categoryId, $deleteSessions = false, $fromWs = false)
3426
    {
3427
        $tblSessionCategory = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3428
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
3429
3430
        if (is_array($categoryId)) {
3431
            $categoryId = array_map('intval', $categoryId);
3432
        } else {
3433
            $categoryId = [(int) $categoryId];
3434
        }
3435
3436
        $categoryId = implode(', ', $categoryId);
3437
3438
        if ($deleteSessions) {
3439
            $sql = "SELECT id FROM $tblSession WHERE session_category_id IN ($categoryId)";
3440
            $result = Database::query($sql);
3441
            while ($rows = Database::fetch_array($result)) {
3442
                $sessionId = $rows['id'];
3443
                self::delete($sessionId, $fromWs);
3444
            }
3445
        } else {
3446
            $sql = "UPDATE $tblSession SET session_category_id = NULL WHERE session_category_id IN ($categoryId)";
3447
            Database::query($sql);
3448
        }
3449
3450
        $sql = "DELETE FROM $tblSessionCategory WHERE id IN ($categoryId)";
3451
        Database::query($sql);
3452
3453
        // Add event to system log
3454
        Event::addEvent(
3455
            LOG_SESSION_CATEGORY_DELETE,
3456
            LOG_SESSION_CATEGORY_ID,
3457
            $categoryId,
3458
            api_get_utc_datetime(),
3459
            api_get_user_id()
3460
        );
3461
3462
        return true;
3463
    }
3464
3465
    /**
3466
     * Get a list of sessions of which the given conditions match with an = 'cond'.
3467
     *
3468
     * @param array $conditions          a list of condition example :
3469
     *                                   array('status' => STUDENT) or
3470
     *                                   array('s.title' => array('operator' => 'LIKE', value = '%$needle%'))
3471
     * @param array $order_by            a list of fields on which sort
3472
     * @param int   $urlId
3473
     * @param array $onlyThisSessionList
3474
     *
3475
     * @return array an array with all sessions of the platform
3476
     *
3477
     * @todo   optional course code parameter, optional sorting parameters...
3478
     */
3479
    public static function get_sessions_list(
3480
        $conditions = [],
3481
        $order_by = [],
3482
        $from = null,
3483
        $to = null,
3484
        $urlId = 0,
3485
        $onlyThisSessionList = []
3486
    ) {
3487
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3488
        $session_category_table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3489
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3490
        $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3491
        $session_course_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3492
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
3493
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
3494
        $return_array = [];
3495
3496
        $sql_query = " SELECT
3497
                    DISTINCT(s.id),
3498
                    s.title,
3499
                    s.nbr_courses,
3500
                    s.access_start_date,
3501
                    s.access_end_date,
3502
                    sc.title as category_name,
3503
                    s.promotion_id
3504
				FROM $session_table s
3505
				INNER JOIN $table_access_url_rel_session ar ON ar.session_id = s.id
3506
				LEFT JOIN  $session_category_table sc ON s.session_category_id = sc.id
3507
				LEFT JOIN $session_course_table sco ON (sco.session_id = s.id)
3508
				INNER JOIN $course_table c ON sco.c_id = c.id
3509
				WHERE ar.access_url_id = $urlId ";
3510
3511
        $availableFields = [
3512
            's.id',
3513
            's.title',
3514
            'c.id',
3515
        ];
3516
3517
        $availableOperator = [
3518
            'like',
3519
            '>=',
3520
            '<=',
3521
            '=',
3522
        ];
3523
3524
        if (count($conditions) > 0) {
3525
            foreach ($conditions as $field => $options) {
3526
                $operator = strtolower($options['operator']);
3527
                $value = Database::escape_string($options['value']);
3528
                if (in_array($field, $availableFields) && in_array($operator, $availableOperator)) {
3529
                    $sql_query .= ' AND '.$field." $operator '".$value."'";
3530
                }
3531
            }
3532
        }
3533
3534
        if (!empty($onlyThisSessionList)) {
3535
            $onlyThisSessionList = array_map('intval', $onlyThisSessionList);
3536
            $onlyThisSessionList = implode("','", $onlyThisSessionList);
3537
            $sql_query .= " AND s.id IN ('$onlyThisSessionList') ";
3538
        }
3539
3540
        $orderAvailableList = ['title'];
3541
        if (count($order_by) > 0) {
3542
            $order = null;
3543
            $direction = null;
3544
            if (isset($order_by[0]) && in_array($order_by[0], $orderAvailableList)) {
3545
                $order = $order_by[0];
3546
            }
3547
            if (isset($order_by[1]) && in_array(strtolower($order_by[1]), ['desc', 'asc'])) {
3548
                $direction = $order_by[1];
3549
            }
3550
3551
            if (!empty($order)) {
3552
                $sql_query .= " ORDER BY $order $direction ";
3553
            }
3554
        }
3555
3556
        if (!is_null($from) && !is_null($to)) {
3557
            $to = (int) $to;
3558
            $from = (int) $from;
3559
            $sql_query .= "LIMIT $from, $to";
3560
        }
3561
3562
        $sql_result = Database::query($sql_query);
3563
        if (Database::num_rows($sql_result) > 0) {
3564
            while ($result = Database::fetch_array($sql_result)) {
3565
                $return_array[$result['id']] = $result;
3566
            }
3567
        }
3568
3569
        return $return_array;
3570
    }
3571
3572
    /**
3573
     * Get the session category information by id.
3574
     *
3575
     * @param string session category ID
3576
     *
3577
     * @return mixed false if the session category does not exist, array if the session category exists
3578
     */
3579
    public static function get_session_category($id)
3580
    {
3581
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3582
        $id = (int) $id;
3583
        $sql = "SELECT id, title, date_start, date_end
3584
                FROM $table
3585
                WHERE id= $id";
3586
        $result = Database::query($sql);
3587
        $num = Database::num_rows($result);
3588
        if ($num > 0) {
3589
            return Database::fetch_array($result);
3590
        } else {
3591
            return false;
3592
        }
3593
    }
3594
3595
    /**
3596
     * Get Hot Sessions (limit 8).
3597
     *
3598
     * @return array with sessions
3599
     */
3600
    public static function getHotSessions()
3601
    {
3602
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3603
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3604
        $tbl_users = Database::get_main_table(TABLE_MAIN_USER);
3605
        $tbl_extra_fields = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3606
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3607
        $tbl_lp = Database::get_course_table(TABLE_LP_MAIN);
3608
3609
        $extraField = new ExtraFieldModel('session');
3610
        $field = $extraField->get_handler_field_info_by_field_variable('image');
3611
3612
        $sql = "SELECT
3613
                s.id,
3614
                s.title,
3615
                s.session_category_id,
3616
                c.title as category_name,
3617
                s.description,
3618
                s.nbr_users as users,
3619
				(SELECT COUNT(*) FROM $tbl_lp WHERE session_id = s.id) as lessons ";
3620
        if (false !== $field) {
3621
            $fieldId = $field['id'];
3622
            $sql .= ",(SELECT value FROM $tbl_extra_fields WHERE field_id = $fieldId AND item_id = s.id) as image ";
3623
        }
3624
        $sql .= " FROM $tbl_session s
3625
                LEFT JOIN $tbl_session_category c
3626
                    ON s.session_category_id = c.id
3627
                ORDER BY 8 DESC
3628
                LIMIT 8";
3629
        $result = Database::query($sql);
3630
3631
        if (Database::num_rows($result) > 0) {
3632
            $plugin = BuyCoursesPlugin::create();
3633
            $checker = $plugin->isEnabled();
3634
            $sessions = [];
3635
            while ($row = Database::fetch_assoc($result)) {
3636
                if (!isset($row['image'])) {
3637
                    $row['image'] = '';
3638
                }
3639
                $row['on_sale'] = '';
3640
                if ($checker) {
3641
                    $row['on_sale'] = $plugin->getItemByProduct(
3642
                        $row['id'],
3643
                        BuyCoursesPlugin::PRODUCT_TYPE_SESSION
3644
                    );
3645
                }
3646
                $sessions[] = $row;
3647
            }
3648
3649
            return $sessions;
3650
        }
3651
3652
        return false;
3653
    }
3654
3655
    /**
3656
     * Get all session categories (filter by access_url_id).
3657
     *
3658
     * @return mixed false if the session category does not exist, array if the session category exists
3659
     */
3660
    public static function get_all_session_category()
3661
    {
3662
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3663
        $id = api_get_current_access_url_id();
3664
        $sql = 'SELECT * FROM '.$table.'
3665
                WHERE access_url_id = '.$id.'
3666
                ORDER BY title ASC';
3667
        $result = Database::query($sql);
3668
        if (Database::num_rows($result) > 0) {
3669
            $data = Database::store_result($result, 'ASSOC');
3670
3671
            return $data;
3672
        }
3673
3674
        return false;
3675
    }
3676
3677
    /**
3678
     * Assign a coach to course in session with status = 2.
3679
     *
3680
     * @param int  $userId
3681
     * @param int  $sessionId
3682
     * @param int  $courseId
3683
     * @param bool $noCoach   optional, if is true the user don't be a coach now,
3684
     *                        otherwise it'll assign a coach
3685
     *
3686
     * @return bool true if there are affected rows, otherwise false
3687
     */
3688
    public static function set_coach_to_course_session(
3689
        $userId,
3690
        $sessionId = 0,
3691
        $courseId = 0,
3692
        $noCoach = false
3693
    ) {
3694
        $userId = (int) $userId;
3695
3696
        $sessionId = !empty($sessionId) ? (int) $sessionId : api_get_session_id();
3697
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_id();
3698
3699
        if (empty($sessionId) || empty($courseId) || empty($userId)) {
3700
            return false;
3701
        }
3702
3703
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3704
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3705
3706
        $user = api_get_user_entity($userId);
3707
3708
        if (!$user->isTeacher()) {
3709
            return false;
3710
        }
3711
3712
        if ($noCoach) {
3713
            // Delete the course-specific coach record
3714
            $sql = "DELETE FROM $tblSessionRelCourseRelUser
3715
                WHERE
3716
                    session_id = $sessionId AND
3717
                    c_id = $courseId AND
3718
                    user_id = $userId AND
3719
                    status = ".Session::COURSE_COACH;
3720
            $result = Database::query($sql);
3721
3722
            // Check if the user is still a coach for any course in this session
3723
            $sql = "SELECT COUNT(*) AS count FROM $tblSessionRelCourseRelUser
3724
                WHERE
3725
                    session_id = $sessionId AND
3726
                    user_id = $userId AND
3727
                    status = ".Session::COURSE_COACH;
3728
            $res = Database::query($sql);
3729
            $resultRow = Database::fetch_assoc($res);
3730
3731
            // If the user is no longer a coach for any course in this session, remove the session relationship
3732
            if (0 === (int) $resultRow['count']) {
3733
                $sql = "DELETE FROM $tblSessionRelUser
3734
                    WHERE
3735
                        session_id = $sessionId AND
3736
                        user_id = $userId AND
3737
                        relation_type = ".Session::COURSE_COACH;
3738
                Database::query($sql);
3739
            }
3740
3741
            return Database::affected_rows($result) > 0;
3742
        }
3743
3744
        // Assign user as a coach to course
3745
        // First check if the user is registered to the course
3746
        $sql = "SELECT user_id FROM $tblSessionRelCourseRelUser
3747
                WHERE
3748
                    session_id = $sessionId AND
3749
                    c_id = $courseId AND
3750
                    user_id = $userId";
3751
        $rs_check = Database::query($sql);
3752
3753
        // Then update or insert.
3754
        if (Database::num_rows($rs_check) > 0) {
3755
            $sql = "UPDATE $tblSessionRelCourseRelUser
3756
                    SET status = ".Session::COURSE_COACH."
3757
                    WHERE
3758
                        session_id = $sessionId AND
3759
                        c_id = $courseId AND
3760
                        user_id = $userId ";
3761
            $result = Database::query($sql);
3762
3763
            return Database::affected_rows($result) > 0;
3764
        }
3765
3766
        $em = Container::getEntityManager();
3767
        $em->clear();
3768
        $session = $em->getRepository(Session::class)->find($sessionId);
3769
        $course = api_get_course_entity($courseId);
3770
        if (!$session->hasCourse($course)) {
3771
            $session->addCourse($course);
3772
        }
3773
        $sessionRepo = Container::getSessionRepository();
3774
        $sessionRepo->addUserInCourse(
3775
            Session::COURSE_COACH,
3776
            api_get_user_entity($userId),
3777
            $course,
3778
            $session
3779
        );
3780
3781
        $sessionRepo->update($session);
3782
3783
        return true;
3784
    }
3785
3786
    /**
3787
     * Subscribes sessions to human resource manager (Dashboard feature).
3788
     *
3789
     * @param array $userInfo               Human Resource Manager info
3790
     * @param array $sessions_list          Sessions id
3791
     * @param bool  $sendEmail
3792
     * @param bool  $removeSessionsFromUser
3793
     *
3794
     * @return int
3795
     * */
3796
    public static function subscribeSessionsToDrh(
3797
        $userInfo,
3798
        $sessions_list,
3799
        $sendEmail = false,
3800
        $removeSessionsFromUser = true
3801
    ) {
3802
        // Database Table Definitions
3803
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3804
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3805
3806
        if (empty($userInfo)) {
3807
            return 0;
3808
        }
3809
3810
        $userId = $userInfo['user_id'];
3811
        $user = api_get_user_entity();
3812
3813
        // Only subscribe DRH users.
3814
        $rolesAllowed = [
3815
            DRH,
3816
            SESSIONADMIN,
3817
            PLATFORM_ADMIN,
3818
            COURSE_TUTOR,
3819
        ];
3820
        $isAdmin = api_is_platform_admin_by_id($userInfo['user_id']);
3821
        if (!$isAdmin && !in_array($userInfo['status'], $rolesAllowed)) {
3822
            return 0;
3823
        }
3824
3825
        $affected_rows = 0;
3826
        // Deleting assigned sessions to hrm_id.
3827
        if ($removeSessionsFromUser) {
3828
            if (api_is_multiple_url_enabled()) {
3829
                $sql = "SELECT s.session_id
3830
                        FROM $tbl_session_rel_user s
3831
                        INNER JOIN $tbl_session_rel_access_url a
3832
                        ON (a.session_id = s.session_id)
3833
                        WHERE
3834
                            s.user_id = $userId AND
3835
                            relation_type = ".Session::DRH." AND
3836
                            access_url_id = ".api_get_current_access_url_id();
3837
            } else {
3838
                $sql = "SELECT s.session_id
3839
                        FROM $tbl_session_rel_user s
3840
                        WHERE user_id = $userId AND relation_type=".Session::DRH;
3841
            }
3842
            $result = Database::query($sql);
3843
3844
            if (Database::num_rows($result) > 0) {
3845
                while ($row = Database::fetch_array($result)) {
3846
                    $sql = "DELETE FROM $tbl_session_rel_user
3847
                            WHERE
3848
                                session_id = {$row['session_id']} AND
3849
                                user_id = $userId AND
3850
                                relation_type =".Session::DRH;
3851
                    Database::query($sql);
3852
                }
3853
            }
3854
        }
3855
3856
        // Inserting new sessions list.
3857
        if (!empty($sessions_list) && is_array($sessions_list)) {
3858
            foreach ($sessions_list as $session_id) {
3859
                $session = api_get_session_entity($session_id);
3860
3861
                if (!$session->hasUserInSession($user, Session::DRH)) {
3862
                    $session->addUserInSession(Session::DRH, $user);
3863
3864
                    $affected_rows++;
3865
                }
3866
            }
3867
        }
3868
3869
        return $affected_rows;
3870
    }
3871
3872
    /**
3873
     * @param int $sessionId
3874
     *
3875
     * @return array
3876
     */
3877
    public static function getDrhUsersInSession($sessionId)
3878
    {
3879
        return self::get_users_by_session($sessionId, Session::DRH);
3880
    }
3881
3882
    /**
3883
     * @param int $userId
3884
     * @param int $sessionId
3885
     *
3886
     * @return array
3887
     */
3888
    public static function getSessionFollowedByDrh($userId, $sessionId)
3889
    {
3890
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3891
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3892
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3893
3894
        $userId = (int) $userId;
3895
        $sessionId = (int) $sessionId;
3896
3897
        $select = " SELECT * ";
3898
        if (api_is_multiple_url_enabled()) {
3899
            $sql = " $select FROM $tbl_session s
3900
                    INNER JOIN $tbl_session_rel_user sru ON (sru.session_id = s.id)
3901
                    LEFT JOIN $tbl_session_rel_access_url a ON (s.id = a.session_id)
3902
                    WHERE
3903
                        sru.user_id = '$userId' AND
3904
                        sru.session_id = '$sessionId' AND
3905
                        sru.relation_type = '".Session::DRH."' AND
3906
                        access_url_id = ".api_get_current_access_url_id()."
3907
                    ";
3908
        } else {
3909
            $sql = "$select FROM $tbl_session s
3910
                     INNER JOIN $tbl_session_rel_user sru
3911
                     ON
3912
                        sru.session_id = s.id AND
3913
                        sru.user_id = '$userId' AND
3914
                        sru.session_id = '$sessionId' AND
3915
                        sru.relation_type = '".Session::DRH."'
3916
                    ";
3917
        }
3918
3919
        $result = Database::query($sql);
3920
        if (Database::num_rows($result)) {
3921
            $row = Database::fetch_assoc($result);
3922
            $row['course_list'] = self::get_course_list_by_session_id($sessionId);
3923
3924
            return $row;
3925
        }
3926
3927
        return [];
3928
    }
3929
3930
    /**
3931
     * Get sessions followed by human resources manager.
3932
     *
3933
     * @param int    $userId
3934
     * @param int    $start
3935
     * @param int    $limit
3936
     * @param bool   $getCount
3937
     * @param bool   $getOnlySessionId
3938
     * @param bool   $getSql
3939
     * @param string $orderCondition
3940
     * @param string $keyword
3941
     * @param string $description
3942
     * @param array  $options
3943
     *
3944
     * @return array sessions
3945
     */
3946
    public static function get_sessions_followed_by_drh(
3947
        $userId,
3948
        $start = null,
3949
        $limit = null,
3950
        $getCount = false,
3951
        $getOnlySessionId = false,
3952
        $getSql = false,
3953
        $orderCondition = null,
3954
        $keyword = '',
3955
        $description = '',
3956
        $options = []
3957
    ) {
3958
        return self::getSessionsFollowedByUser(
3959
            $userId,
3960
            DRH,
3961
            $start,
3962
            $limit,
3963
            $getCount,
3964
            $getOnlySessionId,
3965
            $getSql,
3966
            $orderCondition,
3967
            $keyword,
3968
            $description,
3969
            $options
3970
        );
3971
    }
3972
3973
    /**
3974
     * Get sessions followed by human resources manager.
3975
     *
3976
     * @param int    $userId
3977
     * @param int    $status           DRH Optional
3978
     * @param int    $start
3979
     * @param int    $limit
3980
     * @param bool   $getCount
3981
     * @param bool   $getOnlySessionId
3982
     * @param bool   $getSql
3983
     * @param string $orderCondition
3984
     * @param string $keyword
3985
     * @param string $description
3986
     * @param array  $options
3987
     *
3988
     * @return array|string sessions
3989
     */
3990
    public static function getSessionsFollowedByUser(
3991
        $userId,
3992
        $status = null,
3993
        $start = null,
3994
        $limit = null,
3995
        $getCount = false,
3996
        $getOnlySessionId = false,
3997
        $getSql = false,
3998
        $orderCondition = null,
3999
        $keyword = '',
4000
        $description = '',
4001
        $options = []
4002
    ) {
4003
        // Database Table Definitions
4004
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
4005
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4006
4007
        $extraFieldModel = new ExtraFieldModel('session');
4008
        $conditions = $extraFieldModel->parseConditions($options);
4009
        $sqlInjectJoins = $conditions['inject_joins'];
4010
        $extraFieldsConditions = $conditions['where'];
4011
        $sqlInjectWhere = $conditions['inject_where'];
4012
        $injectExtraFields = $conditions['inject_extra_fields'];
4013
4014
        if (!empty($injectExtraFields)) {
4015
            $injectExtraFields = ' , '.$injectExtraFields.' s.id';
4016
        }
4017
4018
        $userId = (int) $userId;
4019
        $user = api_get_user_entity($userId);
4020
4021
        $select = ' SELECT DISTINCT * '.$injectExtraFields;
4022
        if ($getCount) {
4023
            $select = ' SELECT count(DISTINCT(s.id)) as count ';
4024
        }
4025
4026
        if ($getOnlySessionId) {
4027
            $select = ' SELECT DISTINCT(s.id) ';
4028
        }
4029
4030
        $limitCondition = null;
4031
        if (!is_null($start) && !is_null($limit)) {
4032
            $limitCondition = " LIMIT ".intval($start).", ".intval($limit);
4033
        }
4034
4035
        if (empty($orderCondition)) {
4036
            $orderCondition = ' ORDER BY s.title ';
4037
        }
4038
4039
        $whereConditions = null;
4040
4041
        switch ($status) {
4042
            case DRH:
4043
                $sessionsQuery = array_map(
4044
                    fn(Session $session) => $session->getId(),
4045
                    $user->getDRHSessions()
4046
                );
4047
                break;
4048
            case COURSEMANAGER:
4049
                $coachSessions = array_map(
4050
                    fn(Session $session) => $session->getId(),
4051
                    $user->getSessionsByStatusInCourseSubscription(Session::COURSE_COACH)->getValues()
4052
                );
4053
                $generalCoachSessions = array_map(
4054
                    fn(Session $session) => $session->getId(),
4055
                    $user->getSessionsAsGeneralCoach()
4056
                );
4057
4058
                $sessionsQuery = array_merge($coachSessions, $generalCoachSessions);
4059
                break;
4060
            case SESSIONADMIN:
4061
                $sessionsQuery = array_map(
4062
                    fn(Session $session) => $session->getId(),
4063
                    $user->getSessionsAsAdmin()
4064
                );
4065
                break;
4066
            default:
4067
                $sessionsQuery = array_map(
4068
                    fn(Session $session) => $session->getId(),
4069
                    $user->getSessionsAsStudent()
4070
                );
4071
                break;
4072
        }
4073
4074
        $keywordCondition = '';
4075
        if (!empty($keyword)) {
4076
            $keyword = Database::escape_string($keyword);
4077
            $keywordCondition = " AND (s.title LIKE '%$keyword%' ) ";
4078
            if (!empty($description)) {
4079
                $description = Database::escape_string($description);
4080
                $keywordCondition = " AND (s.title LIKE '%$keyword%' OR s.description LIKE '%$description%' ) ";
4081
            }
4082
        }
4083
4084
        $whereConditions .= $keywordCondition;
4085
        $subQuery = !empty($sessionsQuery) ? (' AND s.id IN ('.implode(',', $sessionsQuery).')') : '';
4086
4087
        $sql = " $select
4088
                FROM $tbl_session s
4089
                INNER JOIN $tbl_session_rel_access_url a
4090
                ON (s.id = a.session_id)
4091
                $sqlInjectJoins
4092
                WHERE
4093
                    access_url_id = ".api_get_current_access_url_id()."
4094
                    $subQuery
4095
                    $whereConditions
4096
                    $extraFieldsConditions
4097
                    $sqlInjectWhere
4098
                    $orderCondition
4099
                    $limitCondition";
4100
4101
        if ($getSql) {
4102
            return $sql;
4103
        }
4104
        $result = Database::query($sql);
4105
4106
        if ($getCount) {
4107
            $row = Database::fetch_array($result);
4108
            if ($row) {
4109
                return (int) $row['count'];
4110
            }
4111
4112
            return 0;
4113
        }
4114
4115
        $sessions = [];
4116
        if (Database::num_rows($result) > 0) {
4117
            $imgPath = Display::return_icon(
4118
                'session_default_small.png',
4119
                null,
4120
                [],
4121
                ICON_SIZE_SMALL,
4122
                false,
4123
                true
4124
            );
4125
4126
            $extraFieldValue = new ExtraFieldValue('session');
4127
            while ($row = Database::fetch_array($result)) {
4128
                if ($getOnlySessionId) {
4129
                    $sessions[$row['id']] = $row;
4130
                    continue;
4131
                }
4132
4133
                $extraFieldImage = $extraFieldValue->get_values_by_handler_and_field_variable($row['id'], 'image');
4134
                $image = $imgPath;
4135
                if (!empty($extraFieldImage) && isset($extraFieldImage['url'])) {
4136
                    $image = $extraFieldImage['url'];
4137
                }
4138
                $row['image'] = $image;
4139
                if ('0000-00-00 00:00:00' === $row['display_start_date'] || '0000-00-00' === $row['display_start_date']) {
4140
                    $row['display_start_date'] = null;
4141
                }
4142
4143
                if ('0000-00-00 00:00:00' === $row['display_end_date'] || '0000-00-00' === $row['display_end_date']) {
4144
                    $row['display_end_date'] = null;
4145
                }
4146
4147
                if ('0000-00-00 00:00:00' === $row['access_start_date'] || '0000-00-00' === $row['access_start_date']) {
4148
                    $row['access_start_date'] = null;
4149
                }
4150
4151
                if ('0000-00-00 00:00:00' === $row['access_end_date'] || '0000-00-00' === $row['access_end_date']) {
4152
                    $row['access_end_date'] = null;
4153
                }
4154
4155
                if ('0000-00-00 00:00:00' === $row['coach_access_start_date'] ||
4156
                    '0000-00-00' === $row['coach_access_start_date']
4157
                ) {
4158
                    $row['coach_access_start_date'] = null;
4159
                }
4160
4161
                if ('0000-00-00 00:00:00' === $row['coach_access_end_date'] ||
4162
                    '0000-00-00' === $row['coach_access_end_date']
4163
                ) {
4164
                    $row['coach_access_end_date'] = null;
4165
                }
4166
4167
                $sessions[$row['id']] = $row;
4168
            }
4169
        }
4170
4171
        return $sessions;
4172
    }
4173
4174
    /**
4175
     * Gets the list (or the count) of courses by session filtered by access_url.
4176
     *
4177
     * @param int    $session_id  The session id
4178
     * @param string $course_name The course code
4179
     * @param string $orderBy     Field to order the data
4180
     * @param bool   $getCount    Optional. Count the session courses
4181
     *
4182
     * @return array|int List of courses. Whether $getCount is true, return the count
4183
     */
4184
    public static function get_course_list_by_session_id(
4185
        $session_id,
4186
        $course_name = '',
4187
        $orderBy = null,
4188
        $getCount = false
4189
    ) {
4190
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4191
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4192
        $session_id = (int) $session_id;
4193
        $sqlSelect = '*, c.id, c.id as real_id, c.code as course_code';
4194
4195
        if ($getCount) {
4196
            $sqlSelect = 'COUNT(1) as count';
4197
        }
4198
4199
        // select the courses
4200
        $sql = "SELECT $sqlSelect
4201
                FROM $tbl_course c
4202
                INNER JOIN $tbl_session_rel_course src
4203
                ON (c.id = src.c_id)
4204
		        WHERE src.session_id = '$session_id' ";
4205
4206
        if (!empty($course_name)) {
4207
            $course_name = Database::escape_string($course_name);
4208
            $sql .= " AND c.title LIKE '%$course_name%' ";
4209
        }
4210
4211
        if (!empty($orderBy)) {
4212
            $orderBy = Database::escape_string($orderBy);
4213
            $orderBy = " ORDER BY $orderBy";
4214
        } else {
4215
            if (self::orderCourseIsEnabled()) {
4216
                $orderBy .= ' ORDER BY position ';
4217
            } else {
4218
                $orderBy .= ' ORDER BY title ';
4219
            }
4220
        }
4221
4222
        $sql .= Database::escape_string($orderBy);
4223
        $result = Database::query($sql);
4224
        $num_rows = Database::num_rows($result);
4225
        $courses = [];
4226
        if ($num_rows > 0) {
4227
            if ($getCount) {
4228
                $count = Database::fetch_assoc($result);
4229
4230
                return (int) $count['count'];
4231
            }
4232
4233
            while ($row = Database::fetch_assoc($result)) {
4234
                $courses[$row['real_id']] = $row;
4235
            }
4236
        }
4237
4238
        return $courses;
4239
    }
4240
4241
    /**
4242
     * Gets the list of courses by session filtered by access_url.
4243
     *
4244
     * @param $userId
4245
     * @param $sessionId
4246
     * @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...
4247
     * @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...
4248
     * @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...
4249
     * @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...
4250
     * @param bool   $getCount
4251
     * @param string $keyword
4252
     *
4253
     * @return array
4254
     */
4255
    public static function getAllCoursesFollowedByUser(
4256
        $userId,
4257
        $sessionId,
4258
        $from = null,
4259
        $limit = null,
4260
        $column = null,
4261
        $direction = null,
4262
        $getCount = false,
4263
        $keyword = ''
4264
    ) {
4265
        if (empty($sessionId)) {
4266
            $sessionsSQL = self::get_sessions_followed_by_drh(
4267
                $userId,
4268
                null,
4269
                null,
4270
                null,
4271
                true,
4272
                true
4273
            );
4274
        } else {
4275
            $sessionsSQL = intval($sessionId);
4276
        }
4277
4278
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4279
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4280
4281
        if ($getCount) {
4282
            $select = "SELECT COUNT(DISTINCT(c.code)) as count ";
4283
        } else {
4284
            $select = "SELECT DISTINCT c.* ";
4285
        }
4286
4287
        $keywordCondition = null;
4288
        if (!empty($keyword)) {
4289
            $keyword = Database::escape_string($keyword);
4290
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4291
        }
4292
4293
        // Select the courses
4294
        $sql = "$select
4295
                FROM $tbl_course c
4296
                INNER JOIN $tbl_session_rel_course src
4297
                ON c.id = src.c_id
4298
		        WHERE
4299
		            src.session_id IN ($sessionsSQL)
4300
		            $keywordCondition
4301
		        ";
4302
        if ($getCount) {
4303
            $result = Database::query($sql);
4304
            $row = Database::fetch_assoc($result);
4305
4306
            return $row['count'];
4307
        }
4308
4309
        if (isset($from) && isset($limit)) {
4310
            $from = intval($from);
4311
            $limit = intval($limit);
4312
            $sql .= " LIMIT $from, $limit";
4313
        }
4314
4315
        $result = Database::query($sql);
4316
        $num_rows = Database::num_rows($result);
4317
        $courses = [];
4318
4319
        if ($num_rows > 0) {
4320
            while ($row = Database::fetch_assoc($result)) {
4321
                $courses[$row['id']] = $row;
4322
            }
4323
        }
4324
4325
        return $courses;
4326
    }
4327
4328
    /**
4329
     * Gets the list of courses by session filtered by access_url.
4330
     *
4331
     * @param int    $session_id
4332
     * @param string $course_name
4333
     *
4334
     * @return array list of courses
4335
     */
4336
    public static function get_course_list_by_session_id_like($session_id, $course_name = '')
4337
    {
4338
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4339
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4340
4341
        $session_id = (int) $session_id;
4342
        $course_name = Database::escape_string($course_name);
4343
4344
        // select the courses
4345
        $sql = "SELECT c.id, c.title FROM $tbl_course c
4346
                INNER JOIN $tbl_session_rel_course src
4347
                ON c.id = src.c_id
4348
		        WHERE ";
4349
4350
        if (!empty($session_id)) {
4351
            $sql .= "src.session_id LIKE '$session_id' AND ";
4352
        }
4353
4354
        if (!empty($course_name)) {
4355
            $sql .= "UPPER(c.title) LIKE UPPER('%$course_name%') ";
4356
        }
4357
4358
        $sql .= "ORDER BY title;";
4359
        $result = Database::query($sql);
4360
        $num_rows = Database::num_rows($result);
4361
        $courses = [];
4362
        if ($num_rows > 0) {
4363
            while ($row = Database::fetch_assoc($result)) {
4364
                $courses[$row['id']] = $row;
4365
            }
4366
        }
4367
4368
        return $courses;
4369
    }
4370
4371
    /**
4372
     * Gets the count of courses by session filtered by access_url.
4373
     *
4374
     * @param int session id
4375
     * @param string $keyword
4376
     *
4377
     * @return array list of courses
4378
     */
4379
    public static function getCourseCountBySessionId($session_id, $keyword = '')
4380
    {
4381
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4382
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4383
        $session_id = (int) $session_id;
4384
4385
        // select the courses
4386
        $sql = "SELECT COUNT(c.code) count
4387
                FROM $tbl_course c
4388
                INNER JOIN $tbl_session_rel_course src
4389
                ON c.id = src.c_id
4390
		        WHERE src.session_id = '$session_id' ";
4391
4392
        $keywordCondition = null;
4393
        if (!empty($keyword)) {
4394
            $keyword = Database::escape_string($keyword);
4395
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4396
        }
4397
        $sql .= $keywordCondition;
4398
4399
        $result = Database::query($sql);
4400
        $num_rows = Database::num_rows($result);
4401
        if ($num_rows > 0) {
4402
            $row = Database::fetch_assoc($result);
4403
4404
            return $row['count'];
4405
        }
4406
4407
        return null;
4408
    }
4409
4410
    /**
4411
     * Get the session id based on the original id and field name in the extra fields.
4412
     * Returns 0 if session was not found.
4413
     *
4414
     * @param string $value    Original session id
4415
     * @param string $variable Original field name
4416
     *
4417
     * @return int Session id
4418
     */
4419
    public static function getSessionIdFromOriginalId($value, $variable)
4420
    {
4421
        $extraFieldValue = new ExtraFieldValue('session');
4422
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4423
            $variable,
4424
            $value
4425
        );
4426
4427
        if (!empty($result)) {
4428
            return $result['item_id'];
4429
        }
4430
4431
        return 0;
4432
    }
4433
4434
    /**
4435
     * Get users by session.
4436
     *
4437
     * @param int  $id       session id
4438
     * @param int  $status   filter by status coach = 2
4439
     * @param bool $getCount Optional. Allow get the number of rows from the result
4440
     * @param int  $urlId
4441
     *
4442
     * @return array|int A list with an user list. If $getCount is true then return a the count of registers
4443
     */
4444
    public static function get_users_by_session(
4445
        $id,
4446
        $status = null,
4447
        $getCount = false,
4448
        $urlId = 0
4449
    ) {
4450
        if (empty($id)) {
4451
            return [];
4452
        }
4453
        $id = (int) $id;
4454
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
4455
4456
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4457
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4458
        $table_access_url_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4459
4460
        $selectedField = '
4461
            u.id as user_id, u.lastname, u.firstname, u.username, su.relation_type, au.access_url_id,
4462
            su.moved_to, su.moved_status, su.moved_at, su.registered_at
4463
        ';
4464
4465
        if ($getCount) {
4466
            $selectedField = 'count(1) AS count';
4467
        }
4468
4469
        $sql = "SELECT $selectedField
4470
                FROM $tbl_user u
4471
                INNER JOIN $tbl_session_rel_user su
4472
                ON u.id = su.user_id AND
4473
                su.session_id = $id
4474
                LEFT OUTER JOIN $table_access_url_user au
4475
                ON (au.user_id = u.id)
4476
                ";
4477
4478
        if (is_numeric($status)) {
4479
            $status = (int) $status;
4480
            $sql .= " WHERE su.relation_type = $status AND (au.access_url_id = $urlId OR au.access_url_id is null)";
4481
        } else {
4482
            $sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
4483
        }
4484
4485
        $sql .= ' AND u.active <> '.USER_SOFT_DELETED.' ORDER BY su.relation_type, ';
4486
        $sql .= api_sort_by_first_name() ? ' u.firstname, u.lastname' : '  u.lastname, u.firstname';
4487
4488
        $result = Database::query($sql);
4489
        if ($getCount) {
4490
            $count = Database::fetch_assoc($result);
4491
            if ($count) {
4492
                return (int) $count['count'];
4493
            }
4494
4495
            return 0;
4496
        }
4497
4498
        $return = [];
4499
        while ($row = Database::fetch_assoc($result)) {
4500
            $return[] = $row;
4501
        }
4502
4503
        return $return;
4504
    }
4505
4506
    /**
4507
     * The general coach (session_rel_user.relation_type = Session::GENERAL_COACH).
4508
     *
4509
     * @param int  $user_id         user id
4510
     * @param bool $asPlatformAdmin The user is platform admin, return everything
4511
     *
4512
     * @return array
4513
     */
4514
    public static function get_sessions_by_general_coach($user_id, $asPlatformAdmin = false)
4515
    {
4516
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
4517
        $user_id = (int) $user_id;
4518
4519
        $innerJoin = '';
4520
        $whereConditions = '';
4521
4522
        if (!$asPlatformAdmin) {
4523
            $innerJoin = " INNER JOIN session_rel_user AS sru ON (s.id = sru.session_id) ";
4524
            $whereConditions = "sru.user_id = $user_id AND sru.relation_type = ".Session::GENERAL_COACH;
4525
        }
4526
4527
        if (api_is_multiple_url_enabled()) {
4528
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4529
            $access_url_id = api_get_current_access_url_id();
4530
4531
            if (-1 != $access_url_id) {
4532
                $innerJoin .= " INNER JOIN $tblSessionRelAccessUrl session_rel_url
4533
                    ON (s.id = access_url_rel_session.session_id)";
4534
                $whereConditions .= " AND access_url_rel_session.access_url_id = $access_url_id";
4535
            }
4536
        }
4537
        $sql = "SELECT s.* FROM $sessionTable AS s $innerJoin ";
4538
        if (!empty($whereConditions)) {
4539
            $sql .= "WHERE $whereConditions ";
4540
        }
4541
        $sql .= "ORDER BY s.title";
4542
        $result = Database::query($sql);
4543
4544
        return Database::store_result($result, 'ASSOC');
4545
    }
4546
4547
    /**
4548
     * @param int $user_id
4549
     * @param int $courseId
4550
     * @param int $session_id
4551
     *
4552
     * @return array|bool
4553
     */
4554
    public static function get_user_status_in_course_session($user_id, $courseId, $session_id)
4555
    {
4556
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4557
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4558
        $sql = "SELECT session_rcru.status
4559
                FROM $table session_rcru
4560
                INNER JOIN $tbl_user user
4561
                ON (session_rcru.user_id = user.id)
4562
                WHERE
4563
                    session_rcru.session_id = '".intval($session_id)."' AND
4564
                    session_rcru.c_id ='".intval($courseId)."' AND
4565
                    user.id = ".intval($user_id);
4566
4567
        $result = Database::query($sql);
4568
        $status = false;
4569
        if (Database::num_rows($result)) {
4570
            $status = Database::fetch_row($result);
4571
            $status = $status['0'];
4572
        }
4573
4574
        return $status;
4575
    }
4576
4577
    /**
4578
     * Gets user status within a session.
4579
     *
4580
     * @param int $userId
4581
     * @param int $sessionId
4582
     *
4583
     * @return SessionRelUser
4584
     */
4585
    public static function getUserStatusInSession($userId, $sessionId)
4586
    {
4587
        $em = Database::getManager();
4588
        $subscriptions = $em
4589
            ->getRepository(SessionRelUser::class)
4590
            ->findBy(['session' => $sessionId, 'user' => $userId]);
4591
4592
        /** @var SessionRelUser $subscription */
4593
        $subscription = current($subscriptions);
4594
4595
        return $subscription;
4596
    }
4597
4598
    /**
4599
     * @param int $id
4600
     *
4601
     * @return array
4602
     */
4603
    public static function get_all_sessions_by_promotion($id)
4604
    {
4605
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4606
4607
        return Database::select(
4608
            '*',
4609
            $table,
4610
            ['where' => ['promotion_id = ?' => $id]]
4611
        );
4612
    }
4613
4614
    /**
4615
     * @param int   $promotion_id
4616
     * @param array $list
4617
     */
4618
    public static function subscribe_sessions_to_promotion($promotion_id, $list)
4619
    {
4620
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4621
        $params = [];
4622
        $params['promotion_id'] = 0;
4623
        Database::update(
4624
            $table,
4625
            $params,
4626
            ['promotion_id = ?' => $promotion_id]
4627
        );
4628
4629
        $params['promotion_id'] = $promotion_id;
4630
        if (!empty($list)) {
4631
            foreach ($list as $session_id) {
4632
                $session_id = (int) $session_id;
4633
                Database::update($table, $params, ['id = ?' => $session_id]);
4634
            }
4635
        }
4636
    }
4637
4638
    /**
4639
     * Updates a session status.
4640
     *
4641
     * @param int session id
4642
     * @param int status
4643
     */
4644
    public static function set_session_status($session_id, $status)
4645
    {
4646
        $t = Database::get_main_table(TABLE_MAIN_SESSION);
4647
        $params['visibility'] = $status;
4648
        Database::update($t, $params, ['id = ?' => $session_id]);
4649
    }
4650
4651
    /**
4652
     * Copies a session with the same data to a new session.
4653
     * The new copy is not assigned to the same promotion.
4654
     *
4655
     * @param int  $id                         Session ID
4656
     * @param bool $copy_courses               Whether to copy the relationship with courses
4657
     * @param bool $copyTeachersAndDrh
4658
     * @param bool $create_new_courses         New courses will be created
4659
     * @param bool $set_exercises_lp_invisible Set exercises and LPs in the new session to invisible by default
4660
     * @param bool $copyWithSessionContent     Copy course session content into the courses
4661
     *
4662
     * @return int The new session ID on success, 0 otherwise
4663
     *
4664
     * @see subscribe_sessions_to_promotions() for that.
4665
     *
4666
     * @todo make sure the extra session fields are copied too
4667
     */
4668
    public static function copy(
4669
        int $id,
4670
        bool $copy_courses = true,
4671
        bool $copyTeachersAndDrh = true,
4672
        bool $create_new_courses = false,
4673
        bool $set_exercises_lp_invisible = false,
4674
        bool $copyWithSessionContent = false,
4675
    ) {
4676
        $id = (int) $id;
4677
        $s = self::fetch($id);
4678
4679
        if (empty($s)) {
4680
            return false;
4681
        }
4682
4683
        // Check all dates before copying
4684
        // Get timestamp for now in UTC - see http://php.net/manual/es/function.time.php#117251
4685
        $now = time() - date('Z');
4686
        // Timestamp in one month
4687
        $inOneMonth = $now + (30 * 24 * 3600);
4688
        $inOneMonth = api_get_local_time($inOneMonth);
4689
        if (api_strtotime($s['access_start_date']) < $now) {
4690
            $s['access_start_date'] = api_get_local_time($now);
4691
        } else {
4692
            $s['access_start_date'] = api_get_local_time($s['access_start_date']);
4693
        }
4694
        if (api_strtotime($s['display_start_date']) < $now) {
4695
            $s['display_start_date'] = api_get_local_time($now);
4696
        } else {
4697
            $s['display_start_date'] = api_get_local_time($s['display_start_date']);
4698
        }
4699
        if (api_strtotime($s['coach_access_start_date']) < $now) {
4700
            $s['coach_access_start_date'] = api_get_local_time($now);
4701
        } else {
4702
            $s['coach_access_start_date'] = api_get_local_time($s['coach_access_start_date']);
4703
        }
4704
        if (api_strtotime($s['access_end_date']) < $now) {
4705
            $s['access_end_date'] = $inOneMonth;
4706
        } else {
4707
            $s['access_end_date'] = api_get_local_time($s['access_end_date']);
4708
        }
4709
        if (api_strtotime($s['display_end_date']) < $now) {
4710
            $s['display_end_date'] = $inOneMonth;
4711
        } else {
4712
            $s['display_end_date'] = api_get_local_time($s['display_end_date']);
4713
        }
4714
        if (api_strtotime($s['coach_access_end_date']) < $now) {
4715
            $s['coach_access_end_date'] = $inOneMonth;
4716
        } else {
4717
            $s['coach_access_end_date'] = api_get_local_time($s['coach_access_end_date']);
4718
        }
4719
4720
        $extraFieldValue = new ExtraFieldValue('session');
4721
        $extraFieldsValues = $extraFieldValue->getAllValuesByItem($id);
4722
        $extraFieldsValuesToCopy = [];
4723
        if (!empty($extraFieldsValues)) {
4724
            foreach ($extraFieldsValues as $extraFieldValue) {
4725
                //$extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4726
                $extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']]['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4727
            }
4728
        }
4729
4730
        // @todo fix session image url copy.
4731
        /*if (isset($extraFieldsValuesToCopy['extra_image']) &&
4732
            isset($extraFieldsValuesToCopy['extra_image']['extra_image'])
4733
        ) {
4734
            $extraFieldsValuesToCopy['extra_image'] = [
4735
                'tmp_name' => api_get_path(SYS_UPLOAD_PATH).$extraFieldsValuesToCopy['extra_image']['extra_image'],
4736
                'error' => 0,
4737
            ];
4738
        }*/
4739
4740
        $generalCoaches = self::getGeneralCoachesIdForSession($id);
4741
4742
        // Now try to create the session
4743
        $sid = self::create_session(
4744
            $s['title'].' '.get_lang('Copy'),
4745
            $s['access_start_date'],
4746
            $s['access_end_date'],
4747
            $s['display_start_date'],
4748
            $s['display_end_date'],
4749
            $s['coach_access_start_date'],
4750
            $s['coach_access_end_date'],
4751
            $generalCoaches,
4752
            $s['session_category_id'],
4753
            (int) $s['visibility'],
4754
            true,
4755
            $s['duration'],
4756
            $s['description'],
4757
            $s['show_description'],
4758
            $extraFieldsValuesToCopy
4759
        );
4760
4761
        if (!is_numeric($sid) || empty($sid)) {
4762
            return false;
4763
        }
4764
4765
        if ($copy_courses) {
4766
            // Register courses from the original session to the new session
4767
            $courses = self::get_course_list_by_session_id($id);
4768
            $short_courses = $new_short_courses = [];
4769
            if (is_array($courses) && count($courses) > 0) {
4770
                foreach ($courses as $course) {
4771
                    $short_courses[] = $course;
4772
                }
4773
            }
4774
4775
            // We will copy the current courses of the session to new courses
4776
            if (!empty($short_courses)) {
4777
                if ($create_new_courses) {
4778
                    api_set_more_memory_and_time_limits();
4779
                    $params = [];
4780
                    $params['skip_lp_dates'] = true;
4781
4782
                    foreach ($short_courses as $course_data) {
4783
                        $course = CourseManager::copy_course_simple(
4784
                            $course_data['title'].' '.get_lang('Copy'),
4785
                            $course_data['course_code'],
4786
                            $id,
4787
                            $sid,
4788
                            $params
4789
                        );
4790
4791
                        if (null !== $course) {
4792
                            $course_info = api_get_course_info($course->getCode());
4793
                            //By default new elements are invisible
4794
                            if ($set_exercises_lp_invisible) {
4795
                                $list = new LearnpathList('', $course_info, $sid);
4796
                                $flat_list = $list->get_flat_list();
4797
                                if (!empty($flat_list)) {
4798
                                    foreach ($flat_list as $lp_id => $data) {
4799
                                        // @todo fix
4800
                                        /*api_item_property_update(
4801
                                            $course_info,
4802
                                            TOOL_LEARNPATH,
4803
                                            $lp_id,
4804
                                            'invisible',
4805
                                            api_get_user_id(),
4806
                                            0,
4807
                                            0,
4808
                                            0,
4809
                                            0,
4810
                                            $sid
4811
                                        );*/
4812
                                    }
4813
                                }
4814
                                $quiz_table = Database::get_course_table(TABLE_QUIZ_TEST);
4815
                                $course_id = $course_info['real_id'];
4816
                                //@todo check this query
4817
                                $sql = "UPDATE $quiz_table SET active = 0
4818
                                        WHERE c_id = $course_id AND session_id = $sid";
4819
                                Database::query($sql);
4820
                            }
4821
                            $new_short_courses[] = $course_info['real_id'];
4822
                        }
4823
                    }
4824
                } else {
4825
                    foreach ($short_courses as $course_data) {
4826
                        $new_short_courses[] = $course_data['id'];
4827
                    }
4828
                }
4829
4830
                $short_courses = $new_short_courses;
4831
                self::add_courses_to_session($sid, $short_courses, true);
4832
4833
                if ($copyWithSessionContent) {
4834
                    foreach ($courses as $course) {
4835
                        CourseManager::copy_course(
4836
                            $course['code'],
4837
                            $id,
4838
                            $course['code'],
4839
                            $sid,
4840
                            [],
4841
                            false,
4842
                            true
4843
                        );
4844
                    }
4845
                }
4846
4847
                if (false === $create_new_courses && $copyTeachersAndDrh) {
4848
                    foreach ($short_courses as $courseItemId) {
4849
                        $coachList = self::getCoachesByCourseSession($id, $courseItemId);
4850
                        foreach ($coachList as $userId) {
4851
                            self::set_coach_to_course_session($userId, $sid, $courseItemId);
4852
                        }
4853
                    }
4854
                }
4855
            }
4856
        }
4857
4858
        if ($copyTeachersAndDrh) {
4859
            // Register users from the original session to the new session
4860
            $users = self::get_users_by_session($id);
4861
            if (!empty($users)) {
4862
                $userListByStatus = [];
4863
                foreach ($users as $userData) {
4864
                    $userData['relation_type'] = (int) $userData['relation_type'];
4865
                    $userListByStatus[$userData['relation_type']][] = $userData;
4866
                }
4867
4868
                foreach ($userListByStatus as $status => $userList) {
4869
                    $userList = array_column($userList, 'user_id');
4870
                    switch ($status) {
4871
                        case 0:
4872
                            /*self::subscribeUsersToSession(
4873
                                $sid,
4874
                                $userList,
4875
                                SESSION_VISIBLE_READ_ONLY,
4876
                                false,
4877
                                true
4878
                            );*/
4879
                            break;
4880
                        case 1:
4881
                            // drh users
4882
                            foreach ($userList as $drhId) {
4883
                                $userInfo = api_get_user_info($drhId);
4884
                                self::subscribeSessionsToDrh($userInfo, [$sid], false, false);
4885
                            }
4886
                            break;
4887
                    }
4888
                }
4889
            }
4890
        }
4891
4892
        return $sid;
4893
    }
4894
4895
    /**
4896
     * Get the number of sessions.
4897
     *
4898
     * @param int $access_url_id ID of the URL we want to filter on (optional)
4899
     *
4900
     * @return int Number of sessions
4901
     */
4902
    public static function count_sessions($access_url_id = 0)
4903
    {
4904
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
4905
        $access_url_rel_session_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4906
        $access_url_id = (int) $access_url_id;
4907
        $sql = "SELECT count(s.id) FROM $session_table s";
4908
        if (!empty($access_url_id)) {
4909
            $sql .= ", $access_url_rel_session_table u ".
4910
                " WHERE s.id = u.session_id AND u.access_url_id = $access_url_id";
4911
        }
4912
        $res = Database::query($sql);
4913
        $row = Database::fetch_row($res);
4914
4915
        return $row[0];
4916
    }
4917
4918
    public static function cantEditSession(?Session $session = null, bool $checkSession = true): bool
4919
    {
4920
        if (!self::allowToManageSessions()) {
4921
            return false;
4922
        }
4923
4924
        if (api_is_platform_admin() && self::allowed($session)) {
4925
            return true;
4926
        }
4927
4928
        if ($checkSession) {
4929
            if (self::allowed($session)) {
4930
                return true;
4931
            }
4932
4933
            return false;
4934
        }
4935
4936
        return true;
4937
    }
4938
4939
    /**
4940
     * Protect a session to be edited.
4941
     *
4942
     * @return mixed | bool true if pass the check, api_not_allowed otherwise
4943
     */
4944
    public static function protectSession(?Session $session = null, bool $checkSession = true)
4945
    {
4946
        if (!self::cantEditSession($session, $checkSession)) {
4947
            api_not_allowed(true);
4948
        }
4949
    }
4950
4951
    public static function allowToManageSessions(): bool
4952
    {
4953
        if (self::allowManageAllSessions()) {
4954
            return true;
4955
        }
4956
4957
        if (api_is_teacher() && 'true' === api_get_setting('allow_teachers_to_create_sessions')) {
4958
            return true;
4959
        }
4960
4961
        return false;
4962
    }
4963
4964
    /**
4965
     * @return bool
4966
     */
4967
    public static function allowOnlyMySessions()
4968
    {
4969
        if (self::allowToManageSessions() &&
4970
            !api_is_platform_admin() &&
4971
            api_is_teacher()
4972
        ) {
4973
            return true;
4974
        }
4975
4976
        return false;
4977
    }
4978
4979
    /**
4980
     * @return bool
4981
     */
4982
    public static function allowManageAllSessions()
4983
    {
4984
        if (api_is_platform_admin() || api_is_session_admin()) {
4985
            return true;
4986
        }
4987
4988
        return false;
4989
    }
4990
4991
    /**
4992
     * @param $id
4993
     *
4994
     * @return bool
4995
     */
4996
    public static function protect_teacher_session_edit($id)
4997
    {
4998
        if (!api_is_coach($id) && !api_is_platform_admin()) {
4999
            api_not_allowed(true);
5000
        } else {
5001
            return true;
5002
        }
5003
    }
5004
5005
    /**
5006
     * @param int $courseId
5007
     *
5008
     * @return array
5009
     */
5010
    public static function get_session_by_course($courseId)
5011
    {
5012
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5013
        $table_session = Database::get_main_table(TABLE_MAIN_SESSION);
5014
        $url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
5015
        $courseId = (int) $courseId;
5016
        $urlId = api_get_current_access_url_id();
5017
5018
        if (empty($courseId)) {
5019
            return [];
5020
        }
5021
5022
        $sql = "SELECT title, s.id
5023
                FROM $table_session_course sc
5024
                INNER JOIN $table_session s
5025
                ON (sc.session_id = s.id)
5026
                INNER JOIN $url u
5027
                ON (u.session_id = s.id)
5028
                WHERE
5029
                    u.access_url_id = $urlId AND
5030
                    sc.c_id = '$courseId' ";
5031
        $result = Database::query($sql);
5032
5033
        return Database::store_result($result);
5034
    }
5035
5036
    /**
5037
     * @param int  $userId
5038
     * @param bool $ignoreVisibilityForAdmins
5039
     * @param bool $ignoreTimeLimit
5040
     *
5041
     * @return array
5042
     */
5043
    public static function get_sessions_by_user(
5044
        $userId,
5045
        $ignoreVisibilityForAdmins = false,
5046
        $ignoreTimeLimit = false
5047
    ) {
5048
        $sessionCategories = UserManager::get_sessions_by_category(
5049
            $userId,
5050
            false,
5051
            $ignoreVisibilityForAdmins,
5052
            $ignoreTimeLimit
5053
        );
5054
5055
        $sessionArray = [];
5056
        if (!empty($sessionCategories)) {
5057
            foreach ($sessionCategories as $category) {
5058
                if (isset($category['sessions'])) {
5059
                    foreach ($category['sessions'] as $session) {
5060
                        $sessionArray[] = $session;
5061
                    }
5062
                }
5063
            }
5064
        }
5065
5066
        return $sessionArray;
5067
    }
5068
5069
    /**
5070
     * Imports sessions from a CSV file, creating or updating sessions with related users and courses.
5071
     *
5072
     * @return array Contains the import result with errors, counters, and session IDs.
5073
     */
5074
    public static function importCSV(
5075
        string $file,
5076
        bool $updateSession,
5077
        ?int $defaultUserId = null,
5078
        ?Logger $logger = null,
5079
        array $extraFields = [],
5080
        ?string $extraFieldId = null,
5081
        ?int $daysCoachAccessBeforeBeginning = null,
5082
        ?int $daysCoachAccessAfterBeginning = null,
5083
        int $sessionVisibility = 1,
5084
        array $fieldsToAvoidUpdate = [],
5085
        bool $deleteUsersNotInList = false,
5086
        bool $updateCourseCoaches = false,
5087
        bool $sessionWithCoursesModifier = false,
5088
        bool $addOriginalCourseTeachersAsCourseSessionCoaches = true,
5089
        bool $removeAllTeachersFromCourse = true,
5090
        ?int $showDescription = null,
5091
        array &$teacherBackupList = [],
5092
        array &$groupBackup = []
5093
    ): array {
5094
5095
        $sepCheck = Import::assertCommaSeparated($file, true);
5096
        if ($sepCheck !== true) {
5097
            return [
5098
                'error_message'   => $sepCheck,
5099
                'session_counter' => 0,
5100
                'session_list'    => [],
5101
            ];
5102
        }
5103
5104
        $error_message = null;
5105
        $session_counter = 0;
5106
        $defaultUserId = empty($defaultUserId) ? api_get_user_id() : (int) $defaultUserId;
5107
        $defaultUser = api_get_user_entity($defaultUserId);
5108
5109
        $eol = PHP_SAPI != 'cli' ? '<br />' : PHP_EOL;
5110
5111
        $debug = isset($logger);
5112
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5113
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
5114
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5115
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5116
5117
        $rows = Import::csvToArray($file);
5118
        if (empty($rows) || !is_array($rows)) {
5119
            return [
5120
                'error_message'   => get_lang('The specified file is not CSV format !'),
5121
                'session_counter' => 0,
5122
                'session_list'    => [],
5123
            ];
5124
        }
5125
5126
        $normalizeKey = static function (string $k): string {
5127
            return trim(ltrim($k, "\xEF\xBB\xBF"));
5128
        };
5129
5130
        $normalizedRows = [];
5131
        foreach ($rows as $r) {
5132
            $nr = [];
5133
            foreach ($r as $k => $v) {
5134
                $nr[$normalizeKey($k)] = $v;
5135
            }
5136
            $normalizedRows[] = $nr;
5137
        }
5138
        $rows = $normalizedRows;
5139
        $first = $rows[0] ?? [];
5140
        $required = ['SessionName', 'DateStart', 'DateEnd'];
5141
        foreach ($required as $col) {
5142
            if (!array_key_exists($col, $first)) {
5143
                return [
5144
                    'error_message'   => get_lang("The specified file doesn't contain all needed data !"),
5145
                    'session_counter' => 0,
5146
                    'session_list'    => [],
5147
                ];
5148
            }
5149
        }
5150
5151
        $sessions = $rows;
5152
        $sessionList = [];
5153
        $report = [];
5154
        foreach ($sessions as $enreg) {
5155
            $user_counter = 0;
5156
            $course_counter = 0;
5157
5158
            if (!empty($extraFields)) {
5159
                foreach ($extraFields as $original => $to) {
5160
                    $enreg[$to] = $enreg[$original] ?? null;
5161
                }
5162
            }
5163
5164
            $session_name = $enreg['SessionName'];
5165
5166
            if ($debug) {
5167
                $logger->debug('---------------------------------------');
5168
                $logger->debug("Sessions - Start process of session: $session_name");
5169
                $logger->debug('---------------------------------------');
5170
            }
5171
5172
            // Default visibility
5173
            $visibilityAfterExpirationPerSession = $sessionVisibility;
5174
            if (isset($enreg['VisibilityAfterExpiration'])) {
5175
                $visibility = $enreg['VisibilityAfterExpiration'];
5176
                switch ($visibility) {
5177
                    case 'read_only':
5178
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE_READ_ONLY;
5179
                        break;
5180
                    case 'accessible':
5181
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE;
5182
                        break;
5183
                    case 'not_accessible':
5184
                        $visibilityAfterExpirationPerSession = SESSION_INVISIBLE;
5185
                        break;
5186
                }
5187
            }
5188
5189
            if (empty($session_name)) {
5190
                continue;
5191
            }
5192
5193
            $displayAccessStartDate = $enreg['DisplayStartDate'] ?? $enreg['DateStart'];
5194
            $displayAccessEndDate = $enreg['DisplayEndDate'] ?? $enreg['DateEnd'];
5195
            $coachAccessStartDate = $enreg['CoachStartDate'] ?? $enreg['DateStart'];
5196
            $coachAccessEndDate = $enreg['CoachEndDate'] ?? $enreg['DateEnd'];
5197
            $dateStart = date('Y-m-d H:i:s', strtotime(trim($enreg['DateStart'])));
5198
            $displayAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($displayAccessStartDate)));
5199
            $coachAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($coachAccessStartDate)));
5200
            $dateEnd = self::normalizeDateEnd($enreg['DateEnd']);
5201
            $displayAccessEndDate = self::normalizeDateEnd($displayAccessEndDate);
5202
            $coachAccessEndDate = self::normalizeDateEnd($coachAccessEndDate);
5203
            $session_category_id = $enreg['SessionCategory'] ?? null;
5204
            $sessionDescription = $enreg['SessionDescription'] ?? null;
5205
            $classes = isset($enreg['Classes']) ? explode('|', $enreg['Classes']) : [];
5206
            $extraParams = [];
5207
            if (!is_null($showDescription)) {
5208
                $extraParams['show_description'] = intval($showDescription);
5209
            }
5210
5211
            $coachBefore = '';
5212
            $coachAfter = '';
5213
            if (!empty($daysCoachAccessBeforeBeginning) && !empty($daysCoachAccessAfterBeginning)) {
5214
                $date = new \DateTime($dateStart);
5215
                $interval = new DateInterval('P'.$daysCoachAccessBeforeBeginning.'D');
5216
                $date->sub($interval);
5217
                $coachBefore = $date->format('Y-m-d h:i');
5218
                $coachAccessStartDate = $coachBefore;
5219
                $coachBefore = api_get_utc_datetime($coachBefore);
5220
5221
                $date = new \DateTime($dateEnd);
5222
                $interval = new DateInterval('P'.$daysCoachAccessAfterBeginning.'D');
5223
                $date->add($interval);
5224
                $coachAfter = $date->format('Y-m-d h:i');
5225
                $coachAccessEndDate = $coachAfter;
5226
                $coachAfter = api_get_utc_datetime($coachAfter);
5227
            }
5228
5229
            $dateStart = api_get_utc_datetime($dateStart);
5230
            $dateEnd = api_get_utc_datetime($dateEnd);
5231
            $displayAccessStartDate = api_get_utc_datetime($displayAccessStartDate);
5232
            $displayAccessEndDate = api_get_utc_datetime($displayAccessEndDate);
5233
            $coachAccessStartDate = api_get_utc_datetime($coachAccessStartDate);
5234
            $coachAccessEndDate = api_get_utc_datetime($coachAccessEndDate);
5235
5236
            if (!empty($sessionDescription)) {
5237
                $extraParams['description'] = $sessionDescription;
5238
            }
5239
5240
            if (!empty($session_category_id)) {
5241
                $extraParams['session_category_id'] = $session_category_id;
5242
            }
5243
5244
            // Searching a general coach.
5245
            if (!empty($enreg['Coach'])) {
5246
                $coach_id = UserManager::get_user_id_from_username($enreg['Coach']);
5247
                if (false === $coach_id) {
5248
                    // If the coach-user does not exist - I'm the coach.
5249
                    $coach_id = $defaultUserId;
5250
                }
5251
            } else {
5252
                $coach_id = $defaultUserId;
5253
            }
5254
5255
            $coach = api_get_user_entity($coach_id);
5256
5257
            $usersRaw = (string)($enreg['Users'] ?? '');
5258
            $users = $usersRaw === ''
5259
                ? []
5260
                : array_values(array_filter(array_map('trim', explode('|', $usersRaw)), 'strlen'));
5261
            $courses = isset($enreg['Courses']) && $enreg['Courses'] !== '' ? explode('|', $enreg['Courses']) : [];
5262
5263
            $deleteOnlyCourseCoaches = false;
5264
            if (1 == count($courses)) {
5265
                if ($logger) {
5266
                    $logger->debug('Only one course delete old coach list');
5267
                }
5268
                $deleteOnlyCourseCoaches = true;
5269
            }
5270
5271
            if (!$updateSession) {
5272
                // Create a session.
5273
                $unique_name = false;
5274
                $i = 0;
5275
                // Change session name, verify that session doesn't exist.
5276
                $suffix = null;
5277
                while (!$unique_name) {
5278
                    if ($i > 1) {
5279
                        $suffix = ' - '.$i;
5280
                    }
5281
                    $sql = 'SELECT id FROM '.$tbl_session.'
5282
                                WHERE title = "'.Database::escape_string($session_name).$suffix.'"';
5283
                    $rs = Database::query($sql);
5284
                    if (Database::result($rs, 0, 0)) {
5285
                        $i++;
5286
                    } else {
5287
                        $unique_name = true;
5288
                        $session_name .= $suffix;
5289
                    }
5290
                }
5291
5292
                $sessionParams = [
5293
                    'title' => $session_name,
5294
                    'access_start_date' => $dateStart,
5295
                    'access_end_date' => $dateEnd,
5296
                    'display_start_date' => $displayAccessStartDate,
5297
                    'display_end_date' => $displayAccessEndDate,
5298
                    'coach_access_start_date' => $coachAccessStartDate,
5299
                    'coach_access_end_date' => $coachAccessEndDate,
5300
                    'visibility' => $visibilityAfterExpirationPerSession,
5301
                    'nbr_users' => 0,
5302
                    'nbr_courses' => 0,
5303
                    'nbr_classes' => 0,
5304
                    'status' => 0,
5305
                    'duration' => 0,
5306
                ];
5307
5308
                if (!empty($extraParams)) {
5309
                    $sessionParams = array_merge($sessionParams, $extraParams);
5310
                }
5311
                // Creating the session.
5312
                $session_id = Database::insert($tbl_session, $sessionParams);
5313
                $session = api_get_session_entity($session_id);
5314
                if ($session_id) {
5315
5316
                    $em = Database::getManager();
5317
                    $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5318
                    $defaultUser = $em->contains($defaultUser) ? $defaultUser : $em->merge($defaultUser);
5319
5320
                    $session->addUserInSession(Session::GENERAL_COACH, $coach);
5321
                    $session->addUserInSession(Session::GENERAL_COACH, $defaultUser);
5322
                    $em->flush();
5323
5324
                    foreach ($enreg as $key => $value) {
5325
                        if ('extra_' === substr($key, 0, 6)) { //an extra field
5326
                            self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5327
                        }
5328
                    }
5329
                    if ($debug) {
5330
                        $logger->debug("Session created: #$session_id - $session_name");
5331
                    }
5332
                } else {
5333
                    if ($debug) {
5334
                        $message = "Sessions - Session NOT created: $session_name";
5335
                        $logger->debug($message);
5336
                        $report[] = $message;
5337
                    }
5338
                }
5339
                $session_counter++;
5340
            } else {
5341
                $sessionId = null;
5342
                if (isset($extraFields) && !empty($extraFields) && !empty($enreg['extra_'.$extraFieldId])) {
5343
                    $sessionId = self::getSessionIdFromOriginalId($enreg['extra_'.$extraFieldId], $extraFieldId);
5344
                    if (empty($sessionId)) {
5345
                        $my_session_result = false;
5346
                    } else {
5347
                        $my_session_result = true;
5348
                    }
5349
                } else {
5350
                    $my_session_result = self::get_session_by_name($enreg['SessionName']);
5351
                }
5352
5353
                if (false === $my_session_result) {
5354
                    // One more check
5355
                    $sessionExistsWithName = self::get_session_by_name($session_name);
5356
                    if ($sessionExistsWithName) {
5357
                        if ($debug) {
5358
                            $message = "Skip Session - Trying to update a session, but name already exists: $session_name";
5359
                            $logger->debug($message);
5360
                            $report[] = $message;
5361
                        }
5362
                        continue;
5363
                    }
5364
5365
                    $sessionParams = [
5366
                        'title' => $session_name,
5367
                        'access_start_date' => $dateStart,
5368
                        'access_end_date' => $dateEnd,
5369
                        'display_start_date' => $displayAccessStartDate,
5370
                        'display_end_date' => $displayAccessEndDate,
5371
                        'coach_access_start_date' => $coachAccessStartDate,
5372
                        'coach_access_end_date' => $coachAccessEndDate,
5373
                        'visibility' => $visibilityAfterExpirationPerSession,
5374
                        'nbr_users' => 0,
5375
                        'nbr_courses' => 0,
5376
                        'nbr_classes' => 0,
5377
                        'status' => 0,
5378
                        'duration' => 0,
5379
                    ];
5380
5381
                    if (!empty($extraParams)) {
5382
                        $sessionParams = array_merge($sessionParams, $extraParams);
5383
                    }
5384
                    $session_id = Database::insert($tbl_session, $sessionParams);
5385
5386
                    if ($session_id) {
5387
                        $session = api_get_session_entity($session_id);
5388
5389
                        $session
5390
                            ->addUserInSession(Session::GENERAL_COACH, $coach)
5391
                            ->addUserInSession(Session::GENERAL_COACH, $defaultUser)
5392
                        ;
5393
                        Database::getManager()->flush();
5394
5395
                        foreach ($enreg as $key => $value) {
5396
                            if ('extra_' == substr($key, 0, 6)) { //an extra field
5397
                                self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5398
                            }
5399
                        }
5400
                        if ($debug) {
5401
                            $logger->debug("Sessions - #$session_id created: $session_name");
5402
                        }
5403
5404
                        // Delete session-user relation only for students
5405
                        $sql = "DELETE FROM $tbl_session_user
5406
                                    WHERE session_id = '$session_id' AND relation_type = ".Session::STUDENT;
5407
                        Database::query($sql);
5408
5409
                        $sql = "DELETE FROM $tbl_session_course WHERE session_id = '$session_id'";
5410
                        Database::query($sql);
5411
5412
                        // Delete session-course-user relationships students and coaches.
5413
                        if ($updateCourseCoaches) {
5414
                            $sql = "DELETE FROM $tbl_session_course_user
5415
                                        WHERE session_id = '$session_id' AND status in (".Session::STUDENT.", ".Session::COURSE_COACH.")";
5416
                            Database::query($sql);
5417
                        } else {
5418
                            // Delete session-course-user relation ships *only* for students.
5419
                            $sql = "DELETE FROM $tbl_session_course_user
5420
                                        WHERE session_id = '$session_id' AND status =".Session::STUDENT;
5421
                            Database::query($sql);
5422
                        }
5423
                        if ($deleteOnlyCourseCoaches) {
5424
                            $sql = "DELETE FROM $tbl_session_course_user
5425
                                        WHERE session_id = '$session_id' AND status = ".Session::COURSE_COACH;
5426
                            Database::query($sql);
5427
                        }
5428
                    }
5429
                } else {
5430
                    // Updating the session.
5431
                    $params = [
5432
                        'access_start_date' => $dateStart,
5433
                        'access_end_date' => $dateEnd,
5434
                        'display_start_date' => $displayAccessStartDate,
5435
                        'display_end_date' => $displayAccessEndDate,
5436
                        'coach_access_start_date' => $coachAccessStartDate,
5437
                        'coach_access_end_date' => $coachAccessEndDate,
5438
                        'visibility' => $visibilityAfterExpirationPerSession,
5439
                        'session_category_id' => $session_category_id,
5440
                    ];
5441
5442
                    if (!empty($sessionDescription)) {
5443
                        $params['description'] = $sessionDescription;
5444
                    }
5445
5446
                    if (!empty($fieldsToAvoidUpdate)) {
5447
                        foreach ($fieldsToAvoidUpdate as $field) {
5448
                            unset($params[$field]);
5449
                        }
5450
                    }
5451
5452
                    if (isset($sessionId) && !empty($sessionId)) {
5453
                        $session_id = $sessionId;
5454
                        if (!empty($enreg['SessionName'])) {
5455
                            $sessionExistsWithName = self::get_session_by_name($session_name);
5456
                            if (false === $sessionExistsWithName) {
5457
                                $sessionName = Database::escape_string($enreg['SessionName']);
5458
                                $sql = "UPDATE $tbl_session SET title = '$sessionName' WHERE id = $session_id";
5459
                                Database::query($sql);
5460
                                $logger->debug(
5461
                                    "Session #$session_id name IS updated with: '$session_name' External id: ".$enreg['extra_'.$extraFieldId]
5462
                                );
5463
                            } else {
5464
                                $sessionExistsBesidesMe = self::sessionNameExistBesidesMySession(
5465
                                    $session_id,
5466
                                    $session_name
5467
                                );
5468
                                if (true === $sessionExistsBesidesMe) {
5469
                                    if ($debug) {
5470
                                        $message = "Skip Session. Error when update session Session #$session_id Name: '$session_name'. Other session has the same name. External id: ".$enreg['extra_'.$extraFieldId];
5471
                                        $logger->debug($message);
5472
                                        $report[] = $message;
5473
                                    }
5474
                                    continue;
5475
                                } else {
5476
                                    if ($debug) {
5477
                                        $logger->debug(
5478
                                            "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]
5479
                                        );
5480
                                    }
5481
                                }
5482
                            }
5483
                        }
5484
                    } else {
5485
                        $my_session_result = self::get_session_by_name($session_name);
5486
                        $session_id = $my_session_result['id'];
5487
                    }
5488
5489
                    if ($debug) {
5490
                        $logger->debug("Session #$session_id to be updated: '$session_name'");
5491
                    }
5492
5493
                    if ($session_id) {
5494
                        $sessionInfo = api_get_session_info($session_id);
5495
                        $params['show_description'] = $sessionInfo['show_description'] ?? intval($showDescription);
5496
5497
                        if (!empty($daysCoachAccessBeforeBeginning) && !empty($daysCoachAccessAfterBeginning)) {
5498
                            if (empty($sessionInfo['nb_days_access_before_beginning']) ||
5499
                                (!empty($sessionInfo['nb_days_access_before_beginning']) &&
5500
                                    $sessionInfo['nb_days_access_before_beginning'] < $daysCoachAccessBeforeBeginning)
5501
                            ) {
5502
                                $params['coach_access_start_date'] = $coachBefore;
5503
                            }
5504
5505
                            if (empty($sessionInfo['nb_days_access_after_end']) ||
5506
                                (!empty($sessionInfo['nb_days_access_after_end']) &&
5507
                                    $sessionInfo['nb_days_access_after_end'] < $daysCoachAccessAfterBeginning)
5508
                            ) {
5509
                                $params['coach_access_end_date'] = $coachAfter;
5510
                            }
5511
                        }
5512
5513
                        Database::update($tbl_session, $params, ['id = ?' => $session_id]);
5514
                        Database::delete(
5515
                            $tbl_session_user,
5516
                            ['session_id = ? AND relation_type = ?' => [$session_id, Session::GENERAL_COACH]]
5517
                        );
5518
5519
                        $em = Database::getManager();
5520
                        $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5521
                        api_get_session_entity($session_id)->addUserInSession(Session::GENERAL_COACH, $coach);
5522
                        $em->flush();
5523
5524
                        foreach ($enreg as $key => $value) {
5525
                            if ('extra_' == substr($key, 0, 6)) { //an extra field
5526
                                self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5527
                            }
5528
                        }
5529
5530
                        if ($debug) {
5531
                            $logger->debug("Session updated #$session_id");
5532
                        }
5533
5534
                        // Delete session-user relation only for students
5535
                        $sql = "DELETE FROM $tbl_session_user
5536
                                    WHERE session_id = '$session_id' AND relation_type = ".Session::STUDENT;
5537
                        Database::query($sql);
5538
5539
                        $sql = "DELETE FROM $tbl_session_course WHERE session_id = '$session_id'";
5540
                        Database::query($sql);
5541
5542
                        // Delete session-course-user relationships students and coaches.
5543
                        if ($updateCourseCoaches) {
5544
                            $sql = "DELETE FROM $tbl_session_course_user
5545
                                        WHERE session_id = '$session_id' AND status in (".Session::STUDENT.", ".Session::COURSE_COACH.")";
5546
                            Database::query($sql);
5547
                        } else {
5548
                            // Delete session-course-user relation ships *only* for students.
5549
                            $sql = "DELETE FROM $tbl_session_course_user
5550
                                        WHERE session_id = '$session_id' AND status = ".Session::STUDENT;
5551
                            Database::query($sql);
5552
                        }
5553
5554
                        if ($deleteOnlyCourseCoaches) {
5555
                            $sql = "DELETE FROM $tbl_session_course_user
5556
                                        WHERE session_id = '$session_id' AND status = ".Session::COURSE_COACH;
5557
                            Database::query($sql);
5558
                        }
5559
                    } else {
5560
                        if ($debug) {
5561
                            $logger->debug(
5562
                                "Sessions - Session not found"
5563
                            );
5564
                        }
5565
                    }
5566
                }
5567
                $session_counter++;
5568
            }
5569
5570
            $sessionList[] = $session_id;
5571
5572
            // Adding the relationship "Session - User" for students
5573
            $userList = [];
5574
            if (is_array($users)) {
5575
                $extraFieldValueCareer = new ExtraFieldValue('career');
5576
                $careerList = isset($enreg['extra_careerid']) && !empty($enreg['extra_careerid']) ? $enreg['extra_careerid'] : [];
5577
                $careerList = str_replace(['[', ']'], '', $careerList);
5578
                if (!empty($careerList)) {
5579
                    $careerList = explode(',', $careerList);
5580
                    $finalCareerIdList = [];
5581
                    foreach ($careerList as $careerId) {
5582
                        $realCareerIdList = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
5583
                            'external_career_id',
5584
                            $careerId
5585
                        );
5586
                        if (isset($realCareerIdList['item_id'])) {
5587
                            $finalCareerIdList[] = $realCareerIdList['item_id'];
5588
                        }
5589
                    }
5590
                }
5591
5592
                foreach ($users as $user) {
5593
                    $user_id = UserManager::get_user_id_from_username($user);
5594
                    if (false !== $user_id) {
5595
                        if (!empty($finalCareerIdList)) {
5596
                            foreach ($finalCareerIdList as $careerId) {
5597
                                UserManager::addUserCareer($user_id, $careerId);
5598
                            }
5599
                        }
5600
5601
                        $userEntity = api_get_user_entity($user_id);
5602
                        $sessionEntity = api_get_session_entity($session_id);
5603
                        $sessionEntity->addUserInSession(Session::STUDENT, $userEntity);
5604
5605
                        if ($debug) {
5606
                            $logger->debug("Adding User #$user_id ($user) to session #$session_id");
5607
                        }
5608
                        $user_counter++;
5609
                    }
5610
                }
5611
            }
5612
5613
            if ($deleteUsersNotInList) {
5614
                // Getting user in DB in order to compare to the new list.
5615
                $usersListInDatabase = self::get_users_by_session($session_id, 0);
5616
                if (!empty($usersListInDatabase)) {
5617
                    if (empty($userList)) {
5618
                        foreach ($usersListInDatabase as $userInfo) {
5619
                            self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5620
                        }
5621
                    } else {
5622
                        foreach ($usersListInDatabase as $userInfo) {
5623
                            if (!in_array($userInfo['user_id'], $userList)) {
5624
                                self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5625
                            }
5626
                        }
5627
                    }
5628
                }
5629
            }
5630
5631
            // See BT#6449
5632
            $onlyAddFirstCoachOrTeacher = false;
5633
            if ($sessionWithCoursesModifier) {
5634
                if (count($courses) >= 2) {
5635
                    // Only first teacher in course session;
5636
                    $onlyAddFirstCoachOrTeacher = true;
5637
                    // Remove all teachers from course.
5638
                    $removeAllTeachersFromCourse = false;
5639
                }
5640
            }
5641
5642
            foreach ($courses as $course) {
5643
                $courseArray = bracketsToArray($course);
5644
                $course_code = $courseArray[0];
5645
5646
                if (CourseManager::course_exists($course_code)) {
5647
                    $courseInfo = api_get_course_info($course_code);
5648
                    $courseId = $courseInfo['real_id'];
5649
5650
                    // Adding the course to a session.
5651
                    $sql = "INSERT IGNORE INTO $tbl_session_course
5652
                                SET c_id = '$courseId', session_id='$session_id'";
5653
                    Database::query($sql);
5654
5655
                    self::installCourse($session_id, $courseInfo['real_id']);
5656
5657
                    if ($debug) {
5658
                        $logger->debug("Adding course '$course_code' to session #$session_id");
5659
                    }
5660
5661
                    $course_counter++;
5662
                    $course_coaches = array_values(
5663
                        array_filter(
5664
                            array_map('trim', explode(',', (string)($courseArray[1] ?? ''))),
5665
                            'strlen'
5666
                        )
5667
                    );
5668
                    $course_users = array_values(
5669
                        array_filter(
5670
                            array_map('trim', explode(',', (string)($courseArray[2] ?? ''))),
5671
                            'strlen'
5672
                        )
5673
                    );
5674
5675
                    // Checking if the flag is set TeachersWillBeAddedAsCoachInAllCourseSessions (course_edit.php)
5676
                    $addTeachersToSession = true;
5677
5678
                    if (array_key_exists('add_teachers_to_sessions_courses', $courseInfo)) {
5679
                        $addTeachersToSession = $courseInfo['add_teachers_to_sessions_courses'];
5680
                    }
5681
5682
                    // If any user provided for a course, use the users array.
5683
                    if (empty($course_users)) {
5684
                        if (!empty($userList)) {
5685
                            self::subscribe_users_to_session_course(
5686
                                $userList,
5687
                                $session_id,
5688
                                $course_code
5689
                            );
5690
                            if ($debug) {
5691
                                $msg = "Adding student list ".implode(', #', $userList)." to course: '$course_code' and session #$session_id";
5692
                                $logger->debug($msg);
5693
                            }
5694
                        }
5695
                    }
5696
5697
                    // Adding coaches to session course user.
5698
                    if (!empty($course_coaches)) {
5699
                        $savedCoaches = [];
5700
                        // only edit if add_teachers_to_sessions_courses is set.
5701
                        if ($addTeachersToSession) {
5702
                            if ($addOriginalCourseTeachersAsCourseSessionCoaches) {
5703
                                // Adding course teachers as course session teachers.
5704
                                $alreadyAddedTeachers = CourseManager::get_teacher_list_from_course_code(
5705
                                    $course_code
5706
                                );
5707
5708
                                if (!empty($alreadyAddedTeachers)) {
5709
                                    $teachersToAdd = [];
5710
                                    foreach ($alreadyAddedTeachers as $user) {
5711
                                        $teachersToAdd[] = $user['username'];
5712
                                    }
5713
                                    $course_coaches = array_merge(
5714
                                        $course_coaches,
5715
                                        $teachersToAdd
5716
                                    );
5717
                                }
5718
                            }
5719
5720
                            foreach ($course_coaches as $course_coach) {
5721
                                $coach_id = UserManager::get_user_id_from_username($course_coach);
5722
                                if (false !== $coach_id) {
5723
                                    // Just insert new coaches
5724
                                    self::updateCoaches(
5725
                                        $session_id,
5726
                                        $courseId,
5727
                                        [$coach_id],
5728
                                        false
5729
                                    );
5730
5731
                                    if ($debug) {
5732
                                        $logger->debug("Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
5733
                                    }
5734
                                    $savedCoaches[] = $coach_id;
5735
                                } else {
5736
                                    $badCoach = trim((string)$course_coach);
5737
                                    $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
5738
                                }
5739
                            }
5740
                        }
5741
5742
                        // Custom courses/session coaches
5743
                        $teacherToAdd = null;
5744
                        // Only one coach is added.
5745
                        if (true == $onlyAddFirstCoachOrTeacher) {
5746
                            if ($debug) {
5747
                                $logger->debug("onlyAddFirstCoachOrTeacher : true");
5748
                            }
5749
5750
                            foreach ($course_coaches as $course_coach) {
5751
                                $coach_id = UserManager::get_user_id_from_username($course_coach);
5752
                                if (false !== $coach_id) {
5753
                                    $teacherToAdd = $coach_id;
5754
                                    break;
5755
                                }
5756
                            }
5757
5758
                            // Un subscribe everyone that's not in the list.
5759
                            $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5760
                            if (!empty($teacherList)) {
5761
                                foreach ($teacherList as $teacher) {
5762
                                    if ($teacherToAdd != $teacher['user_id']) {
5763
                                        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5764
                                                    WHERE
5765
                                                        user_id = ".$teacher['user_id']." AND
5766
                                                        c_id = '".$courseId."'
5767
                                                    ";
5768
5769
                                        $result = Database::query($sql);
5770
                                        $rows = Database::num_rows($result);
5771
                                        if ($rows > 0) {
5772
                                            $userCourseData = Database::fetch_assoc($result);
5773
                                            if (!empty($userCourseData)) {
5774
                                                $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5775
                                            }
5776
                                        }
5777
5778
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5779
                                                    WHERE
5780
                                                        user_id = ".$teacher['user_id']." AND
5781
                                                        c_id = '".$courseInfo['real_id']."'
5782
                                                    ";
5783
5784
                                        $result = Database::query($sql);
5785
                                        while ($groupData = Database::fetch_assoc($result)) {
5786
                                            $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5787
                                        }
5788
5789
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5790
                                                    WHERE
5791
                                                        user_id = ".$teacher['user_id']." AND
5792
                                                        c_id = '".$courseInfo['real_id']."'
5793
                                                    ";
5794
5795
                                        $result = Database::query($sql);
5796
                                        while ($groupData = Database::fetch_assoc($result)) {
5797
                                            $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5798
                                        }
5799
5800
                                        CourseManager::unsubscribe_user(
5801
                                            $teacher['user_id'],
5802
                                            $course_code
5803
                                        );
5804
5805
                                        if ($debug) {
5806
                                            $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5807
                                        }
5808
                                    }
5809
                                }
5810
                            }
5811
5812
                            if (!empty($teacherToAdd)) {
5813
                                self::updateCoaches(
5814
                                    $session_id,
5815
                                    $courseId,
5816
                                    [$teacherToAdd],
5817
                                    true
5818
                                );
5819
5820
                                if ($debug) {
5821
                                    $logger->debug("Add coach #$teacherToAdd to course $courseId and session $session_id");
5822
                                }
5823
5824
                                $userCourseCategory = '';
5825
                                if (isset($teacherBackupList[$teacherToAdd]) &&
5826
                                    isset($teacherBackupList[$teacherToAdd][$course_code])
5827
                                ) {
5828
                                    $courseUserData = $teacherBackupList[$teacherToAdd][$course_code];
5829
                                    $userCourseCategory = $courseUserData['user_course_cat'];
5830
                                }
5831
5832
                                CourseManager::subscribeUser(
5833
                                    $teacherToAdd,
5834
                                    $courseId,
5835
                                    COURSEMANAGER,
5836
                                    0,
5837
                                    $userCourseCategory
5838
                                );
5839
5840
                                if ($debug) {
5841
                                    $logger->debug("Subscribe user #$teacherToAdd as teacher in course $course_code with user userCourseCategory $userCourseCategory");
5842
                                }
5843
5844
                                if (isset($groupBackup['user'][$teacherToAdd]) &&
5845
                                    isset($groupBackup['user'][$teacherToAdd][$course_code]) &&
5846
                                    !empty($groupBackup['user'][$teacherToAdd][$course_code])
5847
                                ) {
5848
                                    foreach ($groupBackup['user'][$teacherToAdd][$course_code] as $data) {
5849
                                        GroupManager::subscribeUsers(
5850
                                            $teacherToAdd,
5851
                                            api_get_group_entity($data['group_id']),
5852
                                            $data['c_id']
5853
                                        );
5854
                                    }
5855
                                }
5856
5857
                                if (isset($groupBackup['tutor'][$teacherToAdd]) &&
5858
                                    isset($groupBackup['tutor'][$teacherToAdd][$course_code]) &&
5859
                                    !empty($groupBackup['tutor'][$teacherToAdd][$course_code])
5860
                                ) {
5861
                                    foreach ($groupBackup['tutor'][$teacherToAdd][$course_code] as $data) {
5862
                                        GroupManager::subscribeTutors(
5863
                                            $teacherToAdd,
5864
                                            api_get_group_entity($data['group_id']),
5865
                                            $data['c_id']
5866
                                        );
5867
                                    }
5868
                                }
5869
                            }
5870
                        }
5871
5872
                        // See BT#6449#note-195
5873
                        // All coaches are added.
5874
                        if ($removeAllTeachersFromCourse) {
5875
                            if ($debug) {
5876
                                $logger->debug("removeAllTeachersFromCourse true");
5877
                            }
5878
                            $teacherToAdd = null;
5879
                            foreach ($course_coaches as $course_coach) {
5880
                                $coach_id = UserManager::get_user_id_from_username(
5881
                                    $course_coach
5882
                                );
5883
                                if (false !== $coach_id) {
5884
                                    $teacherToAdd[] = $coach_id;
5885
                                }
5886
                            }
5887
5888
                            if (!empty($teacherToAdd)) {
5889
                                // Deleting all course teachers and adding the only coach as teacher.
5890
                                $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5891
5892
                                if (!empty($teacherList)) {
5893
                                    foreach ($teacherList as $teacher) {
5894
                                        if (!in_array($teacher['user_id'], $teacherToAdd)) {
5895
                                            $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5896
                                                        WHERE
5897
                                                            user_id = ".$teacher['user_id']." AND
5898
                                                            c_id = '".$courseId."'
5899
                                                        ";
5900
5901
                                            $result = Database::query($sql);
5902
                                            $rows = Database::num_rows($result);
5903
                                            if ($rows > 0) {
5904
                                                $userCourseData = Database::fetch_assoc($result);
5905
                                                if (!empty($userCourseData)) {
5906
                                                    $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5907
                                                }
5908
                                            }
5909
5910
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5911
                                                        WHERE
5912
                                                            user_id = ".$teacher['user_id']." AND
5913
                                                            c_id = '".$courseInfo['real_id']."'
5914
                                                        ";
5915
5916
                                            $result = Database::query($sql);
5917
                                            while ($groupData = Database::fetch_assoc($result)) {
5918
                                                $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5919
                                            }
5920
5921
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5922
                                                        WHERE
5923
                                                            user_id = ".$teacher['user_id']." AND
5924
                                                            c_id = '".$courseInfo['real_id']."'
5925
                                                        ";
5926
5927
                                            $result = Database::query($sql);
5928
                                            while ($groupData = Database::fetch_assoc($result)) {
5929
                                                $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5930
                                            }
5931
5932
                                            CourseManager::unsubscribe_user(
5933
                                                $teacher['user_id'],
5934
                                                $course_code
5935
                                            );
5936
5937
                                            if ($debug) {
5938
                                                $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5939
                                            }
5940
                                        }
5941
                                    }
5942
                                }
5943
5944
                                foreach ($teacherToAdd as $teacherId) {
5945
                                    $userCourseCategory = '';
5946
                                    if (isset($teacherBackupList[$teacherId]) &&
5947
                                        isset($teacherBackupList[$teacherId][$course_code])
5948
                                    ) {
5949
                                        $courseUserData = $teacherBackupList[$teacherId][$course_code];
5950
                                        $userCourseCategory = $courseUserData['user_course_cat'];
5951
                                    }
5952
5953
                                    CourseManager::subscribeUser(
5954
                                        $teacherId,
5955
                                        $courseInfo['real_id'],
5956
                                        COURSEMANAGER,
5957
                                        0,
5958
                                        $userCourseCategory
5959
                                    );
5960
5961
                                    if ($debug) {
5962
                                        $logger->debug("Add user as teacher #".$teacherId." in base course: $course_code with userCourseCategory: $userCourseCategory");
5963
                                    }
5964
5965
                                    if (isset($groupBackup['user'][$teacherId]) &&
5966
                                        isset($groupBackup['user'][$teacherId][$course_code]) &&
5967
                                        !empty($groupBackup['user'][$teacherId][$course_code])
5968
                                    ) {
5969
                                        foreach ($groupBackup['user'][$teacherId][$course_code] as $data) {
5970
                                            GroupManager::subscribeUsers(
5971
                                                $teacherId,
5972
                                                api_get_group_entity($data['group_id']),
5973
                                                $data['c_id']
5974
                                            );
5975
                                        }
5976
                                    }
5977
5978
                                    if (isset($groupBackup['tutor'][$teacherId]) &&
5979
                                        isset($groupBackup['tutor'][$teacherId][$course_code]) &&
5980
                                        !empty($groupBackup['tutor'][$teacherId][$course_code])
5981
                                    ) {
5982
                                        foreach ($groupBackup['tutor'][$teacherId][$course_code] as $data) {
5983
                                            GroupManager::subscribeTutors(
5984
                                                $teacherId,
5985
                                                api_get_group_entity($data['group_id']),
5986
                                                $data['c_id']
5987
                                            );
5988
                                        }
5989
                                    }
5990
                                }
5991
                            }
5992
                        }
5993
5994
                        // Continue default behaviour.
5995
                        if (false == $onlyAddFirstCoachOrTeacher) {
5996
                            // Checking one more time see BT#6449#note-149
5997
                            $coaches = self::getCoachesByCourseSession($session_id, $courseId);
5998
                            // Update coaches if only there's 1 course see BT#6449#note-189
5999
                            if (empty($coaches) || 1 == count($courses)) {
6000
                                foreach ($course_coaches as $course_coach) {
6001
                                    $course_coach = trim($course_coach);
6002
                                    $coach_id = UserManager::get_user_id_from_username($course_coach);
6003
                                    if (false !== $coach_id) {
6004
                                        // Just insert new coaches
6005
                                        self::updateCoaches(
6006
                                            $session_id,
6007
                                            $courseId,
6008
                                            [$coach_id],
6009
                                            false
6010
                                        );
6011
6012
                                        if ($debug) {
6013
                                            $logger->debug("Sessions - Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
6014
                                        }
6015
                                        $savedCoaches[] = $coach_id;
6016
                                    } else {
6017
                                        $badCoach = trim((string)$course_coach);
6018
                                        $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
6019
                                    }
6020
                                }
6021
                            }
6022
                        }
6023
                    }
6024
6025
                    // Adding Students, updating relationship "Session - Course - User".
6026
                    $course_users = array_filter($course_users);
6027
                    if (!empty($course_users)) {
6028
                        foreach ($course_users as $user) {
6029
                            $user_id = UserManager::get_user_id_from_username($user);
6030
6031
                            if (false !== $user_id) {
6032
                                self::subscribe_users_to_session_course(
6033
                                    [$user_id],
6034
                                    $session_id,
6035
                                    $course_code
6036
                                );
6037
                                if ($debug) {
6038
                                    $logger->debug("Adding student: user #$user_id ($user) to course: '$course_code' and session #$session_id");
6039
                                }
6040
                            } else {
6041
                                $badUser = trim((string)$user);
6042
                                $error_message .= get_lang("This user doesn't exist").': "'.$badUser.'"'.$eol;
6043
                            }
6044
                        }
6045
                    }
6046
                    $inserted_in_course[$course_code] = $courseInfo['title'];
6047
                }
6048
            }
6049
            $access_url_id = api_get_current_access_url_id();
6050
            UrlManager::add_session_to_url($session_id, $access_url_id);
6051
            $sql = "UPDATE $tbl_session SET nbr_users = '$user_counter', nbr_courses = '$course_counter'
6052
                        WHERE id = '$session_id'";
6053
            Database::query($sql);
6054
6055
            self::addClassesByName($session_id, $classes, false);
6056
6057
            if ($debug) {
6058
                $logger->debug("End process session #$session_id -------------------- ");
6059
            }
6060
        }
6061
6062
        if (!empty($report)) {
6063
            if ($debug) {
6064
                $logger->debug("--Summary--");
6065
                foreach ($report as $line) {
6066
                    $logger->debug($line);
6067
                }
6068
            }
6069
        }
6070
6071
        return [
6072
            'error_message' => $error_message,
6073
            'session_counter' => $session_counter,
6074
            'session_list' => $sessionList,
6075
        ];
6076
    }
6077
6078
    /**
6079
     * Imports sessions from an XML file and returns the result of the operation.
6080
     */
6081
    public static function importXML(
6082
        string $file,
6083
        bool $updateSession = false,
6084
        int $defaultUserId = null,
6085
        bool $sendMail = false,
6086
        int $sessionVisibility = SESSION_VISIBLE,
6087
        array &$insertedInCourse = [],
6088
        ?string &$errorMessage = ''
6089
    ): array {
6090
        $defaultUserId = $defaultUserId ?? api_get_user_id();
6091
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
6092
        $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
6093
        $tblSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
6094
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6095
6096
        $sessionCounter = 0;
6097
        $sessionList = [];
6098
6099
        $content = file_get_contents($file);
6100
        $content = api_utf8_encode_xml($content);
6101
        $root = @simplexml_load_string($content);
6102
6103
        if (!is_object($root)) {
6104
            $errorMessage .= get_lang('XML document is not valid');
6105
            return [];
6106
        }
6107
6108
        // === USERS ===
6109
        if (isset($root->Users->User)) {
6110
            foreach ($root->Users->User as $nodeUser) {
6111
                $username = trim(api_utf8_decode($nodeUser->Username));
6112
                $password = api_utf8_decode($nodeUser->Password);
6113
                $firstname = api_utf8_decode($nodeUser->Firstname);
6114
                $lastname = api_utf8_decode($nodeUser->Lastname);
6115
                $email = trim(api_utf8_decode($nodeUser->Email));
6116
                $officialCode = trim(api_utf8_decode($nodeUser->OfficialCode));
6117
                $phone = trim(api_utf8_decode($nodeUser->Phone));
6118
                $statusStr = strtolower(trim(api_utf8_decode($nodeUser->Status)));
6119
                $status = $statusStr === 'teacher' ? 1 : 5;
6120
6121
                if (UserManager::is_username_available($username)) {
6122
                    if (empty($password)) {
6123
                        $password = api_generate_password();
6124
                    }
6125
                    UserManager::create_user(
6126
                        $firstname,
6127
                        $lastname,
6128
                        $status,
6129
                        $email,
6130
                        $username,
6131
                        $password,
6132
                        $officialCode,
6133
                        null,
6134
                        $phone,
6135
                        null,
6136
                        [UserAuthSource::PLATFORM],
6137
                        null,
6138
                        1,
6139
                        0,
6140
                        null,
6141
                        null,
6142
                        $sendMail
6143
                    );
6144
                } else {
6145
                    $userId = UserManager::get_user_id_from_username($username);
6146
                    if ($userId) {
6147
                        UserManager::update_user(
6148
                            $userId,
6149
                            $firstname,
6150
                            $lastname,
6151
                            $username,
6152
                            $password,
6153
                            [],
6154
                            $email,
6155
                            $status,
6156
                            $officialCode,
6157
                            $phone,
6158
                            null,
6159
                            null,
6160
                            1,
6161
                            null,
6162
                            0
6163
                        );
6164
                    }
6165
                }
6166
            }
6167
        }
6168
6169
        // === COURSES ===
6170
        if (isset($root->Courses->Course)) {
6171
            foreach ($root->Courses->Course as $nodeCourse) {
6172
                $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6173
                $courseTitle = api_utf8_decode($nodeCourse->CourseTitle ?: $courseCode);
6174
                $courseLang = api_utf8_decode($nodeCourse->CourseLanguage);
6175
                $teacherUsername = trim(api_utf8_decode($nodeCourse->CourseTeacher));
6176
6177
                $teacherId = UserManager::get_user_id_from_username($teacherUsername) ?: $defaultUserId;
6178
6179
                if (!CourseManager::course_exists($courseCode)) {
6180
                    CourseManager::create_course([
6181
                        'wanted_code' => $courseCode,
6182
                        'title' => $courseTitle,
6183
                        'course_language' => $courseLang,
6184
                        'user_id' => $defaultUserId,
6185
                        'teachers' => $teacherId,
6186
                    ]);
6187
                }
6188
            }
6189
        }
6190
6191
        // === SESSIONS ===
6192
        if (isset($root->Session)) {
6193
            foreach ($root->Session as $nodeSession) {
6194
                $sessionName = trim(api_utf8_decode($nodeSession->SessionName));
6195
                $coachUsername = trim(api_utf8_decode($nodeSession->Coach));
6196
                $coachId = UserManager::get_user_id_from_username($coachUsername) ?: $defaultUserId;
6197
                $dateStart = api_utf8_decode($nodeSession->DateStart);
6198
                $dateEnd = api_utf8_decode($nodeSession->DateEnd);
6199
                $sessionCategoryId = (int) trim(api_utf8_decode($nodeSession->SessionCategory));
6200
                $categoryExists = false;
6201
                if (!empty($sessionCategoryId)) {
6202
                    $result = Database::select(
6203
                        'id',
6204
                        Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
6205
                        ['where' => ['id = ?' => $sessionCategoryId]],
6206
                        'first'
6207
                    );
6208
6209
                    $categoryExists = !empty($result);
6210
                }
6211
                if (!$categoryExists) {
6212
                    $sessionCategoryId = null;
6213
                }
6214
                $visibilityStr = strtolower(api_utf8_decode($nodeSession->VisibilityAfterExpiration));
6215
                $visibility = match ($visibilityStr) {
6216
                    'read_only' => SESSION_VISIBLE_READ_ONLY,
6217
                    'not_accessible' => SESSION_INVISIBLE,
6218
                    default => $sessionVisibility,
6219
                };
6220
6221
                // Normalize dates
6222
                $dateStart = date('Y-m-d H:i:s', strtotime($dateStart));
6223
                $dateEnd = date('Y-m-d H:i:s', strtotime($dateEnd));
6224
6225
                $sessionId = null;
6226
                $mySession = SessionManager::get_session_by_name($sessionName);
6227
6228
                if ($updateSession && $mySession) {
6229
                    $sessionId = $mySession['id'];
6230
                    Database::update($tblSession, [
6231
                        'access_start_date' => $dateStart,
6232
                        'access_end_date' => $dateEnd,
6233
                        'visibility' => $visibility,
6234
                        'session_category_id' => $sessionCategoryId,
6235
                    ], ['id = ?' => $sessionId]);
6236
6237
                    Database::query("DELETE FROM $tblSessionUser WHERE session_id = $sessionId");
6238
                    Database::query("DELETE FROM $tblSessionCourse WHERE session_id = $sessionId");
6239
                    Database::query("DELETE FROM $tblSessionCourseUser WHERE session_id = $sessionId");
6240
                } else {
6241
                    $sessionId = Database::insert($tblSession, [
6242
                        'title' => $sessionName,
6243
                        'access_start_date' => $dateStart,
6244
                        'access_end_date' => $dateEnd,
6245
                        'visibility' => $visibility,
6246
                        'nbr_users' => 0,
6247
                        'nbr_courses' => 0,
6248
                        'nbr_classes' => 0,
6249
                        'status' => 0,
6250
                        'duration' => 0,
6251
                        'session_category_id' => $sessionCategoryId,
6252
                    ]);
6253
                }
6254
6255
                if ($sessionId) {
6256
                    Database::insert($tblSessionUser, [
6257
                        'user_id' => $coachId,
6258
                        'session_id' => $sessionId,
6259
                        'registered_at' => api_get_utc_datetime(),
6260
                        'relation_type' => Session::GENERAL_COACH,
6261
                        'duration' => 0,
6262
                    ], false, ['ignore' => true]);
6263
6264
                    Database::insert($tblSessionUser, [
6265
                        'user_id' => $defaultUserId,
6266
                        'session_id' => $sessionId,
6267
                        'registered_at' => api_get_utc_datetime(),
6268
                        'relation_type' => Session::SESSION_ADMIN,
6269
                        'duration' => 0,
6270
                    ], false, ['ignore' => true]);
6271
                    $sessionCounter++;
6272
                    $sessionList[] = $sessionId;
6273
                }
6274
6275
                // Add Users to session
6276
                foreach ($nodeSession->User as $nodeUser) {
6277
                    $username = UserManager::purify_username(api_utf8_decode($nodeUser));
6278
                    $userId = UserManager::get_user_id_from_username($username);
6279
                    if ($userId) {
6280
                        Database::insert($tblSessionUser, [
6281
                            'user_id' => $userId,
6282
                            'session_id' => $sessionId,
6283
                            'relation_type' => Session::STUDENT,
6284
                            'duration' => 0,
6285
                            'registered_at' => api_get_utc_datetime(),
6286
                        ], false, ['ignore' => true]);
6287
                    }
6288
                }
6289
6290
                // Add Courses to session
6291
                foreach ($nodeSession->Course as $nodeCourse) {
6292
                    $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6293
                    $courseInfo = api_get_course_info($courseCode);
6294
                    if ($courseInfo) {
6295
                        $courseId = $courseInfo['real_id'];
6296
                        Database::insert($tblSessionCourse, [
6297
                            'c_id' => $courseId,
6298
                            'session_id' => $sessionId,
6299
                            'nbr_users' => 0,
6300
                            'position' => 0,
6301
                        ]);
6302
                        $courseCoachUsernames = explode(',', $nodeCourse->Coach);
6303
                        foreach ($courseCoachUsernames as $coachUname) {
6304
                            $coachId = UserManager::get_user_id_from_username(trim($coachUname));
6305
                            if ($coachId) {
6306
                                Database::insert($tblSessionCourseUser, [
6307
                                    'user_id' => $coachId,
6308
                                    'c_id' => $courseId,
6309
                                    'session_id' => $sessionId,
6310
                                    'status' => Session::COURSE_COACH,
6311
                                    'visibility' => 1,
6312
                                    'legal_agreement' => 0,
6313
                                    'progress' => 0,
6314
                                ]);
6315
                            }
6316
                        }
6317
6318
                        // Users in the course
6319
                        $userCounter = 0;
6320
                        foreach ($nodeCourse->User as $userNode) {
6321
                            $username = UserManager::purify_username(api_utf8_decode($userNode));
6322
                            $userId = UserManager::get_user_id_from_username($username);
6323
                            if ($userId) {
6324
                                Database::insert($tblSessionUser, [
6325
                                    'user_id' => $userId,
6326
                                    'session_id' => $sessionId,
6327
                                    'registered_at' => api_get_utc_datetime(),
6328
                                    'duration' => 0,
6329
                                    'relation_type' => Session::STUDENT
6330
                                ], false, ['ignore' => true]);
6331
                                Database::insert($tblSessionCourseUser, [
6332
                                    'user_id' => $userId,
6333
                                    'c_id' => $courseId,
6334
                                    'session_id' => $sessionId,
6335
                                    'status' => Session::STUDENT,
6336
                                    'visibility' => 1,
6337
                                    'legal_agreement' => 0,
6338
                                    'progress' => 0,
6339
                                ]);
6340
                                $userCounter++;
6341
                            }
6342
                        }
6343
6344
                        Database::update(
6345
                            $tblSessionCourse,
6346
                            ['nbr_users' => $userCounter],
6347
                            ['c_id = ? AND session_id = ?' => [$courseId, $sessionId]],
6348
                        );
6349
                    }
6350
                }
6351
6352
                Database::update($tblSession, [
6353
                    'nbr_users' => count($nodeSession->User),
6354
                    'nbr_courses' => count($nodeSession->Course),
6355
                ], ['id = ?' => $sessionId]);
6356
6357
                UrlManager::add_session_to_url($sessionId, api_get_current_access_url_id());
6358
            }
6359
        }
6360
6361
        return [
6362
            'session_counter' => $sessionCounter,
6363
            'session_list' => $sessionList,
6364
        ];
6365
    }
6366
6367
    /**
6368
     * Normalizes the end date format to include time if missing.
6369
     */
6370
    private static function normalizeDateEnd(string $date): string
6371
    {
6372
        $dt = new \DateTime(trim($date));
6373
        if ($dt->format('H:i:s') === '00:00:00') {
6374
            $dt->setTime(23, 59, 59);
6375
        }
6376
        return $dt->format('Y-m-d H:i:s');
6377
    }
6378
6379
    /**
6380
     * @param int $sessionId
6381
     * @param int $courseId
6382
     *
6383
     * @return array
6384
     */
6385
    public static function getCoachesByCourseSession($sessionId, $courseId)
6386
    {
6387
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6388
        $sessionId = (int) $sessionId;
6389
        $courseId = (int) $courseId;
6390
6391
        $sql = "SELECT user_id FROM $table
6392
                WHERE
6393
                    session_id = '$sessionId' AND
6394
                    c_id = '$courseId' AND
6395
                    status = ".Session::COURSE_COACH;
6396
        $result = Database::query($sql);
6397
6398
        $coaches = [];
6399
        if (Database::num_rows($result) > 0) {
6400
            while ($row = Database::fetch_array($result)) {
6401
                $coaches[] = $row['user_id'];
6402
            }
6403
        }
6404
6405
        return $coaches;
6406
    }
6407
6408
    /**
6409
     * @param int    $sessionId
6410
     * @param int    $courseId
6411
     * @param string $separator
6412
     *
6413
     * @return string
6414
     */
6415
    public static function getCoachesByCourseSessionToString(
6416
        $sessionId,
6417
        $courseId,
6418
        $separator = ''
6419
    ) {
6420
        $coaches = self::getCoachesByCourseSession($sessionId, $courseId);
6421
        $list = [];
6422
        if (!empty($coaches)) {
6423
            foreach ($coaches as $coachId) {
6424
                $userInfo = api_get_user_info($coachId);
6425
                if ($userInfo) {
6426
                    $list[] = $userInfo['complete_name'];
6427
                }
6428
            }
6429
        }
6430
6431
        $separator = empty($separator) ? CourseManager::USER_SEPARATOR : $separator;
6432
6433
        return array_to_string($list, $separator);
6434
    }
6435
6436
    /**
6437
     * Get all coaches added in the session - course relationship.
6438
     *
6439
     * @param int $sessionId
6440
     *
6441
     * @return array
6442
     */
6443
    public static function getCoachesBySession($sessionId)
6444
    {
6445
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6446
        $sessionId = intval($sessionId);
6447
6448
        $sql = "SELECT DISTINCT user_id
6449
                FROM $table
6450
                WHERE session_id = '$sessionId' AND status = ".Session::COURSE_COACH;
6451
        $result = Database::query($sql);
6452
6453
        $coaches = [];
6454
        if (Database::num_rows($result) > 0) {
6455
            while ($row = Database::fetch_array($result)) {
6456
                $coaches[] = $row['user_id'];
6457
            }
6458
        }
6459
6460
        return $coaches;
6461
    }
6462
6463
    /**
6464
     * @param int $userId
6465
     *
6466
     * @return array
6467
     */
6468
    public static function getAllCoursesFromAllSessionFromDrh($userId)
6469
    {
6470
        $sessions = self::get_sessions_followed_by_drh($userId);
6471
        $coursesFromSession = [];
6472
        if (!empty($sessions)) {
6473
            foreach ($sessions as $session) {
6474
                $courseList = self::get_course_list_by_session_id($session['id']);
6475
                foreach ($courseList as $course) {
6476
                    $coursesFromSession[] = $course['code'];
6477
                }
6478
            }
6479
        }
6480
6481
        return $coursesFromSession;
6482
    }
6483
6484
    /**
6485
     * getAllCoursesFromAllSessions.
6486
     *
6487
     * @return array
6488
     */
6489
    public static function getAllCoursesFromAllSessions()
6490
    {
6491
        $sessions = self::get_sessions_list();
6492
        $coursesFromSession = [];
6493
        if (!empty($sessions)) {
6494
            foreach ($sessions as $session) {
6495
                $courseList = self::get_course_list_by_session_id($session['id']);
6496
                foreach ($courseList as $course) {
6497
                    $coursesFromSession[$course['code'].':'.$session['id']] = $course['visual_code'].' - '.$course['title'].' ('.$session['title'].')';
6498
                }
6499
            }
6500
        }
6501
6502
        return $coursesFromSession;
6503
    }
6504
6505
    /**
6506
     * Return user id list or count of users depending of the $getCount parameter.
6507
     *
6508
     * @param string $status
6509
     * @param int    $userId
6510
     * @param bool   $getCount
6511
     * @param int    $from
6512
     * @param int    $numberItems
6513
     * @param string $column
6514
     * @param string $direction
6515
     * @param string $keyword
6516
     * @param string $active
6517
     * @param string $lastConnectionDate
6518
     * @param array  $sessionIdList
6519
     * @param array  $studentIdList
6520
     * @param int    $filterByStatus
6521
     *
6522
     * @return array|int
6523
     */
6524
    public static function getAllUsersFromCoursesFromAllSessionFromStatus(
6525
        $status,
6526
        $userId,
6527
        $getCount = false,
6528
        $from = null,
6529
        $numberItems = null,
6530
        $column = '',
6531
        $direction = 'asc',
6532
        $keyword = null,
6533
        $active = null,
6534
        $lastConnectionDate = null,
6535
        $sessionIdList = [],
6536
        $studentIdList = [],
6537
        $filterByStatus = null
6538
    ) {
6539
        $filterByStatus = (int) $filterByStatus;
6540
        $userId = (int) $userId;
6541
6542
        if (empty($column)) {
6543
            $column = 'u.lastname';
6544
            if (api_is_western_name_order()) {
6545
                $column = 'u.firstname';
6546
            }
6547
        }
6548
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
6549
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
6550
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
6551
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6552
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
6553
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6554
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6555
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
6556
6557
        $direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : 'asc';
6558
        $column = Database::escape_string($column);
6559
6560
        $urlId = api_get_current_access_url_id();
6561
6562
        $sessionConditions = '';
6563
        $courseConditions = '';
6564
        $userConditions = ' AND u.active <> '.USER_SOFT_DELETED.' ';
6565
6566
        if (isset($active)) {
6567
            $active = (int) $active;
6568
            $userConditions .= " AND active = $active";
6569
        }
6570
6571
        $courseList = CourseManager::get_courses_followed_by_drh($userId, DRH);
6572
        if (!empty($courseList)) {
6573
            $courseIdList = array_column($courseList, 'id');
6574
            $courseConditions = ' AND c.id IN ("'.implode('","', $courseIdList).'")';
6575
        }
6576
6577
        $userConditionsFromDrh = '';
6578
6579
        // Classic DRH
6580
        if (empty($studentIdList)) {
6581
            $studentListSql = UserManager::get_users_followed_by_drh(
6582
                $userId,
6583
                $filterByStatus,
6584
                true,
6585
                false
6586
            );
6587
            if (!empty($studentListSql)) {
6588
                $studentIdList = array_keys($studentListSql);
6589
                $studentListSql = "'".implode("','", $studentIdList)."'";
6590
            }
6591
        } else {
6592
            $studentIdList = array_map('intval', $studentIdList);
6593
            $studentListSql = "'".implode("','", $studentIdList)."'";
6594
        }
6595
        if (!empty($studentListSql)) {
6596
            $userConditionsFromDrh = " AND u.id IN ($studentListSql) ";
6597
        }
6598
6599
        switch ($status) {
6600
            case 'admin':
6601
            case 'drh':
6602
                break;
6603
            case 'drh_all':
6604
                // Show all by DRH
6605
                if (empty($sessionIdList)) {
6606
                    $sessionListFollowed = self::get_sessions_followed_by_drh(
6607
                        $userId,
6608
                        null,
6609
                        null,
6610
                        false,
6611
                        true
6612
                    );
6613
6614
                    if (!empty($sessionListFollowed)) {
6615
                        $sessionIdList = array_column($sessionListFollowed, 'id');
6616
                    }
6617
                }
6618
6619
                if (!empty($sessionIdList)) {
6620
                    $sessionIdList = array_map('intval', $sessionIdList);
6621
                    $sessionsListSql = "'".implode("','", $sessionIdList)."'";
6622
                    $sessionConditions = " AND s.id IN ($sessionsListSql) ";
6623
                }
6624
6625
                break;
6626
            case 'teacher':
6627
            case 'session_admin':
6628
                $generalCoachedSessions = array_map(
6629
                    fn(Session $session) => $session->getId(),
6630
                    api_get_user_entity($userId)->getSessionsAsGeneralCoach()
6631
                );
6632
6633
                $sessionConditions = " AND s.IN (".implode(',', $generalCoachedSessions).") ";
6634
                $userConditionsFromDrh = '';
6635
                break;
6636
        }
6637
6638
        $select = 'SELECT DISTINCT u.*, u.id as user_id';
6639
        $masterSelect = 'SELECT DISTINCT id, id as user_id FROM ';
6640
6641
        if ($getCount) {
6642
            $select = 'SELECT DISTINCT u.id, u.id as user_id';
6643
            $masterSelect = 'SELECT COUNT(DISTINCT(id)) as count FROM ';
6644
        }
6645
6646
        if (!empty($filterByStatus)) {
6647
            $userConditions .= " AND u.status = $filterByStatus";
6648
        }
6649
6650
        if (!empty($lastConnectionDate)) {
6651
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
6652
            $userConditions .= " AND u.last_login <= '$lastConnectionDate' ";
6653
        }
6654
6655
        if (!empty($keyword)) {
6656
            $keyword = Database::escape_string($keyword);
6657
            $userConditions .= " AND (
6658
                u.username LIKE '%$keyword%' OR
6659
                u.firstname LIKE '%$keyword%' OR
6660
                u.lastname LIKE '%$keyword%' OR
6661
                u.official_code LIKE '%$keyword%' OR
6662
                u.email LIKE '%$keyword%'
6663
            )";
6664
        }
6665
6666
        $where = " WHERE
6667
                   access_url_id = $urlId
6668
                   $userConditions
6669
        ";
6670
6671
        $userUnion = '';
6672
        if (!empty($userConditionsFromDrh)) {
6673
            $userUnion = "
6674
            UNION (
6675
                $select
6676
                FROM $tbl_user u
6677
                INNER JOIN $tbl_user_rel_access_url url
6678
                ON (url.user_id = u.id)
6679
                $where
6680
                $userConditionsFromDrh
6681
            )";
6682
        }
6683
6684
        $sql = "$masterSelect (
6685
                ($select
6686
                FROM $tbl_session s
6687
                    INNER JOIN $tbl_session_rel_access_url url
6688
                    ON (url.session_id = s.id)
6689
                    INNER JOIN $tbl_session_rel_course_rel_user su
6690
                    ON (s.id = su.session_id)
6691
                    INNER JOIN $tbl_user u
6692
                    ON (u.id = su.user_id)
6693
                    $where
6694
                    $sessionConditions
6695
                    $userConditionsFromDrh
6696
                ) UNION (
6697
                    $select
6698
                    FROM $tbl_course c
6699
                    INNER JOIN $tbl_course_rel_access_url url
6700
                    ON (url.c_id = c.id)
6701
                    INNER JOIN $tbl_course_user cu
6702
                    ON (cu.c_id = c.id)
6703
                    INNER JOIN $tbl_user u
6704
                    ON (u.id = cu.user_id)
6705
                    $where
6706
                    $courseConditions
6707
                    $userConditionsFromDrh
6708
                ) $userUnion
6709
                ) as t1
6710
                ";
6711
6712
        if ($getCount) {
6713
            $result = Database::query($sql);
6714
6715
            $count = 0;
6716
            if (Database::num_rows($result)) {
6717
                $rows = Database::fetch_array($result);
6718
                $count = $rows['count'];
6719
            }
6720
6721
            return $count;
6722
        }
6723
6724
        if (!empty($column) && !empty($direction)) {
6725
            $column = str_replace('u.', '', $column);
6726
            $sql .= " ORDER BY `$column` $direction ";
6727
        }
6728
6729
        $limitCondition = '';
6730
        if (isset($from) && isset($numberItems)) {
6731
            $from = (int) $from;
6732
            $numberItems = (int) $numberItems;
6733
            $limitCondition = "LIMIT $from, $numberItems";
6734
        }
6735
6736
        $sql .= $limitCondition;
6737
        $result = Database::query($sql);
6738
6739
        return Database::store_result($result);
6740
    }
6741
6742
    /**
6743
     * @param int   $sessionId
6744
     * @param int   $courseId
6745
     * @param array $coachList
6746
     * @param bool  $deleteCoachesNotInList
6747
     */
6748
    public static function updateCoaches(
6749
        $sessionId,
6750
        $courseId,
6751
        $coachList,
6752
        $deleteCoachesNotInList = false
6753
    ) {
6754
        $currentCoaches = self::getCoachesByCourseSession($sessionId, $courseId);
6755
6756
        if (!empty($coachList)) {
6757
            foreach ($coachList as $userId) {
6758
                self::set_coach_to_course_session($userId, $sessionId, $courseId);
6759
            }
6760
        }
6761
6762
        if ($deleteCoachesNotInList) {
6763
            if (!empty($coachList)) {
6764
                $coachesToDelete = array_diff($currentCoaches, $coachList);
6765
            } else {
6766
                $coachesToDelete = $currentCoaches;
6767
            }
6768
6769
            if (!empty($coachesToDelete)) {
6770
                foreach ($coachesToDelete as $userId) {
6771
                    self::set_coach_to_course_session(
6772
                        $userId,
6773
                        $sessionId,
6774
                        $courseId,
6775
                        true
6776
                    );
6777
                }
6778
            }
6779
        }
6780
    }
6781
6782
    /**
6783
     * @param array $sessions
6784
     * @param array $sessionsDestination
6785
     *
6786
     * @return array
6787
     */
6788
    public static function copyStudentsFromSession($sessions, $sessionsDestination)
6789
    {
6790
        $messages = [];
6791
        if (!empty($sessions)) {
6792
            foreach ($sessions as $sessionId) {
6793
                $sessionInfo = self::fetch($sessionId);
6794
                $userList = self::get_users_by_session($sessionId, 0);
6795
                if (!empty($userList)) {
6796
                    $newUserList = [];
6797
                    $userToString = null;
6798
                    foreach ($userList as $userInfo) {
6799
                        $newUserList[] = $userInfo['user_id'];
6800
                        $userToString .= $userInfo['firstname'].' '.$userInfo['lastname'].'<br />';
6801
                    }
6802
6803
                    if (!empty($sessionsDestination)) {
6804
                        foreach ($sessionsDestination as $sessionDestinationId) {
6805
                            $sessionDestinationInfo = self::fetch($sessionDestinationId);
6806
                            $messages[] = Display::return_message(
6807
                                sprintf(
6808
                                    get_lang(
6809
                                        'AddingStudentsFromSessionXToSessionY'
6810
                                    ),
6811
                                    $sessionInfo['title'],
6812
                                    $sessionDestinationInfo['title']
6813
                                ),
6814
                                'info',
6815
                                false
6816
                            );
6817
                            if ($sessionId == $sessionDestinationId) {
6818
                                $messages[] = Display::return_message(
6819
                                    sprintf(
6820
                                        get_lang('Session %s skipped'),
6821
                                        $sessionDestinationId
6822
                                    ),
6823
                                    'warning',
6824
                                    false
6825
                                );
6826
                                continue;
6827
                            }
6828
                            $messages[] = Display::return_message(get_lang('Learner list').'<br />'.$userToString, 'info', false);
6829
                            self::subscribeUsersToSession(
6830
                                $sessionDestinationId,
6831
                                $newUserList,
6832
                                SESSION_VISIBLE_READ_ONLY,
6833
                                false
6834
                            );
6835
                        }
6836
                    } else {
6837
                        $messages[] = Display::return_message(get_lang('No destination session provided'), 'warning');
6838
                    }
6839
                } else {
6840
                    $messages[] = Display::return_message(
6841
                        get_lang('No student found for the session').' #'.$sessionInfo['title'],
6842
                        'warning'
6843
                    );
6844
                }
6845
            }
6846
        } else {
6847
            $messages[] = Display::return_message(get_lang('No data available'), 'warning');
6848
        }
6849
6850
        return $messages;
6851
    }
6852
6853
    /**
6854
     * Assign coaches of a session(s) as teachers to a given course (or courses).
6855
     *
6856
     * @param array A list of session IDs
6857
     * @param array A list of course IDs
6858
     *
6859
     * @return string
6860
     */
6861
    public static function copyCoachesFromSessionToCourse($sessions, $courses)
6862
    {
6863
        $coachesPerSession = [];
6864
        foreach ($sessions as $sessionId) {
6865
            $coaches = self::getCoachesBySession($sessionId);
6866
            $coachesPerSession[$sessionId] = $coaches;
6867
        }
6868
6869
        $result = [];
6870
6871
        if (!empty($courses)) {
6872
            foreach ($courses as $courseId) {
6873
                $courseInfo = api_get_course_info_by_id($courseId);
6874
                foreach ($coachesPerSession as $sessionId => $coachList) {
6875
                    CourseManager::updateTeachers(
6876
                        $courseInfo,
6877
                        $coachList,
6878
                        false,
6879
                        false,
6880
                        false
6881
                    );
6882
                    $result[$courseInfo['code']][$sessionId] = $coachList;
6883
                }
6884
            }
6885
        }
6886
        $sessionUrl = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session=';
6887
        $htmlResult = null;
6888
6889
        if (!empty($result)) {
6890
            foreach ($result as $courseCode => $data) {
6891
                $url = api_get_course_url($courseCode);
6892
                $htmlResult .= sprintf(
6893
                    get_lang('Coaches subscribed as teachers in course %s'),
6894
                    Display::url($courseCode, $url, ['target' => '_blank'])
6895
                );
6896
                foreach ($data as $sessionId => $coachList) {
6897
                    $sessionInfo = self::fetch($sessionId);
6898
                    $htmlResult .= '<br />';
6899
                    $htmlResult .= Display::url(
6900
                        get_lang('Session').': '.$sessionInfo['title'].' <br />',
6901
                        $sessionUrl.$sessionId,
6902
                        ['target' => '_blank']
6903
                    );
6904
                    $teacherList = [];
6905
                    foreach ($coachList as $coachId) {
6906
                        $userInfo = api_get_user_info($coachId);
6907
                        $teacherList[] = $userInfo['complete_name'];
6908
                    }
6909
                    if (!empty($teacherList)) {
6910
                        $htmlResult .= implode(', ', $teacherList);
6911
                    } else {
6912
                        $htmlResult .= get_lang('Nothing to add');
6913
                    }
6914
                }
6915
                $htmlResult .= '<br />';
6916
            }
6917
            $htmlResult = Display::return_message($htmlResult, 'normal', false);
6918
        }
6919
6920
        return $htmlResult;
6921
    }
6922
6923
    /**
6924
     * @param string $keyword
6925
     * @param string $active
6926
     * @param string $lastConnectionDate
6927
     * @param array  $sessionIdList
6928
     * @param array  $studentIdList
6929
     * @param int    $filterUserStatus   STUDENT|COURSEMANAGER constants
6930
     *
6931
     * @return array|int
6932
     */
6933
    public static function getCountUserTracking(
6934
        $keyword = null,
6935
        $active = null,
6936
        $lastConnectionDate = null,
6937
        $sessionIdList = [],
6938
        $studentIdList = [],
6939
        $filterUserStatus = null
6940
    ) {
6941
        $userId = api_get_user_id();
6942
        $drhLoaded = false;
6943
6944
        if (api_is_drh()) {
6945
            if (api_drh_can_access_all_session_content()) {
6946
                $count = self::getAllUsersFromCoursesFromAllSessionFromStatus(
6947
                    'drh_all',
6948
                    $userId,
6949
                    true,
6950
                    null,
6951
                    null,
6952
                    null,
6953
                    null,
6954
                    $keyword,
6955
                    $active,
6956
                    $lastConnectionDate,
6957
                    $sessionIdList,
6958
                    $studentIdList,
6959
                    $filterUserStatus
6960
                );
6961
                $drhLoaded = true;
6962
            }
6963
        }
6964
6965
        if (false == $drhLoaded) {
6966
            $count = UserManager::getUsersFollowedByUser(
6967
                $userId,
6968
                $filterUserStatus,
6969
                false,
6970
                false,
6971
                true,
6972
                null,
6973
                null,
6974
                null,
6975
                null,
6976
                $active,
6977
                $lastConnectionDate,
6978
                api_is_student_boss() ? STUDENT_BOSS : COURSEMANAGER,
6979
                $keyword
6980
            );
6981
        }
6982
6983
        return $count;
6984
    }
6985
6986
    /**
6987
     * Get teachers followed by a user.
6988
     *
6989
     * @param int    $userId
6990
     * @param int    $active
6991
     * @param string $lastConnectionDate
6992
     * @param bool   $getCount
6993
     * @param array  $sessionIdList
6994
     *
6995
     * @return array|int
6996
     */
6997
    public static function getTeacherTracking(
6998
        $userId,
6999
        $active = 1,
7000
        $lastConnectionDate = null,
7001
        $getCount = false,
7002
        $sessionIdList = []
7003
    ) {
7004
        $teacherListId = [];
7005
        if (api_is_drh() || api_is_platform_admin()) {
7006
            // Followed teachers by drh
7007
            if (api_drh_can_access_all_session_content()) {
7008
                if (empty($sessionIdList)) {
7009
                    $sessions = self::get_sessions_followed_by_drh($userId);
7010
                    $sessionIdList = [];
7011
                    foreach ($sessions as $session) {
7012
                        $sessionIdList[] = $session['id'];
7013
                    }
7014
                }
7015
7016
                $sessionIdList = array_map('intval', $sessionIdList);
7017
                $sessionToString = implode("', '", $sessionIdList);
7018
7019
                $course = Database::get_main_table(TABLE_MAIN_COURSE);
7020
                $sessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7021
                $courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
7022
7023
                // Select the teachers.
7024
                $sql = "SELECT DISTINCT(cu.user_id)
7025
                        FROM $course c
7026
                        INNER JOIN $sessionCourse src
7027
                        ON c.id = src.c_id
7028
                        INNER JOIN $courseUser cu
7029
                        ON (cu.c_id = c.id)
7030
		                WHERE src.session_id IN ('$sessionToString') AND cu.status = 1";
7031
                $result = Database::query($sql);
7032
                while ($row = Database::fetch_assoc($result)) {
7033
                    $teacherListId[$row['user_id']] = $row['user_id'];
7034
                }
7035
            } else {
7036
                $teacherResult = UserManager::get_users_followed_by_drh($userId, COURSEMANAGER);
7037
                foreach ($teacherResult as $userInfo) {
7038
                    $teacherListId[] = $userInfo['user_id'];
7039
                }
7040
            }
7041
        }
7042
7043
        if (!empty($teacherListId)) {
7044
            $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7045
7046
            $select = "SELECT DISTINCT u.* ";
7047
            if ($getCount) {
7048
                $select = "SELECT count(DISTINCT(u.id)) as count";
7049
            }
7050
7051
            $sql = "$select FROM $tableUser u";
7052
7053
            if (!empty($lastConnectionDate)) {
7054
                $tableLogin = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7055
                //$sql .= " INNER JOIN $tableLogin l ON (l.login_user_id = u.user_id) ";
7056
            }
7057
            $active = intval($active);
7058
            $teacherListId = implode("','", $teacherListId);
7059
            $where = " WHERE u.active = $active AND u.id IN ('$teacherListId') ";
7060
7061
            if (!empty($lastConnectionDate)) {
7062
                $lastConnectionDate = Database::escape_string($lastConnectionDate);
7063
                //$where .= " AND l.login_date <= '$lastConnectionDate' ";
7064
            }
7065
7066
            $sql .= $where;
7067
            $result = Database::query($sql);
7068
            if (Database::num_rows($result)) {
7069
                if ($getCount) {
7070
                    $row = Database::fetch_array($result);
7071
7072
                    return $row['count'];
7073
                } else {
7074
                    return Database::store_result($result, 'ASSOC');
7075
                }
7076
            }
7077
        }
7078
7079
        return 0;
7080
    }
7081
7082
    /**
7083
     * Get the list of course tools that have to be dealt with in case of
7084
     * registering any course to a session.
7085
     *
7086
     * @return array The list of tools to be dealt with (literal names)
7087
     */
7088
    public static function getCourseToolToBeManaged()
7089
    {
7090
        return [
7091
            'courseDescription',
7092
            'courseIntroduction',
7093
        ];
7094
    }
7095
7096
    /**
7097
     * Calls the methods bound to each tool when a course is registered into a session.
7098
     *
7099
     * @param int $sessionId
7100
     * @param int $courseId
7101
     *
7102
     * @return bool
7103
     */
7104
    public static function installCourse($sessionId, $courseId)
7105
    {
7106
        return true;
7107
        $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...
7108
7109
        foreach ($toolList as $tool) {
7110
            $method = 'add'.$tool;
7111
            if (method_exists(get_class(), $method)) {
7112
                self::$method($sessionId, $courseId);
7113
            }
7114
        }
7115
    }
7116
7117
    /**
7118
     * Calls the methods bound to each tool when a course is unregistered from
7119
     * a session.
7120
     *
7121
     * @param int $sessionId
7122
     * @param int $courseId
7123
     */
7124
    public static function unInstallCourse($sessionId, $courseId)
7125
    {
7126
        return true;
7127
        $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...
7128
7129
        foreach ($toolList as $tool) {
7130
            $method = 'remove'.$tool;
7131
            if (method_exists(get_class(), $method)) {
7132
                self::$method($sessionId, $courseId);
7133
            }
7134
        }
7135
    }
7136
7137
    /**
7138
     * @param array $userSessionList        format see self::importSessionDrhCSV()
7139
     * @param bool  $sendEmail
7140
     * @param bool  $removeOldRelationShips
7141
     */
7142
    public static function subscribeDrhToSessionList(
7143
        $userSessionList,
7144
        $sendEmail,
7145
        $removeOldRelationShips
7146
    ) {
7147
        if (!empty($userSessionList)) {
7148
            foreach ($userSessionList as $userId => $data) {
7149
                $sessionList = [];
7150
                foreach ($data['session_list'] as $sessionInfo) {
7151
                    $sessionList[] = $sessionInfo['session_id'];
7152
                }
7153
                $userInfo = $data['user_info'];
7154
                self::subscribeSessionsToDrh(
7155
                    $userInfo,
7156
                    $sessionList,
7157
                    $sendEmail,
7158
                    $removeOldRelationShips
7159
                );
7160
            }
7161
        }
7162
    }
7163
7164
    /**
7165
     * @param array $userSessionList format see self::importSessionDrhCSV()
7166
     *
7167
     * @return string
7168
     */
7169
    public static function checkSubscribeDrhToSessionList($userSessionList)
7170
    {
7171
        $message = null;
7172
        if (!empty($userSessionList)) {
7173
            if (!empty($userSessionList)) {
7174
                foreach ($userSessionList as $userId => $data) {
7175
                    $userInfo = $data['user_info'];
7176
7177
                    $sessionListSubscribed = self::get_sessions_followed_by_drh($userId);
7178
                    if (!empty($sessionListSubscribed)) {
7179
                        $sessionListSubscribed = array_keys($sessionListSubscribed);
7180
                    }
7181
7182
                    $sessionList = [];
7183
                    if (!empty($data['session_list'])) {
7184
                        foreach ($data['session_list'] as $sessionInfo) {
7185
                            if (in_array($sessionInfo['session_id'], $sessionListSubscribed)) {
7186
                                $sessionList[] = $sessionInfo['session_info']['title'];
7187
                            }
7188
                        }
7189
                    }
7190
7191
                    $message .= '<strong>'.get_lang('User').'</strong>: ';
7192
                    $message .= $userInfo['complete_name_with_username'].' <br />';
7193
7194
                    if (!in_array($userInfo['status'], [DRH]) && !api_is_platform_admin_by_id($userInfo['user_id'])) {
7195
                        $message .= get_lang('Users must have the HR director role').'<br />';
7196
                        continue;
7197
                    }
7198
7199
                    if (!empty($sessionList)) {
7200
                        $message .= '<strong>'.get_lang('Course sessions').':</strong> <br />';
7201
                        $message .= implode(', ', $sessionList).'<br /><br />';
7202
                    } else {
7203
                        $message .= get_lang('No session provided').' <br /><br />';
7204
                    }
7205
                }
7206
            }
7207
        }
7208
7209
        return $message;
7210
    }
7211
7212
    /**
7213
     * @param string $file
7214
     * @param bool   $sendEmail
7215
     * @param bool   $removeOldRelationShips
7216
     *
7217
     * @return string
7218
     */
7219
    public static function importSessionDrhCSV($file, $sendEmail, $removeOldRelationShips)
7220
    {
7221
        $list = Import::csv_reader($file);
7222
7223
        if (!empty($list)) {
7224
            $userSessionList = [];
7225
            foreach ($list as $data) {
7226
                $sessionInfo = [];
7227
                if (isset($data['SessionId'])) {
7228
                    $sessionInfo = api_get_session_info($data['SessionId']);
7229
                }
7230
7231
                if (isset($data['SessionName']) && empty($sessionInfo)) {
7232
                $sessionInfo = self::get_session_by_name($data['SessionName']);
7233
                }
7234
7235
                if (empty($sessionInfo)) {
7236
                    $sessionData = isset($data['SessionName']) ? $data['SessionName'] : $data['SessionId'];
7237
                    Display::addFlash(
7238
                        Display::return_message(get_lang('Session not found.').' - '.$sessionData, 'warning')
7239
                    );
7240
                    continue;
7241
                }
7242
                $userList = explode(',', $data['Username']);
7243
7244
                foreach ($userList as $username) {
7245
                    $userInfo = api_get_user_info_from_username($username);
7246
7247
                if (empty($userInfo)) {
7248
                        Display::addFlash(
7249
                            Display::return_message(get_lang("This user doesn't exist").' - '.$username, 'warning')
7250
                        );
7251
                        continue;
7252
                }
7253
7254
                if (!empty($userInfo) && !empty($sessionInfo)) {
7255
                    $userSessionList[$userInfo['user_id']]['session_list'][] = [
7256
                        'session_id' => $sessionInfo['id'],
7257
                        'session_info' => $sessionInfo,
7258
                    ];
7259
                    $userSessionList[$userInfo['user_id']]['user_info'] = $userInfo;
7260
                    }
7261
                }
7262
            }
7263
7264
            self::subscribeDrhToSessionList($userSessionList, $sendEmail, $removeOldRelationShips);
7265
7266
            return self::checkSubscribeDrhToSessionList($userSessionList);
7267
        }
7268
    }
7269
7270
    /**
7271
     * Courses re-ordering in resume_session.php flag see BT#8316.
7272
     */
7273
    public static function orderCourseIsEnabled()
7274
    {
7275
        $sessionCourseOrder = api_get_setting('session_course_ordering');
7276
        if ('true' === $sessionCourseOrder) {
7277
            return true;
7278
        }
7279
7280
        return false;
7281
    }
7282
7283
    /**
7284
     * @param string $direction (up/down)
7285
     * @param int    $sessionId
7286
     * @param int    $courseId
7287
     *
7288
     * @return bool
7289
     */
7290
    public static function move($direction, $sessionId, $courseId)
7291
    {
7292
        if (!self::orderCourseIsEnabled()) {
7293
            return false;
7294
        }
7295
7296
        $sessionId = intval($sessionId);
7297
        $courseId = intval($courseId);
7298
7299
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7300
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7301
7302
        $position = [];
7303
        $count = 0;
7304
        foreach ($courseList as $course) {
7305
            if ('' == $course['position']) {
7306
                $course['position'] = $count;
7307
            }
7308
            $position[$course['code']] = $course['position'];
7309
            // Saving current order.
7310
            $sql = "UPDATE $table SET position = $count
7311
                    WHERE session_id = $sessionId AND c_id = '".$course['real_id']."'";
7312
            Database::query($sql);
7313
            $count++;
7314
        }
7315
7316
        // Loading new positions.
7317
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7318
7319
        $found = false;
7320
7321
        switch ($direction) {
7322
            case 'up':
7323
                $courseList = array_reverse($courseList);
7324
                break;
7325
            case 'down':
7326
                break;
7327
        }
7328
7329
        foreach ($courseList as $course) {
7330
            if ($found) {
7331
                $nextId = $course['real_id'];
7332
                $nextOrder = $course['position'];
7333
                break;
7334
            }
7335
7336
            if ($courseId == $course['real_id']) {
7337
                $thisCourseCode = $course['real_id'];
7338
                $thisOrder = $course['position'];
7339
                $found = true;
7340
            }
7341
        }
7342
7343
        $sql1 = "UPDATE $table SET position = '".intval($nextOrder)."'
7344
                 WHERE session_id = $sessionId AND c_id =  $thisCourseCode";
7345
        Database::query($sql1);
7346
7347
        $sql2 = "UPDATE $table SET position = '".intval($thisOrder)."'
7348
                 WHERE session_id = $sessionId AND c_id = $nextId";
7349
        Database::query($sql2);
7350
7351
        return true;
7352
    }
7353
7354
    /**
7355
     * @param int $sessionId
7356
     * @param int $courseId
7357
     *
7358
     * @return bool
7359
     */
7360
    public static function moveUp($sessionId, $courseId)
7361
    {
7362
        return self::move('up', $sessionId, $courseId);
7363
    }
7364
7365
    /**
7366
     * @param int    $sessionId
7367
     * @param string $courseCode
7368
     *
7369
     * @return bool
7370
     */
7371
    public static function moveDown($sessionId, $courseCode)
7372
    {
7373
        return self::move('down', $sessionId, $courseCode);
7374
    }
7375
7376
    /**
7377
     * Use the session duration to allow/block user access see BT#8317
7378
     * Needs these DB changes
7379
     * ALTER TABLE session ADD COLUMN duration int;
7380
     * ALTER TABLE session_rel_user ADD COLUMN duration int;.
7381
     */
7382
    public static function durationPerUserIsEnabled()
7383
    {
7384
        return api_get_configuration_value('session_duration_feature');
7385
    }
7386
7387
    /**
7388
     * Returns the number of days the student has left in a session when using
7389
     * sessions durations.
7390
     *
7391
     * @param int $userId
7392
     *
7393
     * @return int
7394
     */
7395
    public static function getDayLeftInSession(array $sessionInfo, $userId)
7396
    {
7397
        $sessionId = $sessionInfo['id'];
7398
        $subscription = self::getUserSession($userId, $sessionId);
7399
        $duration = empty($subscription['duration'])
7400
            ? $sessionInfo['duration']
7401
            : $sessionInfo['duration'] + $subscription['duration'];
7402
7403
        // Get an array with the details of the first access of the student to
7404
        // this session
7405
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
7406
            $sessionId,
7407
            $userId
7408
        );
7409
7410
        $currentTime = time();
7411
7412
        // If no previous access, return false
7413
        if (0 == count($courseAccess)) {
7414
            return $duration;
7415
        }
7416
7417
        $firstAccess = api_strtotime($courseAccess['login_course_date'], 'UTC');
7418
        $endDateInSeconds = $firstAccess + $duration * 24 * 60 * 60;
7419
        $leftDays = round(($endDateInSeconds - $currentTime) / 60 / 60 / 24);
7420
7421
        return $leftDays;
7422
    }
7423
7424
    /**
7425
     * @param int $duration
7426
     * @param int $userId
7427
     * @param int $sessionId
7428
     *
7429
     * @return bool
7430
     */
7431
    public static function editUserSessionDuration($duration, $userId, $sessionId)
7432
    {
7433
        $duration = (int) $duration;
7434
        $userId = (int) $userId;
7435
        $sessionId = (int) $sessionId;
7436
7437
        if (empty($userId) || empty($sessionId)) {
7438
            return false;
7439
        }
7440
7441
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7442
        $parameters = ['duration' => $duration];
7443
        $where = ['session_id = ? AND user_id = ? ' => [$sessionId, $userId]];
7444
        Database::update($table, $parameters, $where);
7445
7446
        return true;
7447
    }
7448
7449
    /**
7450
     * Gets one row from the session_rel_user table.
7451
     *
7452
     * @param int $userId
7453
     * @param int $sessionId
7454
     *
7455
     * @return array
7456
     */
7457
    public static function getUserSession($userId, $sessionId)
7458
    {
7459
        $userId = (int) $userId;
7460
        $sessionId = (int) $sessionId;
7461
7462
        if (empty($userId) || empty($sessionId)) {
7463
            return false;
7464
        }
7465
7466
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7467
        $sql = "SELECT * FROM $table
7468
                WHERE session_id = $sessionId AND user_id = $userId";
7469
        $result = Database::query($sql);
7470
        $values = [];
7471
        if (Database::num_rows($result)) {
7472
            $values = Database::fetch_assoc($result);
7473
        }
7474
7475
        return $values;
7476
    }
7477
7478
    /**
7479
     * Check if user is subscribed inside a session as student.
7480
     *
7481
     * @param int $sessionId The session id
7482
     * @param int $userId    The user id
7483
     *
7484
     * @return bool Whether is subscribed
7485
     */
7486
    public static function isUserSubscribedAsStudent($sessionId, $userId)
7487
    {
7488
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7489
        $sessionId = (int) $sessionId;
7490
        $userId = (int) $userId;
7491
7492
        // COUNT(1) actually returns the number of rows from the table (as if
7493
        // counting the results from the first column)
7494
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7495
                WHERE
7496
                    session_id = $sessionId AND
7497
                    user_id = $userId AND
7498
                    relation_type = ".Session::STUDENT;
7499
7500
        $result = Database::fetch_assoc(Database::query($sql));
7501
7502
        if (!empty($result) && $result['qty'] > 0) {
7503
            return true;
7504
        }
7505
7506
        return false;
7507
    }
7508
7509
    /**
7510
     * Check if user is subscribed inside a session as a HRM.
7511
     *
7512
     * @param int $sessionId The session id
7513
     * @param int $userId    The user id
7514
     *
7515
     * @return bool Whether is subscribed
7516
     */
7517
    public static function isUserSubscribedAsHRM($sessionId, $userId)
7518
    {
7519
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7520
7521
        $sessionId = (int) $sessionId;
7522
        $userId = (int) $userId;
7523
7524
        // COUNT(1) actually returns the number of rows from the table (as if
7525
        // counting the results from the first column)
7526
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7527
                WHERE
7528
                    session_id = $sessionId AND
7529
                    user_id = $userId AND
7530
                    relation_type = ".Session::DRH;
7531
7532
        $result = Database::fetch_assoc(Database::query($sql));
7533
7534
        if (!empty($result) && $result['qty'] > 0) {
7535
            return true;
7536
        }
7537
7538
        return false;
7539
    }
7540
7541
    /**
7542
     * Get the session coached by a user (general coach and course-session coach).
7543
     *
7544
     * @param int  $coachId                       The coach id
7545
     * @param bool $checkSessionRelUserVisibility Check the session visibility
7546
     * @param bool $asPlatformAdmin               The user is a platform admin and we want all sessions
7547
     *
7548
     * @return array The session list
7549
     */
7550
    public static function getSessionsCoachedByUser(
7551
        $coachId,
7552
        $checkSessionRelUserVisibility = false,
7553
        $asPlatformAdmin = false
7554
    ) {
7555
        // Get all sessions where $coachId is the general coach
7556
        $sessions = self::get_sessions_by_general_coach($coachId, $asPlatformAdmin);
7557
        // Get all sessions where $coachId is the course - session coach
7558
        $courseSessionList = self::getCoursesListByCourseCoach($coachId);
7559
        $sessionsByCoach = [];
7560
        if (!empty($courseSessionList)) {
7561
            foreach ($courseSessionList as $userCourseSubscription) {
7562
                $session = $userCourseSubscription->getSession();
7563
                $sessionsByCoach[$session->getId()] = api_get_session_info(
7564
                    $session->getId()
7565
                );
7566
            }
7567
        }
7568
7569
        if (!empty($sessionsByCoach)) {
7570
            $sessions = array_merge($sessions, $sessionsByCoach);
7571
        }
7572
7573
        // Remove repeated sessions
7574
        if (!empty($sessions)) {
7575
            $cleanSessions = [];
7576
            foreach ($sessions as $session) {
7577
                $cleanSessions[$session['id']] = $session;
7578
            }
7579
            $sessions = $cleanSessions;
7580
        }
7581
7582
        if ($checkSessionRelUserVisibility) {
7583
            if (!empty($sessions)) {
7584
                $newSessions = [];
7585
                foreach ($sessions as $session) {
7586
                    $visibility = api_get_session_visibility($session['id']);
7587
                    if (SESSION_INVISIBLE == $visibility) {
7588
                        continue;
7589
                    }
7590
                    $newSessions[] = $session;
7591
                }
7592
                $sessions = $newSessions;
7593
            }
7594
        }
7595
7596
        return $sessions;
7597
    }
7598
7599
    /**
7600
     * Check if the course belongs to the session.
7601
     *
7602
     * @param int    $sessionId  The session id
7603
     * @param string $courseCode The course code
7604
     *
7605
     * @return bool
7606
     */
7607
    public static function sessionHasCourse($sessionId, $courseCode)
7608
    {
7609
        $sessionId = (int) $sessionId;
7610
        $courseCode = Database::escape_string($courseCode);
7611
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7612
        $sessionRelCourseTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7613
7614
        $sql = "SELECT COUNT(1) AS qty
7615
                FROM $courseTable c
7616
                INNER JOIN $sessionRelCourseTable src
7617
                ON c.id = src.c_id
7618
                WHERE src.session_id = $sessionId
7619
                AND c.code = '$courseCode'  ";
7620
7621
        $result = Database::query($sql);
7622
7623
        if (false !== $result) {
7624
            $data = Database::fetch_assoc($result);
7625
7626
            if ($data['qty'] > 0) {
7627
                return true;
7628
            }
7629
        }
7630
7631
        return false;
7632
    }
7633
7634
    /**
7635
     * Calculate the total user time in the platform.
7636
     *
7637
     * @param int    $userId The user id
7638
     * @param string $from   Optional. From date
7639
     * @param string $until  Optional. Until date
7640
     *
7641
     * @return string The time (hh:mm:ss)
7642
     */
7643
    public static function getTotalUserTimeInPlatform($userId, $from = '', $until = '')
7644
    {
7645
        $userId = (int) $userId;
7646
        $trackLoginTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7647
        $whereConditions = [
7648
            'login_user_id = ? ' => $userId,
7649
        ];
7650
7651
        if (!empty($from) && !empty($until)) {
7652
            $whereConditions["AND (login_date >= '?' "] = $from;
7653
            $whereConditions["AND logout_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
7654
        }
7655
7656
        $trackResult = Database::select(
7657
            'SEC_TO_TIME(SUM(UNIX_TIMESTAMP(logout_date) - UNIX_TIMESTAMP(login_date))) as total_time',
7658
            $trackLoginTable,
7659
            [
7660
                'where' => $whereConditions,
7661
            ],
7662
            'first'
7663
        );
7664
7665
        if (false != $trackResult) {
7666
            return $trackResult['total_time'] ? $trackResult['total_time'] : '00:00:00';
7667
        }
7668
7669
        return '00:00:00';
7670
    }
7671
7672
    /**
7673
     * Get the courses list by a course coach.
7674
     *
7675
     * @param int $coachId The coach id
7676
     *
7677
     * @return array (id, user_id, session_id, c_id, visibility, status, legal_agreement)
7678
     */
7679
    public static function getCoursesListByCourseCoach($coachId)
7680
    {
7681
        $entityManager = Database::getManager();
7682
        $repo = $entityManager->getRepository(SessionRelCourseRelUser::class);
7683
7684
        return $repo->findBy([
7685
            'user' => $coachId,
7686
            'status' => Session::COURSE_COACH,
7687
        ]);
7688
    }
7689
7690
    /**
7691
     * Get the count of user courses in session.
7692
     *
7693
     * @param int $sessionId
7694
     * @param int $courseId
7695
     *
7696
     * @return array
7697
     */
7698
    public static function getTotalUserCoursesInSession($sessionId, $courseId = 0)
7699
    {
7700
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7701
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7702
7703
        $sessionId = (int) $sessionId;
7704
7705
        if (empty($sessionId)) {
7706
            return [];
7707
        }
7708
7709
        $courseCondition = '';
7710
        if (!empty($courseId)) {
7711
            $courseId = (int) $courseId;
7712
            $courseCondition = "  c_id = $courseId AND ";
7713
        }
7714
7715
        $sql = "SELECT
7716
                    COUNT(u.id) as count,
7717
                    u.id,
7718
                    scu.status status_in_session,
7719
                    u.status user_status
7720
                FROM $table scu
7721
                INNER JOIN $tableUser u
7722
                ON scu.user_id = u.id
7723
                WHERE
7724
                  $courseCondition
7725
                  scu.session_id = ".$sessionId."
7726
                GROUP BY u.id";
7727
7728
        $result = Database::query($sql);
7729
7730
        $list = [];
7731
        while ($data = Database::fetch_assoc($result)) {
7732
            $list[] = $data;
7733
        }
7734
7735
        return $list;
7736
    }
7737
7738
    /**
7739
     * Returns list of a few data from session (name, short description, start
7740
     * date, end date) and the given extra fields if defined based on a
7741
     * session category Id.
7742
     *
7743
     * @param int    $categoryId  The internal ID of the session category
7744
     * @param string $target      Value to search for in the session field values
7745
     * @param array  $extraFields A list of fields to be scanned and returned
7746
     *
7747
     * @return mixed
7748
     */
7749
    public static function getShortSessionListAndExtraByCategory(
7750
        $categoryId,
7751
        $target,
7752
        $extraFields = null,
7753
        $publicationDate = null
7754
    ) {
7755
        $categoryId = (int) $categoryId;
7756
        $sessionList = [];
7757
        // Check if categoryId is valid
7758
        if ($categoryId > 0) {
7759
            $target = Database::escape_string($target);
7760
            $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
7761
            $sfTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7762
            $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7763
            // Join session field and session field values tables
7764
            $joinTable = $sfTable.' sf INNER JOIN '.$sfvTable.' sfv ON sf.id = sfv.field_id';
7765
            $fieldsArray = [];
7766
            foreach ($extraFields as $field) {
7767
                $fieldsArray[] = Database::escape_string($field);
7768
            }
7769
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7770
            if (isset($publicationDate)) {
7771
                $publicationDateString = $publicationDate->format('Y-m-d H:i:s');
7772
                $wherePublication = " AND id NOT IN (
7773
                    SELECT sfv.item_id FROM $joinTable
7774
                    WHERE
7775
                        sf.item_type = $extraFieldType AND
7776
                        ((sf.variable = 'publication_start_date' AND sfv.field_value > '$publicationDateString' and sfv.field_value != '') OR
7777
                        (sf.variable = 'publication_end_date' AND sfv.field_value < '$publicationDateString' and sfv.field_value != ''))
7778
                )";
7779
            }
7780
            // Get the session list from session category and target
7781
            $sessionList = Database::select(
7782
                'id, title, access_start_date, access_end_date',
7783
                $sTable,
7784
                [
7785
                    'where' => [
7786
                        "session_category_id = ? AND id IN (
7787
                            SELECT sfv.item_id FROM $joinTable
7788
                            WHERE
7789
                                sf.item_type = $extraFieldType AND
7790
                                sfv.item_id = session.id AND
7791
                                sf.variable = 'target' AND
7792
                                sfv.field_value = ?
7793
                        ) $wherePublication" => [$categoryId, $target],
7794
                    ],
7795
                ]
7796
            );
7797
            $whereFieldVariables = [];
7798
            $whereFieldIds = [];
7799
            if (
7800
                is_array($fieldsArray) &&
7801
                count($fieldsArray) > 0
7802
            ) {
7803
                $whereParams = '?';
7804
                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...
7805
                    $whereParams .= ', ?';
7806
                }
7807
                $whereFieldVariables = ' variable IN ( '.$whereParams.' )';
7808
                $whereFieldIds = 'field_id IN ( '.$whereParams.' )';
7809
            }
7810
            // Get session fields
7811
            $extraField = new ExtraFieldModel('session');
7812
            $questionMarks = substr(str_repeat('?, ', count($fieldsArray)), 0, -2);
7813
            $fieldsList = $extraField->get_all([
7814
                ' variable IN ( '.$questionMarks.' )' => $fieldsArray,
7815
            ]);
7816
            // Index session fields
7817
            foreach ($fieldsList as $field) {
7818
                $fields[$field['id']] = $field['variable'];
7819
            }
7820
            // Get session field values
7821
            $extra = new ExtraFieldValue('session');
7822
            $questionMarksFields = substr(str_repeat('?, ', count($fields)), 0, -2);
7823
            $sessionFieldValueList = $extra->get_all(['where' => ['field_id IN ( '.$questionMarksFields.' )' => array_keys($fields)]]);
7824
            // Add session fields values to session list
7825
            foreach ($sessionList as $id => &$session) {
7826
                foreach ($sessionFieldValueList as $sessionFieldValue) {
7827
                    // Match session field values to session
7828
                    if ($sessionFieldValue['item_id'] == $id) {
7829
                        // Check if session field value is set in session field list
7830
                        if (isset($fields[$sessionFieldValue['field_id']])) {
7831
                            // Avoid overwriting the session's ID field
7832
                            if ('id' != $fields[$sessionFieldValue['field_id']]) {
7833
                                $var = $fields[$sessionFieldValue['field_id']];
7834
                                $val = $sessionFieldValue['value'];
7835
                                // Assign session field value to session
7836
                                $session[$var] = $val;
7837
                            }
7838
                        }
7839
                    }
7840
                }
7841
            }
7842
        }
7843
7844
        return $sessionList;
7845
    }
7846
7847
    /**
7848
     * Return the Session Category id searched by name.
7849
     *
7850
     * @param string $categoryName Name attribute of session category used for search query
7851
     * @param bool   $force        boolean used to get even if something is wrong (e.g not unique name)
7852
     *
7853
     * @return int|array If success, return category id (int), else it will return an array
7854
     *                   with the next structure:
7855
     *                   array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7856
     */
7857
    public static function getSessionCategoryIdByName($categoryName, $force = false)
7858
    {
7859
        // Start error result
7860
        $errorResult = ['error' => true, 'errorMessage' => get_lang('There was an error.')];
7861
        $categoryName = Database::escape_string($categoryName);
7862
        // Check if is not empty category name
7863
        if (!empty($categoryName)) {
7864
            $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
7865
            // Get all session category with same name
7866
            $result = Database::select(
7867
                'id',
7868
                $sessionCategoryTable,
7869
                [
7870
                    'where' => [
7871
                        'title = ?' => $categoryName,
7872
                    ],
7873
                ]
7874
            );
7875
            // Check the result
7876
            if ($result < 1) {
7877
                // If not found any result, update error message
7878
                $errorResult['errorMessage'] = 'Not found any session category name '.$categoryName;
7879
            } elseif (count($result) > 1 && !$force) {
7880
                // If found more than one result and force is disabled, update error message
7881
                $errorResult['errorMessage'] = 'Found many session categories';
7882
            } elseif (1 == count($result) || $force) {
7883
                // If found just one session category or force option is enabled
7884
7885
                return key($result);
7886
            }
7887
        } else {
7888
            // category name is empty, update error message
7889
            $errorResult['errorMessage'] = 'Not valid category name';
7890
        }
7891
7892
        return $errorResult;
7893
    }
7894
7895
    /**
7896
     * Return all data from sessions (plus extra field, course and coach data) by category id.
7897
     *
7898
     * @param int $sessionCategoryId session category id used to search sessions
7899
     *
7900
     * @return array If success, return session list and more session related data, else it will return an array
7901
     *               with the next structure:
7902
     *               array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7903
     */
7904
    public static function getSessionListAndExtraByCategoryId($sessionCategoryId)
7905
    {
7906
        // Start error result
7907
        $errorResult = [
7908
            'error' => true,
7909
            'errorMessage' => get_lang('There was an error.'),
7910
        ];
7911
7912
        $sessionCategoryId = intval($sessionCategoryId);
7913
        // Check if session category id is valid
7914
        if ($sessionCategoryId > 0) {
7915
            // Get table names
7916
            $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
7917
            $sessionFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7918
            $sessionFieldValueTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7919
            $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7920
            $userTable = Database::get_main_table(TABLE_MAIN_USER);
7921
            $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7922
7923
            // Get all data from all sessions whit the session category specified
7924
            $sessionList = Database::select(
7925
                '*',
7926
                $sessionTable,
7927
                [
7928
                    'where' => [
7929
                        'session_category_id = ?' => $sessionCategoryId,
7930
                    ],
7931
                ]
7932
            );
7933
7934
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7935
7936
            // Check if session list query had result
7937
            if (!empty($sessionList)) {
7938
                // implode all session id
7939
                $sessionIdsString = '('.implode(', ', array_keys($sessionList)).')';
7940
                // Get all field variables
7941
                $sessionFieldList = Database::select(
7942
                    'id, variable',
7943
                    $sessionFieldTable,
7944
                    ['item_type = ? ' => [$extraFieldType]]
7945
                );
7946
7947
                // Get all field values
7948
                $sql = "SELECT item_id, field_id, value FROM
7949
                        $sessionFieldValueTable v INNER JOIN $sessionFieldTable f
7950
                        ON (f.id = v.field_id)
7951
                        WHERE
7952
                            item_id IN $sessionIdsString AND
7953
                            item_type = $extraFieldType
7954
                ";
7955
                $result = Database::query($sql);
7956
                $sessionFieldValueList = Database::store_result($result, 'ASSOC');
7957
7958
                // Check if session field values had result
7959
                if (!empty($sessionFieldValueList)) {
7960
                    $sessionFieldValueListBySession = [];
7961
                    foreach ($sessionFieldValueList as $key => $sessionFieldValue) {
7962
                        // Create an array to index ids to session id
7963
                        $sessionFieldValueListBySession[$sessionFieldValue['item_id']][] = $key;
7964
                    }
7965
                }
7966
                // Query used to find course-coaches from sessions
7967
                $sql = "SELECT
7968
                            scu.session_id,
7969
                            c.id AS course_id,
7970
                            c.code AS course_code,
7971
                            c.title AS course_title,
7972
                            u.username AS coach_username,
7973
                            u.firstname AS coach_firstname,
7974
                            u.lastname AS coach_lastname
7975
                        FROM $courseTable c
7976
                        INNER JOIN $sessionCourseUserTable scu ON c.id = scu.c_id
7977
                        INNER JOIN $userTable u ON scu.user_id = u.id
7978
                        WHERE scu.status = ".Session::COURSE_COACH." AND scu.session_id IN $sessionIdsString
7979
                        ORDER BY scu.session_id ASC ";
7980
                $res = Database::query($sql);
7981
                $sessionCourseList = Database::store_result($res, 'ASSOC');
7982
                // Check if course list had result
7983
                if (!empty($sessionCourseList)) {
7984
                    foreach ($sessionCourseList as $key => $sessionCourse) {
7985
                        // Create an array to index ids to session_id
7986
                        $sessionCourseListBySession[$sessionCourse['session_id']][] = $key;
7987
                    }
7988
                }
7989
                // Join lists
7990
                if (is_array($sessionList)) {
7991
                    foreach ($sessionList as $id => &$row) {
7992
                        if (
7993
                            !empty($sessionFieldValueListBySession) &&
7994
                            is_array($sessionFieldValueListBySession[$id])
7995
                        ) {
7996
                            // If have an index array for session extra fields, use it to join arrays
7997
                            foreach ($sessionFieldValueListBySession[$id] as $key) {
7998
                                $row['extra'][$key] = [
7999
                                    'field_name' => $sessionFieldList[$sessionFieldValueList[$key]['field_id']]['variable'],
8000
                                    'value' => $sessionFieldValueList[$key]['value'],
8001
                                ];
8002
                            }
8003
                        }
8004
                        if (
8005
                            !empty($sessionCourseListBySession) &&
8006
                            is_array($sessionCourseListBySession[$id])
8007
                        ) {
8008
                            // If have an index array for session course coach, use it to join arrays
8009
                            foreach ($sessionCourseListBySession[$id] as $key) {
8010
                                $row['course'][$key] = [
8011
                                    'course_id' => $sessionCourseList[$key]['course_id'],
8012
                                    'course_code' => $sessionCourseList[$key]['course_code'],
8013
                                    'course_title' => $sessionCourseList[$key]['course_title'],
8014
                                    'coach_username' => $sessionCourseList[$key]['coach_username'],
8015
                                    'coach_firstname' => $sessionCourseList[$key]['coach_firstname'],
8016
                                    'coach_lastname' => $sessionCourseList[$key]['coach_lastname'],
8017
                                ];
8018
                            }
8019
                        }
8020
                    }
8021
                }
8022
8023
                return $sessionList;
8024
            } else {
8025
                // Not found result, update error message
8026
                $errorResult['errorMessage'] = 'Not found any session for session category id '.$sessionCategoryId;
8027
            }
8028
        }
8029
8030
        return $errorResult;
8031
    }
8032
8033
    /**
8034
     * Return session description from session id.
8035
     *
8036
     * @param int $sessionId
8037
     *
8038
     * @return string
8039
     */
8040
    public static function getDescriptionFromSessionId($sessionId)
8041
    {
8042
        // Init variables
8043
        $sessionId = (int) $sessionId;
8044
        $description = '';
8045
        // Check if session id is valid
8046
        if ($sessionId > 0) {
8047
            // Select query from session id
8048
            $rows = Database::select(
8049
                'description',
8050
                Database::get_main_table(TABLE_MAIN_SESSION),
8051
                [
8052
                    'where' => [
8053
                        'id = ?' => $sessionId,
8054
                    ],
8055
                ]
8056
            );
8057
8058
            // Check if select query result is not empty
8059
            if (!empty($rows)) {
8060
                // Get session description
8061
                $description = $rows[0]['description'];
8062
            }
8063
        }
8064
8065
        return $description;
8066
    }
8067
8068
    /**
8069
     * Get a session list filtered by name, description or any of the given extra fields.
8070
     *
8071
     * @param string $term                 The term to search
8072
     * @param array  $extraFieldsToInclude Extra fields to include in the session data
8073
     *
8074
     * @return array The list
8075
     */
8076
    public static function searchSession($term, $extraFieldsToInclude = [])
8077
    {
8078
        $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
8079
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
8080
        $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8081
        $term = Database::escape_string($term);
8082
        $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
8083
        if (is_array($extraFieldsToInclude) && count($extraFieldsToInclude) > 0) {
8084
            $resultData = Database::select('*', $sTable, [
8085
                'where' => [
8086
                    "title LIKE %?% " => $term,
8087
                    " OR description LIKE %?% " => $term,
8088
                    " OR id IN (
8089
                    SELECT item_id
8090
                    FROM $sfvTable v INNER JOIN $extraFieldTable e
8091
                    ON (v.field_id = e.id)
8092
                    WHERE field_value LIKE %?% AND item_type = $extraFieldType
8093
                ) " => $term,
8094
                ],
8095
            ]);
8096
        } else {
8097
            $resultData = Database::select('*', $sTable, [
8098
                'where' => [
8099
                    "title LIKE %?% " => $term,
8100
                    "OR description LIKE %?% " => $term,
8101
                ],
8102
            ]);
8103
8104
            return $resultData;
8105
        }
8106
8107
        foreach ($resultData as $id => &$session) {
8108
            $session['extra'] = self::getFilteredExtraFields($id, $extraFieldsToInclude);
8109
        }
8110
8111
        return $resultData;
8112
    }
8113
8114
    /**
8115
     * @param int   $sessionId
8116
     * @param array $extraFieldsToInclude (empty means all)
8117
     *
8118
     * @return array
8119
     */
8120
    public static function getFilteredExtraFields($sessionId, $extraFieldsToInclude = [])
8121
    {
8122
        $extraData = [];
8123
        $variables = [];
8124
        $variablePlaceHolders = [];
8125
8126
        foreach ($extraFieldsToInclude as $sessionExtraField) {
8127
            $variablePlaceHolders[] = "?";
8128
            $variables[] = Database::escape_string($sessionExtraField);
8129
        }
8130
8131
        $sessionExtraField = new ExtraFieldModel('session');
8132
        $fieldList = $sessionExtraField->get_all(empty($extraFieldsToInclude) ? [] : [
8133
            "variable IN ( ".implode(", ", $variablePlaceHolders)." ) " => $variables,
8134
        ]);
8135
8136
        if (empty($fieldList)) {
8137
            return [];
8138
        }
8139
8140
        $fields = [];
8141
8142
        // Index session fields
8143
        foreach ($fieldList as $field) {
8144
            $fields[$field['id']] = $field['variable'];
8145
        }
8146
8147
        // Get session field values
8148
        $extra = new ExtraFieldValue('session');
8149
        $sessionFieldValueList = [];
8150
        foreach (array_keys($fields) as $fieldId) {
8151
            $sessionFieldValue = $extra->get_values_by_handler_and_field_id($sessionId, $fieldId);
8152
            if (false != $sessionFieldValue) {
8153
                $sessionFieldValueList[$fieldId] = $sessionFieldValue;
8154
            }
8155
        }
8156
8157
        foreach ($sessionFieldValueList as $sessionFieldValue) {
8158
            // Match session field values to session
8159
            if ($sessionFieldValue['item_id'] != $sessionId) {
8160
                continue;
8161
            }
8162
8163
            // Check if session field value is set in session field list
8164
            if (!isset($fields[$sessionFieldValue['field_id']])) {
8165
                continue;
8166
            }
8167
8168
            $extrafieldVariable = $fields[$sessionFieldValue['field_id']];
8169
            $extrafieldValue = $sessionFieldValue['value'];
8170
8171
            $extraData[] = [
8172
                'variable' => $extrafieldVariable,
8173
                'value' => $extrafieldValue,
8174
            ];
8175
        }
8176
8177
        return $extraData;
8178
    }
8179
8180
    /**
8181
     * @param int $sessionId
8182
     *
8183
     * @return bool
8184
     */
8185
    public static function isValidId($sessionId)
8186
    {
8187
        $sessionId = (int) $sessionId;
8188
        if ($sessionId > 0) {
8189
            $rows = Database::select(
8190
                'id',
8191
                Database::get_main_table(TABLE_MAIN_SESSION),
8192
                ['where' => ['id = ?' => $sessionId]]
8193
            );
8194
            if (!empty($rows)) {
8195
                return true;
8196
            }
8197
        }
8198
8199
        return false;
8200
    }
8201
8202
    /**
8203
     * Get list of sessions based on users of a group for a group admin.
8204
     *
8205
     * @param int $userId The user id
8206
     *
8207
     * @return array
8208
     */
8209
    public static function getSessionsFollowedForGroupAdmin($userId)
8210
    {
8211
        $sessionList = [];
8212
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
8213
        $sessionUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8214
        $userGroup = new UserGroupModel();
8215
        $userIdList = $userGroup->getGroupUsersByUser($userId);
8216
8217
        if (empty($userIdList)) {
8218
            return [];
8219
        }
8220
8221
        $sql = "SELECT DISTINCT s.*
8222
                FROM $sessionTable s
8223
                INNER JOIN $sessionUserTable sru
8224
                ON s.id = sru.id_session
8225
                WHERE
8226
                    (sru.id_user IN (".implode(', ', $userIdList).")
8227
                    AND sru.relation_type = ".Session::STUDENT."
8228
                )";
8229
8230
        if (api_is_multiple_url_enabled()) {
8231
            $sessionAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8232
            $accessUrlId = api_get_current_access_url_id();
8233
8234
            if (-1 != $accessUrlId) {
8235
                $sql = "SELECT DISTINCT s.*
8236
                        FROM $sessionTable s
8237
                        INNER JOIN $sessionUserTable sru ON s.id = sru.id_session
8238
                        INNER JOIN $sessionAccessUrlTable srau ON s.id = srau.session_id
8239
                        WHERE
8240
                            srau.access_url_id = $accessUrlId
8241
                            AND (
8242
                                sru.id_user IN (".implode(', ', $userIdList).")
8243
                                AND sru.relation_type = ".Session::STUDENT."
8244
                            )";
8245
            }
8246
        }
8247
8248
        $result = Database::query($sql);
8249
        while ($row = Database::fetch_assoc($result)) {
8250
            $sessionList[] = $row;
8251
        }
8252
8253
        return $sessionList;
8254
    }
8255
8256
    public static function getSessionVisibility(Session $session) : string
8257
    {
8258
        switch ($session->getVisibility()) {
8259
            case 1:
8260
                return get_lang('Read only');
8261
            case 2:
8262
                return get_lang('Visible');
8263
            case 3:
8264
                return api_ucfirst(get_lang('invisible'));
8265
        }
8266
8267
        return '';
8268
    }
8269
8270
    /**
8271
     * Returns a human readable string.
8272
     *
8273
     * @return array
8274
     */
8275
    public static function parseSessionDates(Session $session, bool $showTime = false)
8276
    {
8277
        $displayDates = self::convertSessionDateToString(
8278
            $session->getDisplayStartDate(),
8279
            $session->getDisplayEndDate(),
8280
            $showTime,
8281
            true
8282
        );
8283
        $accessDates = self::convertSessionDateToString(
8284
            $session->getAccessStartDate(),
8285
            $session->getAccessEndDate(),
8286
            $showTime,
8287
            true
8288
        );
8289
8290
        $coachDates = self::convertSessionDateToString(
8291
            $session->getCoachAccessStartDate(),
8292
            $session->getCoachAccessEndDate(),
8293
            $showTime,
8294
            true
8295
        );
8296
8297
        return [
8298
            'access' => $accessDates,
8299
            'display' => $displayDates,
8300
            'coach' => $coachDates,
8301
        ];
8302
    }
8303
8304
    /**
8305
     * @throws Exception
8306
     */
8307
    public static function setForm(FormValidator $form, Session $session = null, $fromSessionId = null): array
8308
    {
8309
        $categoriesList = self::get_all_session_category();
8310
8311
        $categoriesOptions = [
8312
            '0' => get_lang('none'),
8313
        ];
8314
8315
        if (false != $categoriesList) {
8316
            foreach ($categoriesList as $categoryItem) {
8317
                $categoriesOptions[$categoryItem['id']] = $categoryItem['title'];
8318
            }
8319
        }
8320
8321
        // Database Table Definitions
8322
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8323
8324
        $form->addText(
8325
            'title',
8326
            get_lang('Session name'),
8327
            true,
8328
            ['maxlength' => 150, 'aria-label' => get_lang('Session name')]
8329
        );
8330
        $form->addRule('title', get_lang('Session title already exists'), 'callback', 'check_session_name');
8331
8332
        if (!api_is_platform_admin() && api_is_teacher()) {
8333
            $form->addSelectFromCollection(
8334
                'coach_username',
8335
                [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.')],
8336
                [api_get_user_entity()],
8337
                [
8338
                    'id' => 'coach_username',
8339
                    'style' => 'width:370px;',
8340
                    'multiple' => true,
8341
                ],
8342
                false,
8343
                'getFullname'
8344
            );
8345
        } else {
8346
            $sql = "SELECT COUNT(1) FROM $tbl_user WHERE active <> ".USER_SOFT_DELETED." AND status = 1";
8347
            $rs = Database::query($sql);
8348
            $countUsers = (int) Database::result($rs, 0, '0');
8349
8350
            if ($countUsers < 1) {
8351
                $orderClause = 'ORDER BY ';
8352
                $orderClause .= api_sort_by_first_name() ? 'firstname, lastname, username' : 'lastname, firstname, username';
8353
8354
                $sql = "SELECT id as user_id, lastname, firstname, username
8355
                        FROM $tbl_user
8356
                        WHERE active <> -1 AND status = '1' ".
8357
                        $orderClause;
8358
8359
                if (api_is_multiple_url_enabled()) {
8360
                    $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
8361
                    $accessUrlId = api_get_current_access_url_id();
8362
                    if (-1 != $accessUrlId) {
8363
                        $sql = "SELECT user.id as user_id, username, lastname, firstname
8364
                        FROM $tbl_user user
8365
                        INNER JOIN $userRelAccessUrlTable url_user
8366
                        ON (url_user.user_id = user.id)
8367
                        WHERE
8368
                            user.active <> -1 AND
8369
                            access_url_id = $accessUrlId AND
8370
                            status = 1 "
8371
                            .$orderClause;
8372
                    }
8373
                }
8374
8375
                $result = Database::query($sql);
8376
                $coachesList = Database::store_result($result);
8377
                $coachesOptions = [];
8378
                foreach ($coachesList as $coachItem) {
8379
                    $coachesOptions[$coachItem['user_id']] =
8380
                        api_get_person_name($coachItem['firstname'], $coachItem['lastname']).' ('.$coachItem['username'].')';
8381
                }
8382
8383
                $form->addSelect(
8384
                    'coach_username',
8385
                    [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.')],
8386
                    $coachesOptions,
8387
                    [
8388
                        'id' => 'coach_username',
8389
                        'style' => 'width:370px;',
8390
                        'multiple' => true,
8391
                    ]
8392
                );
8393
            } else {
8394
                $coaches = [];
8395
8396
                if ($session) {
8397
                    foreach ($session->getGeneralCoaches() as $coach) {
8398
                        $coaches[$coach->getId()] = $coach->getFullName();
8399
                    }
8400
                }
8401
8402
                $form->addSelectAjax(
8403
                    'coach_username',
8404
                    [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.')],
8405
                    $coaches,
8406
                    [
8407
                        'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_general_coach',
8408
                        'width' => '100%',
8409
                        'id' => 'coach_username',
8410
                        'multiple' => true,
8411
                    ]
8412
                );
8413
            }
8414
        }
8415
8416
        $form->addRule('coach_username', get_lang('Required field'), 'required');
8417
        $form->addHtml('<div id="ajax_list_coachs"></div>');
8418
8419
        $form->addButtonAdvancedSettings('advanced_params');
8420
        $form->addElement('html', '<div id="advanced_params_options" style="'.(isset($fromSessionId) ? 'display:block' : 'display:none').'">');
8421
8422
        if (null === $session) {
8423
            $form->addSelectAjax(
8424
                'session_template',
8425
                get_lang('Session template'),
8426
                [],
8427
                [
8428
                    'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_template_session',
8429
                    'id' => 'system_template',
8430
                ]
8431
            );
8432
        }
8433
8434
        if (isset($fromSessionId)) {
8435
            $session = api_get_session_entity($fromSessionId);
8436
        }
8437
        $form->addSelect(
8438
            'session_category',
8439
            get_lang('Sessions categories'),
8440
            $categoriesOptions,
8441
            [
8442
                'id' => 'session_category',
8443
            ]
8444
        );
8445
8446
        $statusList = self::getStatusList();
8447
        $form->addSelect(
8448
            'status',
8449
            get_lang('Session status'),
8450
            $statusList,
8451
            [
8452
                'id' => 'status',
8453
            ]
8454
        );
8455
8456
        $form->addHtmlEditor(
8457
            'description',
8458
            get_lang('Description'),
8459
            false,
8460
            false,
8461
            [
8462
                'ToolbarSet' => 'Minimal',
8463
            ]
8464
        );
8465
8466
        $form->addElement('checkbox', 'show_description', null, get_lang('Show description'));
8467
8468
        $visibilityGroup = [];
8469
        $visibilityGroup[] = $form->createElement(
8470
            'select',
8471
            'session_visibility',
8472
            null,
8473
            [
8474
                SESSION_VISIBLE_READ_ONLY => get_lang('Read only'),
8475
                SESSION_VISIBLE => get_lang('Accessible'),
8476
                SESSION_INVISIBLE => api_ucfirst(get_lang('Not accessible')),
8477
            ],
8478
            []
8479
        );
8480
        $form->addGroup(
8481
            $visibilityGroup,
8482
            'visibility_group',
8483
            get_lang('Visibility after end date'),
8484
            null,
8485
            false
8486
        );
8487
8488
        $options = [
8489
            0 => get_lang('By duration'),
8490
            1 => get_lang('By dates'),
8491
        ];
8492
8493
        $form->addSelect('access', get_lang('Access'), $options, [
8494
            'onchange' => 'accessSwitcher(this.value)',
8495
            'id' => 'access',
8496
        ]);
8497
8498
        $form->addHtml('<div id="duration_div" style="display:none">');
8499
        $form->addElement(
8500
            'number',
8501
            'duration',
8502
            [
8503
                get_lang('Session duration'),
8504
                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."),
8505
            ],
8506
            [
8507
                'maxlength' => 50,
8508
            ]
8509
        );
8510
8511
        $form->addHtml('</div>');
8512
        $form->addHtml('<div id="date_fields" style="display:none">');
8513
8514
        // Dates
8515
        $form->addDateTimePicker(
8516
            'access_start_date',
8517
            [get_lang('Access start date'), get_lang('Date on which the session is made available to all')],
8518
            ['id' => 'access_start_date']
8519
        );
8520
8521
        $form->addDateTimePicker(
8522
            'access_end_date',
8523
            [get_lang('Access end date'), get_lang('Date on which the session is closed')],
8524
            ['id' => 'access_end_date']
8525
        );
8526
8527
        $form->addRule(
8528
            ['access_start_date', 'access_end_date'],
8529
            get_lang('Start date must be before the end date'),
8530
            'compare_datetime_text',
8531
            '< allow_empty'
8532
        );
8533
8534
        $form->addDateTimePicker(
8535
            'display_start_date',
8536
            [
8537
                get_lang('Start date to display'),
8538
                get_lang('Date that will be shown in the session information as the date on which the session starts'),
8539
            ],
8540
            ['id' => 'display_start_date']
8541
        );
8542
8543
        $form->addDateTimePicker(
8544
            'display_end_date',
8545
            [
8546
                get_lang('End date to display'),
8547
                get_lang('Date that will be shown in the session information as the date on which the session ends'),
8548
            ],
8549
            ['id' => 'display_end_date']
8550
        );
8551
8552
        $form->addRule(
8553
            ['display_start_date', 'display_end_date'],
8554
            get_lang('Start date must be before the end date'),
8555
            'compare_datetime_text',
8556
            '< allow_empty'
8557
        );
8558
8559
        $form->addDateTimePicker(
8560
            'coach_access_start_date',
8561
            [
8562
                get_lang('Access start date for coaches'),
8563
                get_lang('Date on which the session is made available to coaches, so they can prepare it before the students get connected'),
8564
            ],
8565
            ['id' => 'coach_access_start_date']
8566
        );
8567
8568
        $form->addDateTimePicker(
8569
            'coach_access_end_date',
8570
            [
8571
                get_lang('Access end date for coaches'),
8572
                get_lang('Date on which the session is closed to coaches. The additional delay will allow them to export all relevant tracking information'),
8573
            ],
8574
            ['id' => 'coach_access_end_date']
8575
        );
8576
8577
        $form->addRule(
8578
            ['coach_access_start_date', 'coach_access_end_date'],
8579
            get_lang('Start date must be before the end date'),
8580
            'compare_datetime_text',
8581
            '< allow_empty'
8582
        );
8583
8584
        $form->addElement('html', '</div>');
8585
8586
        $form->addCheckBox(
8587
            'send_subscription_notification',
8588
            get_lang('Send an email when a user being subscribed to session'),
8589
        );
8590
8591
        $form->addCheckBox(
8592
            'notify_boss',
8593
            get_lang('Notify subscription of user to student boss')
8594
        );
8595
8596
        // Picture
8597
        $form->addFile(
8598
            'picture',
8599
            get_lang('Add image'),
8600
            ['id' => 'picture', 'class' => 'picture-form', 'crop_image' => true]
8601
        );
8602
        $allowedPictureTypes = api_get_supported_image_extensions(false);
8603
        $form->addRule('picture', get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowedPictureTypes).')', 'filetype', $allowedPictureTypes);
8604
8605
        if ($session && $session->getImage()) {
8606
            if (isset($fromSessionId)) {
8607
                $imageUrl = self::getSessionPictureUrl($session);
8608
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8609
                $form->addHidden('image_session_template', $imageUrl);
8610
8611
            } else {
8612
                $form->addElement('checkbox', 'delete_picture', null, get_lang('Delete picture'));
8613
                $imageUrl = self::getSessionPictureUrl($session);
8614
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8615
            }
8616
        }
8617
8618
        // Extra fields
8619
        $extra_field = new ExtraFieldModel('session');
8620
        $extra = $extra_field->addElements($form, $session ? $session->getId() : 0, ['image']);
8621
8622
        if ('true' === api_get_setting('session.enable_auto_reinscription')) {
8623
            $form->addElement(
8624
                'text',
8625
                'days_before_finishing_for_reinscription',
8626
                get_lang('Days before finishing for re-enrollment'),
8627
                ['maxlength' => 5]
8628
            );
8629
            $form->addRule(
8630
                'days_before_finishing_for_reinscription',
8631
                get_lang('The field must be empty or a positive integer'),
8632
                'regex',
8633
                '/^\d*$/'
8634
            );
8635
        }
8636
8637
        if ('true' === api_get_setting('session.enable_session_replication')) {
8638
            $form->addElement(
8639
                'text',
8640
                'days_before_finishing_to_create_new_repetition',
8641
                get_lang('Days before finishing automated creation of new repetitions'),
8642
                ['maxlength' => 5]
8643
            );
8644
            $form->addRule(
8645
                'days_before_finishing_to_create_new_repetition',
8646
                get_lang('The field must be empty or a positive integer'),
8647
                'regex',
8648
                '/^\d*$/'
8649
            );
8650
        }
8651
8652
        if ('true' === api_get_setting('session.enable_auto_reinscription') || 'true' === api_get_setting('session.enable_session_replication')) {
8653
            $form->addElement(
8654
                'checkbox',
8655
                'last_repetition',
8656
                get_lang('Last repetition')
8657
            );
8658
8659
            $form->addElement(
8660
                'number',
8661
                'validity_in_days',
8662
                get_lang('Validity (days)'),
8663
                [
8664
                    'min' => 0,
8665
                    'max' => 365,
8666
                    'step' => 1,
8667
                    'placeholder' => get_lang('Number of days'),
8668
                ]
8669
            );
8670
8671
            $form->addRule(
8672
                'validity_in_days',
8673
                get_lang('The field must be a positive integer'),
8674
                'numeric',
8675
                null,
8676
                'client'
8677
            );
8678
        }
8679
8680
        /** @var HTML_QuickForm_select $element */
8681
        $element = $form->createElement(
8682
            'select',
8683
            'parent_id',
8684
            get_lang('Parent session'),
8685
            [],
8686
            ['class' => 'form-control']
8687
        );
8688
8689
        $element->addOption(get_lang('None'), 0, []);
8690
        $sessions = SessionManager::getListOfParentSessions();
8691
        $currentSessionId = $session?->getId();
8692
        foreach ($sessions as $id => $title) {
8693
            if ($id !== $currentSessionId) {
8694
                $attributes = [];
8695
                $element->addOption($title, $id, $attributes);
8696
            }
8697
        }
8698
        $element->setSelected($session?->getParentId() ?? 0);
8699
        $form->addElement($element);
8700
8701
        $form->addElement('html', '</div>');
8702
8703
        $js = $extra['jquery_ready_content'];
8704
8705
        return ['js' => $js];
8706
    }
8707
8708
    /**
8709
     * Saves the session picture.
8710
     *
8711
     * @param int    $sessionId
8712
     * @param array  $file
8713
     * @param string $crop
8714
     *
8715
     * @return false
8716
     */
8717
    public static function updateSessionPicture(
8718
        $sessionId,
8719
        $file,
8720
        string $crop = ''
8721
    ) {
8722
        if (empty($file)) {
8723
            return false;
8724
        }
8725
8726
        $sessionRepo = Container::getSessionRepository();
8727
        $assetRepo = Container::getAssetRepository();
8728
8729
        $asset = (new Asset())
8730
            ->setCategory(Asset::SESSION)
8731
            ->setTitle($file['name'])
8732
        ;
8733
        if (!empty($crop)) {
8734
            $asset->setCrop($crop);
8735
        }
8736
        $asset = $assetRepo->createFromRequest($asset, $file);
8737
8738
        /** @var Session $session */
8739
        $session = $sessionRepo->find($sessionId);
8740
        $session->setImage($asset);
8741
        $sessionRepo->update($session);
8742
    }
8743
8744
    /**
8745
     * Deletes de session picture as asset.
8746
     *
8747
     * @param int $sessionId
8748
     */
8749
    public static function deleteAsset(int $sessionId): void
8750
    {
8751
        $sessionRepo = Container::getSessionRepository();
8752
8753
        /** @var Session $session */
8754
        $session = $sessionRepo->find($sessionId);
8755
        $em = Database::getManager();
8756
        if ($session->hasImage()) {
8757
            $asset = $session->getImage();
8758
            $em->remove($asset);
8759
            $em->flush();
8760
        }
8761
    }
8762
8763
    /**
8764
     * Get the session picture url.
8765
     *
8766
     * @param Session $session
8767
     * @return string
8768
     */
8769
    public static function getSessionPictureUrl(Session $session): string
8770
    {
8771
        $assetRepo = Container::getAssetRepository();
8772
        $imageUrl = $assetRepo->getAssetUrl($session->getImage());
8773
8774
        return $imageUrl;
8775
    }
8776
8777
    /**
8778
     * Gets the number of rows in the session table filtered through the given
8779
     * array of parameters.
8780
     *
8781
     * @param array Array of options/filters/keys
8782
     *
8783
     * @return int The number of rows, or false on wrong param
8784
     * @assert ('a') === false
8785
     */
8786
    public static function get_count_admin_complete($options = [])
8787
    {
8788
        if (!is_array($options)) {
8789
            return false;
8790
        }
8791
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
8792
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
8793
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8794
        $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
8795
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
8796
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8797
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
8798
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8799
8800
        $where = 'WHERE 1 = 1 AND u.active <> -1 ';
8801
8802
        if (api_is_session_admin() &&
8803
            'false' == api_get_setting('allow_session_admins_to_see_all_sessions')
8804
        ) {
8805
            $user_id = api_get_user_id();
8806
            $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
8807
        } else {
8808
            $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
8809
        }
8810
8811
        $extraFieldTables = '';
8812
        if (!empty($options['where'])) {
8813
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
8814
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
8815
8816
            $options['where'] = str_replace(
8817
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
8818
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
8819
                $options['where']
8820
            );
8821
8822
            $options['where'] = str_replace(
8823
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
8824
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
8825
                $options['where']
8826
            );
8827
8828
            if (!empty($options['extra'])) {
8829
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
8830
                $options['where'] = str_replace('AND', 'OR', $options['where']);
8831
8832
                foreach ($options['extra'] as $extra) {
8833
                    $options['where'] = str_replace(
8834
                        $extra['field'],
8835
                        'fv.field_id = '.$extra['id'].' AND fvo.option_value',
8836
                        $options['where']
8837
                    );
8838
                    $extraFieldTables = "$tbl_session_field_values fv, $tbl_session_field_options fvo, ";
8839
                }
8840
            }
8841
            $where .= ' AND '.$options['where'];
8842
        }
8843
8844
        $today = api_get_utc_datetime();
8845
        $query_rows = "SELECT count(*) as total_rows, c.title as course_title, s.title,
8846
                        IF (
8847
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
8848
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
8849
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
8850
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
8851
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
8852
                        , 1, 0) as session_active
8853
                       FROM $extraFieldTables $tbl_session s
8854
                       LEFT JOIN  $tbl_session_category sc
8855
                       ON s.session_category_id = sc.id
8856
                       INNER JOIN $tblSessionRelUser sru
8857
                       ON s.id = sru.session_id
8858
                       INNER JOIN $tbl_user u
8859
                       ON sru.user_id = u.id
8860
                       INNER JOIN $sessionCourseUserTable scu
8861
                       ON s.id = scu.session_id
8862
                       INNER JOIN $courseTable c
8863
                       ON c.id = scu.c_id
8864
                       $where ";
8865
8866
        if (api_is_multiple_url_enabled()) {
8867
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8868
            $access_url_id = api_get_current_access_url_id();
8869
            if (-1 != $access_url_id) {
8870
                $where .= " AND ar.access_url_id = $access_url_id ";
8871
                $query_rows = "SELECT count(*) as total_rows
8872
                               FROM $tbl_session s
8873
                               LEFT JOIN  $tbl_session_category sc
8874
                               ON s.session_category_id = sc.id
8875
                               INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
8876
                               INNER JOIN $tbl_user u
8877
                               ON sru.user_id = u.id
8878
                               INNER JOIN $table_access_url_rel_session ar
8879
                               ON ar.session_id = s.id $where ";
8880
            }
8881
        }
8882
8883
        $result = Database::query($query_rows);
8884
        $num = 0;
8885
        if (Database::num_rows($result)) {
8886
            $rows = Database::fetch_array($result);
8887
            $num = $rows['total_rows'];
8888
        }
8889
8890
        return $num;
8891
    }
8892
8893
    /**
8894
     * @param string $listType
8895
     * @param array  $extraFields
8896
     *
8897
     * @return array
8898
     */
8899
    public static function getGridColumns(
8900
        $listType = 'all',
8901
        $extraFields = [],
8902
        $addExtraFields = true
8903
    ) {
8904
        $showCount = ('true' === api_get_setting('session.session_list_show_count_users'));
8905
        // Column config
8906
        $operators = ['cn', 'nc'];
8907
        $date_operators = ['gt', 'ge', 'lt', 'le'];
8908
8909
        switch ($listType) {
8910
            case 'my_space':
8911
                $columns = [
8912
                    get_lang('Title'),
8913
                    get_lang('Date'),
8914
                    get_lang('Number of courses per session'),
8915
                    get_lang('Number of learners by session'),
8916
                    get_lang('Details'),
8917
                ];
8918
8919
                $columnModel = [
8920
                    ['name' => 'title', 'index' => 'title', 'align' => 'left'],
8921
                    ['name' => 'date', 'index' => 'access_start_date', 'align' => 'left'],
8922
                    [
8923
                        'name' => 'course_per_session',
8924
                        'index' => 'course_per_session',
8925
                        'sortable' => 'false',
8926
                        'search' => 'false',
8927
                    ],
8928
                    [
8929
                        'name' => 'student_per_session',
8930
                        'index' => 'student_per_session',
8931
                        'sortable' => 'false',
8932
                        'search' => 'false',
8933
                    ],
8934
                    [
8935
                        'name' => 'actions',
8936
                        'index' => 'actions',
8937
                        'sortable' => 'false',
8938
                        'search' => 'false',
8939
                    ],
8940
                ];
8941
                break;
8942
            case 'all':
8943
            case 'active':
8944
            case 'close':
8945
                $columns = [
8946
                    '#',
8947
                    get_lang('Title'),
8948
                    get_lang('Category'),
8949
                    get_lang('Start date to display'),
8950
                    get_lang('End date to display'),
8951
                    get_lang('Visibility'),
8952
                ];
8953
8954
                $columnModel = [
8955
                    [
8956
                        'name' => 'id',
8957
                        'index' => 's.id',
8958
                        'hidden' => 'true',
8959
                    ],
8960
                    [
8961
                        'name' => 'title',
8962
                        'index' => 's.title',
8963
                        'width' => '300',
8964
                        'align' => 'left',
8965
                        'search' => 'true',
8966
                        'searchoptions' => ['sopt' => $operators],
8967
                    ],
8968
                    [
8969
                        'name' => 'category_name',
8970
                        'index' => 'category_name',
8971
                        'align' => 'left',
8972
                        'search' => 'true',
8973
                        'searchoptions' => ['sopt' => $operators],
8974
                    ],
8975
                    [
8976
                        'name' => 'display_start_date',
8977
                        'index' => 'display_start_date',
8978
                        'align' => 'left',
8979
                        'width' => '200',
8980
                        'search' => 'true',
8981
                        'searchoptions' => [
8982
                            'dataInit' => 'date_pick_today',
8983
                            'sopt' => $date_operators,
8984
                        ],
8985
                    ],
8986
                    [
8987
                        'name' => 'display_end_date',
8988
                        'index' => 'display_end_date',
8989
                        'align' => 'left',
8990
                        'width' => '200',
8991
                        'search' => 'true',
8992
                        'searchoptions' => [
8993
                            'dataInit' => 'date_pick_one_month',
8994
                            'sopt' => $date_operators,
8995
                        ],
8996
                    ],
8997
                    [
8998
                        'name' => 'visibility',
8999
                        'index' => 'visibility',
9000
                        'align' => 'left',
9001
                        'search' => 'false',
9002
                    ],
9003
                ];
9004
9005
                if ($showCount) {
9006
                    $columns[] = get_lang('Users');
9007
                    $columnModel[] = [
9008
                        'name' => 'users',
9009
                        'index' => 'users',
9010
                        'align' => 'left',
9011
                        'width' => '100',
9012
                        'search' => 'false',
9013
                    ];
9014
9015
                    // ofaj
9016
                    $columns[] = get_lang('Teachers');
9017
                    $columnModel[] = [
9018
                        'name' => 'teachers',
9019
                        'index' => 'teachers',
9020
                        'align' => 'left',
9021
                        'search' => 'false',
9022
                    ];
9023
                }
9024
9025
                $columns[] = get_lang('Session status');
9026
                $list = self::getStatusList();
9027
                $listToString = '';
9028
                foreach ($list as $statusId => $status) {
9029
                    $listToString .= $statusId.':'.$status.';';
9030
                }
9031
9032
                $columnModel[] = [
9033
                    'name' => 'status',
9034
                    'index' => 'status',
9035
                    'align' => 'left',
9036
                    'width' => '120',
9037
                    'search' => 'true',
9038
                    'stype' => 'select',
9039
                    // for the bottom bar
9040
                    'searchoptions' => [
9041
                        'defaultValue' => '1',
9042
                        'value' => $listToString,
9043
                    ],
9044
                ];
9045
9046
                break;
9047
9048
            case 'simple':
9049
                $columns = [
9050
                    '#',
9051
                    get_lang('Title'),
9052
                    get_lang('Category'),
9053
                    get_lang('Start date to display'),
9054
                    get_lang('End date to display'),
9055
                    get_lang('Visibility'),
9056
                ];
9057
9058
                $columnModel = [
9059
                    [
9060
                        'name' => 'id',
9061
                        'index' => 's.id',
9062
                        'hidden' => 'true',
9063
                    ],
9064
                    [
9065
                        'name' => 'title',
9066
                        'index' => 's.title',
9067
                        'width' => '300',
9068
                        'align' => 'left',
9069
                        'search' => 'true',
9070
                        'searchoptions' => ['sopt' => $operators],
9071
                    ],
9072
                    [
9073
                        'name' => 'category_name',
9074
                        'index' => 'category_name',
9075
                        'align' => 'left',
9076
                        'search' => 'true',
9077
                        'searchoptions' => ['sopt' => $operators],
9078
                    ],
9079
                    [
9080
                        'name' => 'display_start_date',
9081
                        'index' => 'display_start_date',
9082
                        'align' => 'left',
9083
                        'width' => '200',
9084
                        'search' => 'true',
9085
                        'searchoptions' => [
9086
                            'dataInit' => 'date_pick_today',
9087
                            'sopt' => $date_operators,
9088
                        ],
9089
                    ],
9090
                    [
9091
                        'name' => 'display_end_date',
9092
                        'index' => 'display_end_date',
9093
                        'align' => 'left',
9094
                        'width' => '200',
9095
                        'search' => 'true',
9096
                        'searchoptions' => [
9097
                            'dataInit' => 'date_pick_one_month',
9098
                            'sopt' => $date_operators,
9099
                        ],
9100
                    ],
9101
                    [
9102
                        'name' => 'visibility',
9103
                        'index' => 'visibility',
9104
                        'align' => 'left',
9105
                        'search' => 'false',
9106
                    ],
9107
                ];
9108
9109
                if ($showCount) {
9110
                    $columns[] = get_lang('Users');
9111
                    $columnModel[] = [
9112
                        'name' => 'users',
9113
                        'index' => 'users',
9114
                        'align' => 'left',
9115
                        'width' => '100',
9116
                        'search' => 'false',
9117
                    ];
9118
9119
                    // ofaj
9120
                    $columns[] = get_lang('Teachers');
9121
                    $columnModel[] = [
9122
                        'name' => 'teachers',
9123
                        'index' => 'teachers',
9124
                        'align' => 'left',
9125
                        'search' => 'false',
9126
                    ];
9127
                }
9128
9129
                $columns[] = get_lang('Session status');
9130
                $list = self::getStatusList();
9131
                $listToString = '';
9132
                foreach ($list as $statusId => $status) {
9133
                    $listToString .= $statusId.':'.$status.';';
9134
                }
9135
9136
                $columnModel[] = ['name' => 'status', 'index' => 'status', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
9137
                    // for the bottom bar
9138
                    'searchoptions' => [
9139
                        'defaultValue' => '1',
9140
                        'value' => $listToString,
9141
                    ],
9142
                ];
9143
9144
                break;
9145
            case 'complete':
9146
                $columns = [
9147
                    get_lang('Title'),
9148
                    get_lang('Start date to display'),
9149
                    get_lang('End date to display'),
9150
                    get_lang('Coach'),
9151
                    get_lang('Status'),
9152
                    get_lang('Visibility'),
9153
                    get_lang('Course title'),
9154
                ];
9155
                $columnModel = [
9156
                    [
9157
                        'name' => 'title',
9158
                        'index' => 's.title',
9159
                        'width' => '300',
9160
                        'align' => 'left',
9161
                        'search' => 'true',
9162
                        'searchoptions' => ['sopt' => $operators],
9163
                    ],
9164
                    [
9165
                        'name' => 'display_start_date',
9166
                        'index' => 'display_start_date',
9167
                        'align' => 'left',
9168
                        'width' => '200',
9169
                        'search' => 'true',
9170
                        'searchoptions' => ['dataInit' => 'date_pick_today', 'sopt' => $date_operators],
9171
                    ],
9172
                    [
9173
                        'name' => 'display_end_date',
9174
                        'index' => 'display_end_date',
9175
                        'width' => '200',
9176
                        'align' => 'left',
9177
                        'search' => 'true',
9178
                        'searchoptions' => ['dataInit' => 'date_pick_one_month', 'sopt' => $date_operators],
9179
                    ],
9180
                    [
9181
                        'name' => 'coach_name',
9182
                        'index' => 'coach_name',
9183
                        'align' => 'left',
9184
                        'search' => 'false',
9185
                        'searchoptions' => ['sopt' => $operators],
9186
                    ],
9187
                    [
9188
                        'name' => 'session_active',
9189
                        'index' => 'session_active',
9190
                        'align' => 'left',
9191
                        'search' => 'true',
9192
                        'stype' => 'select',
9193
                        // for the bottom bar
9194
                        'searchoptions' => [
9195
                            'defaultValue' => '1',
9196
                            'value' => '1:'.get_lang('Active').';0:'.get_lang('Inactive'),
9197
                        ],
9198
                        // for the top bar
9199
                        'editoptions' => [
9200
                            'value' => '" ":'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang(
9201
                                    'Inactive'
9202
                                ),
9203
                        ],
9204
                    ],
9205
                    [
9206
                        'name' => 'visibility',
9207
                        'index' => 'visibility',
9208
                        'align' => 'left',
9209
                        'search' => 'false',
9210
                    ],
9211
                    [
9212
                        'name' => 'course_title',
9213
                        'index' => 'course_title',
9214
                        'hidden' => 'true',
9215
                        'search' => 'true',
9216
                        'searchoptions' => ['searchhidden' => 'true', 'sopt' => $operators],
9217
                    ],
9218
                ];
9219
9220
                break;
9221
            case 'replication':
9222
            case 'custom':
9223
                $columns = [
9224
                    '#',
9225
                    get_lang('Title'),
9226
                    get_lang('Category'),
9227
                    get_lang('Start date to display'),
9228
                    get_lang('End date to display'),
9229
                    get_lang('Visibility'),
9230
                ];
9231
                $columnModel = [
9232
                    [
9233
                        'name' => 'id',
9234
                        'index' => 's.id',
9235
                        'hidden' => 'true',
9236
                    ],
9237
                    [
9238
                        'name' => 'title',
9239
                        'index' => 's.title',
9240
                        'width' => '260px',
9241
                        'width' => '300',
9242
                        'align' => 'left',
9243
                        'search' => 'true',
9244
                        'searchoptions' => ['sopt' => $operators],
9245
                    ],
9246
                    [
9247
                        'name' => 'category_name',
9248
                        'index' => 'category_name',
9249
                        'align' => 'left',
9250
                        'search' => 'true',
9251
                        'searchoptions' => ['sopt' => $operators],
9252
                    ],
9253
                    [
9254
                        'name' => 'display_start_date',
9255
                        'index' => 'display_start_date',
9256
                        'align' => 'left',
9257
                        'width' => '200',
9258
                        'search' => 'true',
9259
                        'searchoptions' => [
9260
                            'dataInit' => 'date_pick_today',
9261
                            'sopt' => $date_operators,
9262
                        ],
9263
                    ],
9264
                    [
9265
                        'name' => 'display_end_date',
9266
                        'index' => 'display_end_date',
9267
                        'align' => 'left',
9268
                        'width' => '200',
9269
                        'search' => 'true',
9270
                        'searchoptions' => [
9271
                            'dataInit' => 'date_pick_one_month',
9272
                            'sopt' => $date_operators,
9273
                        ],
9274
                    ],
9275
                    [
9276
                        'name' => 'visibility',
9277
                        'index' => 'visibility',
9278
                        'align' => 'left',
9279
                        'search' => 'false',
9280
                    ],
9281
                ];
9282
9283
                if ($showCount) {
9284
                    $columns[] = get_lang('Users');
9285
                    $columnModel[] = [
9286
                        'name' => 'users',
9287
                        'index' => 'users',
9288
                        'align' => 'left',
9289
                        'width' => '100',
9290
                        'search' => 'false',
9291
                    ];
9292
9293
                    // ofaj
9294
                    $columns[] = get_lang('Teachers');
9295
                    $columnModel[] = [
9296
                        'name' => 'teachers',
9297
                        'index' => 'teachers',
9298
                        'align' => 'left',
9299
                        'search' => 'false',
9300
                    ];
9301
                }
9302
9303
                $columns[] = get_lang('Session status');
9304
                $list = self::getStatusList();
9305
                $listToString = '';
9306
                foreach ($list as $statusId => $status) {
9307
                    $listToString .= $statusId.':'.$status.';';
9308
                }
9309
9310
                $columnModel[] = [
9311
                    'name' => 'status',
9312
                    'index' => 'status',
9313
                    'align' => 'left',
9314
                    'width' => '120',
9315
                    'search' => 'true',
9316
                    'stype' => 'select',
9317
                    // for the bottom bar
9318
                    'searchoptions' => [
9319
                        'defaultValue' => '1',
9320
                        'value' => $listToString,
9321
                    ],
9322
                ];
9323
9324
                break;
9325
        }
9326
9327
        if (!empty($extraFields)) {
9328
            foreach ($extraFields as $field) {
9329
                $columns[] = $field['display_text'];
9330
                $columnModel[] = [
9331
                    'name' => $field['variable'],
9332
                    'index' => $field['variable'],
9333
                    'align' => 'center',
9334
                    'search' => 'false',
9335
                ];
9336
            }
9337
        }
9338
9339
        // Inject extra session fields
9340
        $rules = [];
9341
        if ($addExtraFields) {
9342
            $sessionField = new ExtraFieldModel('session');
9343
            $rules = $sessionField->getRules($columns, $columnModel);
9344
        }
9345
9346
        if (!in_array('actions', array_column($columnModel, 'name'))) {
9347
            $columnModel[] = [
9348
                'name' => 'actions',
9349
                'index' => 'actions',
9350
                'align' => 'left',
9351
                'formatter' => 'action_formatter',
9352
                'sortable' => 'false',
9353
                'search' => 'false',
9354
            ];
9355
            $columns[] = get_lang('Actions');
9356
        }
9357
9358
        $columnName = [];
9359
        foreach ($columnModel as $col) {
9360
            $columnName[] = $col['name'];
9361
        }
9362
9363
        $return = [
9364
            'columns' => $columns,
9365
            'column_model' => $columnModel,
9366
            'rules' => $rules,
9367
            'simple_column_name' => $columnName,
9368
        ];
9369
9370
        return $return;
9371
    }
9372
9373
    /**
9374
     * Converts all dates sent through the param array (given form) to correct dates with timezones.
9375
     *
9376
     * @param array The dates The same array, with times converted
9377
     * @param bool $applyFormat Whether apply the DATE_TIME_FORMAT_SHORT format for sessions
9378
     *
9379
     * @return array The same array, with times converted
9380
     */
9381
    public static function convert_dates_to_local($params, $applyFormat = false)
9382
    {
9383
        if (!is_array($params)) {
9384
            return false;
9385
        }
9386
        $params['display_start_date'] = api_get_local_time($params['display_start_date'], null, null, true);
9387
        $params['display_end_date'] = api_get_local_time($params['display_end_date'], null, null, true);
9388
9389
        $params['access_start_date'] = api_get_local_time($params['access_start_date'], null, null, true);
9390
        $params['access_end_date'] = api_get_local_time($params['access_end_date'], null, null, true);
9391
9392
        $params['coach_access_start_date'] = isset($params['coach_access_start_date']) ? api_get_local_time($params['coach_access_start_date'], null, null, true) : null;
9393
        $params['coach_access_end_date'] = isset($params['coach_access_end_date']) ? api_get_local_time($params['coach_access_end_date'], null, null, true) : null;
9394
9395
        if ($applyFormat) {
9396
            if (isset($params['display_start_date'])) {
9397
                $params['display_start_date'] = api_format_date($params['display_start_date'], DATE_TIME_FORMAT_SHORT);
9398
            }
9399
9400
            if (isset($params['display_end_date'])) {
9401
                $params['display_end_date'] = api_format_date($params['display_end_date'], DATE_TIME_FORMAT_SHORT);
9402
            }
9403
9404
            if (isset($params['access_start_date'])) {
9405
                $params['access_start_date'] = api_format_date($params['access_start_date'], DATE_TIME_FORMAT_SHORT);
9406
            }
9407
9408
            if (isset($params['access_end_date'])) {
9409
                $params['access_end_date'] = api_format_date($params['access_end_date'], DATE_TIME_FORMAT_SHORT);
9410
            }
9411
9412
            if (isset($params['coach_access_start_date'])) {
9413
                $params['coach_access_start_date'] = api_format_date($params['coach_access_start_date'], DATE_TIME_FORMAT_SHORT);
9414
            }
9415
9416
            if (isset($params['coach_access_end_date'])) {
9417
                $params['coach_access_end_date'] = api_format_date($params['coach_access_end_date'], DATE_TIME_FORMAT_SHORT);
9418
            }
9419
        }
9420
9421
        return $params;
9422
    }
9423
9424
    /**
9425
     * Gets the admin session list callback of the session/session_list.php
9426
     * page with all user/details in the right fomat.
9427
     *
9428
     * @param array $options
9429
     *
9430
     * @return array Array of rows results
9431
     * @asset ('a') === false
9432
     */
9433
    public static function get_sessions_admin_complete($options = [])
9434
    {
9435
        if (!is_array($options)) {
9436
            return false;
9437
        }
9438
9439
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
9440
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
9441
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
9442
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9443
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
9444
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
9445
9446
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
9447
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
9448
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
9449
9450
        $where = 'WHERE 1 = 1 ';
9451
9452
        if (!api_is_platform_admin()) {
9453
            if (api_is_session_admin() &&
9454
                'false' == api_get_setting('allow_session_admins_to_manage_all_sessions')
9455
            ) {
9456
                $user_id = api_get_user_id();
9457
                $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
9458
            } else {
9459
                $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
9460
            }
9461
        }
9462
9463
        $coach_name = " CONCAT(u.lastname , ' ', u.firstname) as coach_name ";
9464
        if (api_is_western_name_order()) {
9465
            $coach_name = " CONCAT(u.firstname, ' ', u.lastname) as coach_name ";
9466
        }
9467
9468
        $today = api_get_utc_datetime();
9469
        $injectExtraFields = null;
9470
        $extra_fields_info = [];
9471
9472
        //for now only sessions
9473
        $extra_field = new ExtraFieldModel('session');
9474
        $double_fields = [];
9475
        $extra_field_option = new ExtraFieldOption('session');
9476
9477
        if (isset($options['extra'])) {
9478
            $extra_fields = $options['extra'];
9479
            if (!empty($extra_fields)) {
9480
                foreach ($extra_fields as $extra) {
9481
                    $injectExtraFields .= " IF (fv.field_id = {$extra['id']}, fvo.option_display_text, NULL ) as {$extra['field']} , ";
9482
                    if (isset($extra_fields_info[$extra['id']])) {
9483
                        $info = $extra_fields_info[$extra['id']];
9484
                    } else {
9485
                        $info = $extra_field->get($extra['id']);
9486
                        $extra_fields_info[$extra['id']] = $info;
9487
                    }
9488
9489
                    if (ExtraFieldModel::FIELD_TYPE_DOUBLE_SELECT == $info['value_type']) {
9490
                        $double_fields[$info['id']] = $info;
9491
                    }
9492
                }
9493
            }
9494
        }
9495
9496
        $options_by_double = [];
9497
        foreach ($double_fields as $double) {
9498
            $my_options = $extra_field_option->get_field_options_by_field(
9499
                $double['id'],
9500
                true
9501
            );
9502
            $options_by_double['extra_'.$double['field_variable']] = $my_options;
9503
        }
9504
9505
        //sc.title as category_name,
9506
        $select = "
9507
                SELECT * FROM (
9508
                    SELECT DISTINCT
9509
                        IF (
9510
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
9511
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
9512
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
9513
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
9514
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
9515
                        , 1, 0) as session_active,
9516
                s.title,
9517
                s.nbr_courses,
9518
                s.nbr_users,
9519
                s.display_start_date,
9520
                s.display_end_date,
9521
                $coach_name,
9522
                access_start_date,
9523
                access_end_date,
9524
                s.visibility,
9525
                u.id as user_id,
9526
                $injectExtraFields
9527
                c.title as course_title,
9528
                s.id ";
9529
9530
        if (!empty($options['where'])) {
9531
            if (!empty($options['extra'])) {
9532
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
9533
                $options['where'] = str_replace('AND', 'OR', $options['where']);
9534
                foreach ($options['extra'] as $extra) {
9535
                    $options['where'] = str_replace($extra['field'], 'fv.field_id = '.$extra['id'].' AND fvo.option_value', $options['where']);
9536
                }
9537
            }
9538
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
9539
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
9540
            $options['where'] = str_replace(
9541
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
9542
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
9543
                $options['where']
9544
            );
9545
9546
            $options['where'] = str_replace(
9547
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
9548
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
9549
                $options['where']
9550
            );
9551
9552
            $where .= ' AND '.$options['where'];
9553
        }
9554
9555
        $limit = '';
9556
        if (!empty($options['limit'])) {
9557
            $limit = ' LIMIT '.$options['limit'];
9558
        }
9559
9560
        $query = "$select FROM $tbl_session s
9561
                    LEFT JOIN $tbl_session_field_values fv
9562
                    ON (fv.item_id = s.id)
9563
                    LEFT JOIN $extraFieldTable f
9564
                    ON f.id = fv.field_id
9565
                    LEFT JOIN $tbl_session_field_options fvo
9566
                    ON (fv.field_id = fvo.field_id)
9567
                    LEFT JOIN $tbl_session_rel_course src
9568
                    ON (src.session_id = s.id)
9569
                    LEFT JOIN $tbl_course c
9570
                    ON (src.c_id = c.id)
9571
                    LEFT JOIN $tbl_session_category sc
9572
                    ON (s.session_category_id = sc.id)
9573
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9574
                    INNER JOIN $tbl_user u
9575
                    ON sru.user_id = u.id
9576
                    $where
9577
                    $limit
9578
        ";
9579
9580
        if (api_is_multiple_url_enabled()) {
9581
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
9582
            $access_url_id = api_get_current_access_url_id();
9583
            if (-1 != $access_url_id) {
9584
                $query = "$select
9585
                    FROM $tbl_session s
9586
                    LEFT JOIN $tbl_session_field_values fv
9587
                    ON (fv.item_id = s.id)
9588
                    LEFT JOIN $tbl_session_field_options fvo
9589
                    ON (fv.field_id = fvo.field_id)
9590
                    LEFT JOIN $tbl_session_rel_course src
9591
                    ON (src.session_id = s.id)
9592
                    LEFT JOIN $tbl_course c
9593
                    ON (src.c_id = c.id)
9594
                    LEFT JOIN $tbl_session_category sc
9595
                    ON (s.session_category_id = sc.id)
9596
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9597
                    INNER JOIN $tbl_user u
9598
                    ON sru.user_id = u.id
9599
                    INNER JOIN $table_access_url_rel_session ar
9600
                    ON (ar.session_id = s.id AND ar.access_url_id = $access_url_id)
9601
                    $where
9602
                    $limit
9603
                ";
9604
            }
9605
        }
9606
9607
        $query .= ') AS s';
9608
9609
        if (!empty($options['order'])) {
9610
            $query .= ' ORDER BY '.$options['order'];
9611
        }
9612
9613
        $result = Database::query($query);
9614
9615
        $acceptIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
9616
9617
        $errorIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
9618
9619
        $formatted_sessions = [];
9620
        if (Database::num_rows($result)) {
9621
            $sessions = Database::store_result($result, 'ASSOC');
9622
            foreach ($sessions as $session) {
9623
                $session_id = $session['id'];
9624
                $session['title'] = Display::url($session['title'], "resume_session.php?id_session=".$session['id']);
9625
                $session['coach_name'] = Display::url($session['coach_name'], "user_information.php?user_id=".$session['user_id']);
9626
                if (1 == $session['session_active']) {
9627
                    $session['session_active'] = $acceptIcon;
9628
                } else {
9629
                    $session['session_active'] = $errorIcon;
9630
                }
9631
9632
                $session = self::convert_dates_to_local($session);
9633
9634
                switch ($session['visibility']) {
9635
                    case SESSION_VISIBLE_READ_ONLY: //1
9636
                        $session['visibility'] = get_lang('Read only');
9637
                        break;
9638
                    case SESSION_VISIBLE:           //2
9639
                    case SESSION_AVAILABLE:         //4
9640
                        $session['visibility'] = get_lang('Visible');
9641
                        break;
9642
                    case SESSION_INVISIBLE:         //3
9643
                        $session['visibility'] = api_ucfirst(get_lang('invisible'));
9644
                        break;
9645
                }
9646
9647
                // Cleaning double selects
9648
                foreach ($session as $key => &$value) {
9649
                    if (isset($options_by_double[$key]) || isset($options_by_double[$key.'_second'])) {
9650
                        $options = explode('::', $value);
9651
                    }
9652
                    $original_key = $key;
9653
9654
                    if (false === strpos($key, '_second')) {
9655
                    } else {
9656
                        $key = str_replace('_second', '', $key);
9657
                    }
9658
9659
                    if (isset($options_by_double[$key])) {
9660
                        if (isset($options[0])) {
9661
                            if (isset($options_by_double[$key][$options[0]])) {
9662
                                if (false === strpos($original_key, '_second')) {
9663
                                    $value = $options_by_double[$key][$options[0]]['option_display_text'];
9664
                                } else {
9665
                                    $value = $options_by_double[$key][$options[1]]['option_display_text'];
9666
                                }
9667
                            }
9668
                        }
9669
                    }
9670
                }
9671
9672
                // Magic filter
9673
                if (isset($formatted_sessions[$session_id])) {
9674
                    $formatted_sessions[$session_id] = self::compareArraysToMerge(
9675
                        $formatted_sessions[$session_id],
9676
                        $session
9677
                    );
9678
                } else {
9679
                    $formatted_sessions[$session_id] = $session;
9680
                }
9681
            }
9682
        }
9683
9684
        return $formatted_sessions;
9685
    }
9686
9687
    /**
9688
     * Compare two arrays.
9689
     *
9690
     * @param array $array1
9691
     * @param array $array2
9692
     *
9693
     * @return array
9694
     */
9695
    public static function compareArraysToMerge($array1, $array2)
9696
    {
9697
        if (empty($array2)) {
9698
            return $array1;
9699
        }
9700
        foreach ($array1 as $key => $item) {
9701
            if (!isset($array1[$key])) {
9702
                //My string is empty try the other one
9703
                if (isset($array2[$key]) && !empty($array2[$key])) {
9704
                    $array1[$key] = $array2[$key];
9705
                }
9706
            }
9707
        }
9708
9709
        return $array1;
9710
    }
9711
9712
    /**
9713
     * Get link to the admin page for this session.
9714
     *
9715
     * @param int $id Session ID
9716
     *
9717
     * @return mixed URL to the admin page to manage the session, or false on error
9718
     */
9719
    public static function getAdminPath($id)
9720
    {
9721
        $id = (int) $id;
9722
        $session = self::fetch($id);
9723
        if (empty($session)) {
9724
            return false;
9725
        }
9726
9727
        return api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$id;
9728
    }
9729
9730
    /**
9731
     * Get link to the user page for this session.
9732
     * If a course is provided, build the link to the course.
9733
     *
9734
     * @param int $id       Session ID
9735
     * @param int $courseId Course ID (optional) in case the link has to send straight to the course
9736
     *
9737
     * @return mixed URL to the page to use the session, or false on error
9738
     */
9739
    public static function getPath($id, $courseId = 0)
9740
    {
9741
        $id = (int) $id;
9742
        $session = self::fetch($id);
9743
        if (empty($session)) {
9744
            return false;
9745
        }
9746
        if (empty($courseId)) {
9747
            return api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$id;
9748
        } else {
9749
            $courseInfo = api_get_course_info_by_id($courseId);
9750
            if ($courseInfo) {
9751
                return $courseInfo['course_public_url'].'?id_session='.$id;
9752
            }
9753
        }
9754
9755
        return false;
9756
    }
9757
9758
    /**
9759
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9760
     * where course id_course is in sessions id_session1, id_session2
9761
     * for course where user is coach
9762
     * i.e. coach for the course or
9763
     * main coach for a session the course is in
9764
     * for a session category (or woth no session category if empty).
9765
     *
9766
     * @param int $userId
9767
     *
9768
     * @return array
9769
     */
9770
    public static function getSessionCourseForUser($userId)
9771
    {
9772
        // list of COURSES where user is COURSE session coach
9773
        $listCourseCourseCoachSession = self::getCoursesForCourseSessionCoach($userId);
9774
        // list of courses where user is MAIN session coach
9775
        $listCourseMainCoachSession = self::getCoursesForMainSessionCoach($userId);
9776
        // merge these 2 array
9777
        $listResCourseSession = $listCourseCourseCoachSession;
9778
        foreach ($listCourseMainCoachSession as $courseId2 => $listSessionId2) {
9779
            if (isset($listResCourseSession[$courseId2])) {
9780
                // if sessionId array exists for this course
9781
                // same courseId, merge the list of session
9782
                foreach ($listCourseMainCoachSession[$courseId2] as $i => $sessionId2) {
9783
                    if (!in_array($sessionId2, $listResCourseSession[$courseId2])) {
9784
                        $listResCourseSession[$courseId2][] = $sessionId2;
9785
                    }
9786
                }
9787
            } else {
9788
                $listResCourseSession[$courseId2] = $listSessionId2;
9789
            }
9790
        }
9791
9792
        return $listResCourseSession;
9793
    }
9794
9795
    /**
9796
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9797
     * where course id_course is in sessions id_session1, id_session2.
9798
     *
9799
     * @param int $userId
9800
     *
9801
     * @return array
9802
     */
9803
    public static function getCoursesForCourseSessionCoach($userId)
9804
    {
9805
        $userId = (int) $userId;
9806
        $listResCourseSession = [];
9807
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9808
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9809
9810
        $sql = "SELECT session_id, c_id, c.id
9811
                FROM $tblSessionRelCourseRelUser srcru
9812
                LEFT JOIN $tblCourse c
9813
                ON c.id = srcru.c_id
9814
                WHERE
9815
                    srcru.user_id = $userId AND
9816
                    srcru.status = ".Session::COURSE_COACH;
9817
9818
        $res = Database::query($sql);
9819
9820
        while ($data = Database::fetch_assoc($res)) {
9821
            if (api_get_session_visibility($data['session_id'])) {
9822
                if (!isset($listResCourseSession[$data['id']])) {
9823
                    $listResCourseSession[$data['id']] = [];
9824
                }
9825
                $listResCourseSession[$data['id']][] = $data['session_id'];
9826
            }
9827
        }
9828
9829
        return $listResCourseSession;
9830
    }
9831
9832
    /**
9833
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9834
     * where course id_course is in sessions id_session1, id_session2.
9835
     *
9836
     * @param $userId
9837
     *
9838
     * @return array
9839
     */
9840
    public static function getCoursesForMainSessionCoach($userId)
9841
    {
9842
        $userId = (int) $userId;
9843
        $user = api_get_user_entity($userId);
9844
        $listResCourseSession = [];
9845
9846
        $sessions = $user->getSessionsAsGeneralCoach();
9847
9848
        foreach ($sessions as $session) {
9849
            $sessionId = $session->getId();
9850
            $listCoursesInSession = self::getCoursesInSession($sessionId);
9851
            foreach ($listCoursesInSession as $i => $courseId) {
9852
                if (api_get_session_visibility($sessionId)) {
9853
                    if (!isset($listResCourseSession[$courseId])) {
9854
                        $listResCourseSession[$courseId] = [];
9855
                    }
9856
                    $listResCourseSession[$courseId][] = $sessionId;
9857
                }
9858
            }
9859
        }
9860
9861
        return $listResCourseSession;
9862
    }
9863
9864
    /**
9865
     * Return an array of course_id used in session $sessionId.
9866
     *
9867
     * @param $sessionId
9868
     *
9869
     * @return array
9870
     */
9871
    public static function getCoursesInSession($sessionId)
9872
    {
9873
        if (empty($sessionId)) {
9874
            return [];
9875
        }
9876
9877
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9878
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9879
9880
        // list of course in this session
9881
        $sql = "SELECT session_id, c.id
9882
                FROM $tblSessionRelCourse src
9883
                LEFT JOIN $tblCourse c
9884
                ON c.id = src.c_id
9885
                WHERE session_id = ".intval($sessionId);
9886
        $res = Database::query($sql);
9887
9888
        $listResultsCourseId = [];
9889
        while ($data = Database::fetch_assoc($res)) {
9890
            $listResultsCourseId[] = $data['id'];
9891
        }
9892
9893
        return $listResultsCourseId;
9894
    }
9895
9896
    /**
9897
     * Return an array of courses in session for user
9898
     * and for each courses the list of session that use this course for user.
9899
     *
9900
     * [0] => array
9901
     *      userCatId
9902
     *      userCatTitle
9903
     *      courseInUserCatList
9904
     *          [0] => array
9905
     *              courseId
9906
     *              title
9907
     *              courseCode
9908
     *              sessionCatList
9909
     *                  [0] => array
9910
     *                      catSessionId
9911
     *                      catSessionName
9912
     *                      sessionList
9913
     *                          [0] => array
9914
     *                              sessionId
9915
     *                              sessionName
9916
     *
9917
     * @param int $userId
9918
     *
9919
     * @return array
9920
     */
9921
    public static function getNamedSessionCourseForCoach($userId)
9922
    {
9923
        $listResults = [];
9924
        $listCourseSession = self::getSessionCourseForUser($userId);
9925
        foreach ($listCourseSession as $courseId => $listSessionId) {
9926
            // Course info
9927
            $courseInfo = api_get_course_info_by_id($courseId);
9928
            $listOneCourse = [];
9929
            $listOneCourse['courseId'] = $courseId;
9930
            $listOneCourse['title'] = $courseInfo['title'];
9931
            //$listOneCourse['courseCode'] = $courseInfo['code'];
9932
            $listOneCourse['course'] = $courseInfo;
9933
            $listOneCourse['sessionCatList'] = [];
9934
            $listCat = [];
9935
            foreach ($listSessionId as $i => $sessionId) {
9936
                // here we got all session for this course
9937
                // lets check there session categories
9938
                $sessionInfo = self::fetch($sessionId);
9939
                $catId = $sessionInfo['session_category_id'];
9940
                if (!isset($listCat[$catId])) {
9941
                    $listCatInfo = self::get_session_category($catId);
9942
                    if ($listCatInfo) {
9943
                        $listCat[$catId] = [];
9944
                        $listCat[$catId]['catSessionId'] = $catId;
9945
                        $listCat[$catId]['catSessionName'] = $listCatInfo['title'];
9946
                        $listCat[$catId]['sessionList'] = [];
9947
                    }
9948
                }
9949
                $listSessionInfo = self::fetch($sessionId);
9950
                $listSessionIdName = [
9951
                    'sessionId' => $sessionId,
9952
                    'sessionName' => $listSessionInfo['title'],
9953
                ];
9954
                $listCat[$catId]['sessionList'][] = $listSessionIdName;
9955
            }
9956
            // sort $listCat by catSessionName
9957
            usort($listCat, 'self::compareBySessionName');
9958
            // in each catSession sort sessionList by sessionName
9959
            foreach ($listCat as $i => $listCatSessionInfo) {
9960
                $listSessionList = $listCatSessionInfo['sessionList'];
9961
                usort($listSessionList, 'self::compareCatSessionInfo');
9962
                $listCat[$i]['sessionList'] = $listSessionList;
9963
            }
9964
9965
            $listOneCourse['sessionCatList'] = $listCat;
9966
            //$listResults[$userCatId]['courseInUserCatList'][] = $listOneCourse;
9967
        }
9968
9969
        // sort by user course cat
9970
        uasort($listResults, 'self::compareByUserCourseCat');
9971
9972
        // sort by course title
9973
        foreach ($listResults as $userCourseCatId => $tabCoursesInCat) {
9974
            $courseInUserCatList = $tabCoursesInCat['courseInUserCatList'];
9975
            uasort($courseInUserCatList, 'self::compareByCourse');
9976
            $listResults[$userCourseCatId]['courseInUserCatList'] = $courseInUserCatList;
9977
        }
9978
9979
        return $listResults;
9980
    }
9981
9982
    /**
9983
     * @param int $userId
9984
     * @param int $courseId
9985
     *
9986
     * @return array
9987
     */
9988
    public static function searchCourseInSessionsFromUser($userId, $courseId)
9989
    {
9990
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9991
        $userId = (int) $userId;
9992
        $courseId = (int) $courseId;
9993
        if (empty($userId) || empty($courseId)) {
9994
            return [];
9995
        }
9996
9997
        $sql = "SELECT * FROM $table
9998
                WHERE c_id = $courseId AND user_id = $userId";
9999
        $result = Database::query($sql);
10000
10001
        return Database::store_result($result, 'ASSOC');
10002
    }
10003
10004
    /**
10005
     * Subscribe and redirect to session after inscription.
10006
     */
10007
    public static function redirectToSession()
10008
    {
10009
        $sessionId = (int) ChamiloSession::read('session_redirect');
10010
        $onlyOneCourseSessionToRedirect = ChamiloSession::read('only_one_course_session_redirect');
10011
        if ($sessionId) {
10012
            $sessionInfo = api_get_session_info($sessionId);
10013
            if (!empty($sessionInfo)) {
10014
                $userId = api_get_user_id();
10015
                $response = self::isUserSubscribedAsStudent($sessionId, $userId);
10016
                if ($response) {
10017
                    $urlToRedirect = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
10018
                    if (!empty($onlyOneCourseSessionToRedirect)) {
10019
                        $urlToRedirect = api_get_path(WEB_PATH).
10020
                            'courses/'.$onlyOneCourseSessionToRedirect.'/index.php?id_session='.$sessionId;
10021
                    }
10022
10023
                    header('Location: '.$urlToRedirect);
10024
                    exit;
10025
                }
10026
            }
10027
        }
10028
    }
10029
10030
    /**
10031
     * @return int
10032
     */
10033
    public static function getCountUsersInCourseSession(Course $course, Session $session)
10034
    {
10035
        $url = api_get_url_entity(api_get_current_access_url_id());
10036
10037
        return Database::getManager()
10038
            ->createQuery("
10039
                SELECT COUNT(scu)
10040
                FROM ChamiloCoreBundle:SessionRelCourseRelUser scu
10041
                INNER JOIN ChamiloCoreBundle:SessionRelUser su
10042
                    WITH scu.user = su.user
10043
                    AND scu.session = su.session
10044
                INNER JOIN ChamiloCoreBundle:AccessUrlRelUser a
10045
                    WITH a.user = su.user
10046
                WHERE
10047
                    scu.course = :course AND
10048
                    su.relationType <> :relationType AND
10049
                    scu.session = :session AND
10050
                    a.url = :url
10051
            ")
10052
            ->setParameters([
10053
                'course' => $course->getId(),
10054
                'relationType' => Session::DRH,
10055
                'session' => $session->getId(),
10056
                'url' => $url,
10057
            ])
10058
            ->getSingleScalarResult();
10059
    }
10060
10061
    /**
10062
     * Get course IDs where user in not subscribed in session.
10063
     *
10064
     * @return array
10065
     */
10066
    public static function getAvoidedCoursesInSession(User $user, Session $session)
10067
    {
10068
        $courseIds = [];
10069
10070
        /** @var SessionRelCourse $sessionCourse */
10071
        foreach ($session->getCourses() as $sessionCourse) {
10072
            /** @var Course $course */
10073
            $course = $sessionCourse->getCourse();
10074
10075
            if ($session->getUserInCourse($user, $course)->count()) {
10076
                continue;
10077
            }
10078
10079
            $courseIds[] = $course->getId();
10080
        }
10081
10082
        return $courseIds;
10083
    }
10084
10085
    /**
10086
     * @param int             $userId
10087
     * @param int             $sessionId
10088
     * @param ExtraFieldValue $extraFieldValue
10089
     * @param string          $collapsableLink
10090
     *
10091
     * @return array
10092
     */
10093
    public static function getCollapsableData($userId, $sessionId, $extraFieldValue, $collapsableLink)
10094
    {
10095
        $collapsed = 0;
10096
10097
        // Get default collapsed value in extra field
10098
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($sessionId, 'collapsed');
10099
        if (!empty($value) && isset($value['value'])) {
10100
            $collapsed = $value['value'];
10101
        }
10102
10103
        $userRelSession = self::getUserSession($userId, $sessionId);
10104
10105
        if ($userRelSession) {
10106
            if (isset($userRelSession['collapsed']) && '' != $userRelSession['collapsed']) {
10107
                $collapsed = $userRelSession['collapsed'];
10108
            }
10109
        } else {
10110
            return ['collapsed' => $collapsed, 'collapsable_link' => '&nbsp;'];
10111
        }
10112
10113
        $link = $collapsableLink.'&session_id='.$sessionId.'&value=1';
10114
        $image = '<i class="fa fa-folder-open"></i>';
10115
        if (1 == $collapsed) {
10116
            $link = $collapsableLink.'&session_id='.$sessionId.'&value=0';
10117
            $image = '<i class="fa fa-folder"></i>';
10118
        }
10119
10120
        $link = Display::url(
10121
            $image,
10122
            $link
10123
        );
10124
10125
        return ['collapsed' => $collapsed, 'collapsable_link' => $link];
10126
    }
10127
10128
    /**
10129
     * Converts "start date" and "end date" to "From start date to end date" string.
10130
     *
10131
     * @param string|DateTime $startDate
10132
     * @param string|DateTime $endDate
10133
     * @param bool   $showTime
10134
     * @param bool   $dateHuman
10135
     *
10136
     * @return string
10137
     */
10138
    public static function convertSessionDateToString($startDate, $endDate, $showTime, $dateHuman)
10139
    {
10140
        // api_get_local_time returns empty if date is invalid like 0000-00-00 00:00:00
10141
        $startDateToLocal = api_get_local_time(
10142
            $startDate,
10143
            null,
10144
            null,
10145
            true,
10146
            $showTime,
10147
            $dateHuman
10148
        );
10149
        $endDateToLocal = api_get_local_time(
10150
            $endDate,
10151
            null,
10152
            null,
10153
            true,
10154
            $showTime,
10155
            $dateHuman
10156
        );
10157
10158
        $format = $showTime ? DATE_TIME_FORMAT_LONG_24H : DATE_FORMAT_LONG_NO_DAY;
10159
10160
        $result = '';
10161
        if (!empty($startDateToLocal) && !empty($endDateToLocal)) {
10162
            $result = sprintf(
10163
                get_lang('From %s to %s'),
10164
                api_format_date($startDateToLocal, $format),
10165
                api_format_date($endDateToLocal, $format)
10166
            );
10167
        } else {
10168
            if (!empty($startDateToLocal)) {
10169
                $result = get_lang('From').' '.api_format_date($startDateToLocal, $format);
10170
            }
10171
            if (!empty($endDateToLocal)) {
10172
                $result = get_lang('Until').' '.api_format_date($endDateToLocal, $format);
10173
            }
10174
        }
10175
        if (empty($result)) {
10176
            $result = get_lang('No time limits');
10177
        }
10178
10179
        return $result;
10180
    }
10181
10182
    /**
10183
     * @param int $id
10184
     */
10185
    public static function getSessionChangeUserReason($id): string
10186
    {
10187
        $reasons = self::getSessionChangeUserReasons();
10188
10189
        return $reasons[$id] ?? '';
10190
    }
10191
10192
    public static function getSessionChangeUserReasons(): array
10193
    {
10194
        return [
10195
            self::SESSION_CHANGE_USER_REASON_SCHEDULE => get_lang('Schedule changed'),
10196
            self::SESSION_CHANGE_USER_REASON_CLASSROOM => get_lang('Classroom changed'),
10197
            self::SESSION_CHANGE_USER_REASON_LOCATION => get_lang('Location changed'),
10198
            //self::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION => get_lang('Enrollment cancelled'),
10199
        ];
10200
    }
10201
10202
    public static function getStatusList()
10203
    {
10204
        return [
10205
            self::STATUS_PLANNED => get_lang('Planned'),
10206
            self::STATUS_PROGRESS => get_lang('In progress'),
10207
            self::STATUS_FINISHED => get_lang('Finished'),
10208
            self::STATUS_CANCELLED => get_lang('Cancelled'),
10209
        ];
10210
    }
10211
10212
    public static function getStatusLabel($status)
10213
    {
10214
        $list = self::getStatusList();
10215
10216
        if (!isset($list[$status])) {
10217
            return get_lang('No status');
10218
        }
10219
10220
        return $list[$status];
10221
    }
10222
10223
    public static function getDefaultSessionTab()
10224
    {
10225
        $default = 'all';
10226
        $view = api_get_setting('session.default_session_list_view');
10227
10228
        if ('false' !== $view && !empty($view)) {
10229
            $default = $view;
10230
        }
10231
10232
        return $default;
10233
    }
10234
10235
    /**
10236
     * @return string
10237
     */
10238
    public static function getSessionListTabs($listType): string
10239
    {
10240
        $tabs = [
10241
            [
10242
                'content' => get_lang('All sessions'),
10243
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=all',
10244
            ],
10245
            [
10246
                'content' => get_lang('Active sessions'),
10247
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=active',
10248
            ],
10249
            [
10250
                'content' => get_lang('Closed sessions'),
10251
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=close',
10252
            ],
10253
            [
10254
                'content' => get_lang('Custom list'),
10255
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=custom',
10256
            ],
10257
            [
10258
                'content' => get_lang('Replication'),
10259
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=replication',
10260
            ],
10261
        ];
10262
        $default = null;
10263
        switch ($listType) {
10264
            case 'all':
10265
                $default = 1;
10266
                break;
10267
            case 'active':
10268
                $default = 2;
10269
                break;
10270
            case 'close':
10271
                $default = 3;
10272
                break;
10273
            case 'custom':
10274
                $default = 4;
10275
                break;
10276
            case 'replication':
10277
                $default = 5;
10278
                break;
10279
        }
10280
10281
        return Display::tabsOnlyLink($tabs, $default);
10282
    }
10283
10284
    /**
10285
     * Check if a session is followed by human resources manager.
10286
     *
10287
     * @param int $sessionId
10288
     * @param int $userId
10289
     *
10290
     * @return bool
10291
     */
10292
    public static function isSessionFollowedByDrh($sessionId, $userId)
10293
    {
10294
        $userId = (int) $userId;
10295
        $sessionId = (int) $sessionId;
10296
10297
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
10298
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
10299
10300
        if (api_is_multiple_url_enabled()) {
10301
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
10302
10303
            $sql = "SELECT s.id FROM $tblSession s
10304
                INNER JOIN $tblSessionRelUser sru ON (sru.session_id = s.id)
10305
                LEFT JOIN $tblSessionRelAccessUrl a ON (s.id = a.session_id)
10306
                WHERE
10307
                    sru.user_id = '$userId' AND
10308
                    sru.session_id = '$sessionId' AND
10309
                    sru.relation_type = '".Session::DRH."' AND
10310
                    access_url_id = ".api_get_current_access_url_id();
10311
        } else {
10312
            $sql = "SELECT s.id FROM $tblSession s
10313
                INNER JOIN $tblSessionRelUser sru ON sru.session_id = s.id
10314
                WHERE
10315
                    sru.user_id = '$userId' AND
10316
                    sru.session_id = '$sessionId' AND
10317
                    sru.relation_type = '".Session::DRH."'";
10318
        }
10319
10320
        $result = Database::query($sql);
10321
10322
        return Database::num_rows($result) > 0;
10323
    }
10324
10325
    /**
10326
     * Add a warning message when session is read-only mode.
10327
     */
10328
    public static function addFlashSessionReadOnly()
10329
    {
10330
        if (api_get_session_id() && !api_is_allowed_to_session_edit()) {
10331
            Display::addFlash(
10332
                Display::return_message(get_lang('The session is read only'), 'warning')
10333
            );
10334
        }
10335
    }
10336
10337
    public static function insertUsersInCourses(array $studentIds, array $courseIds, int $sessionId)
10338
    {
10339
        $session = api_get_session_entity($sessionId);
10340
10341
        foreach ($courseIds as $courseId) {
10342
            self::insertUsersInCourse($studentIds, $courseId, $sessionId, [], false);
10343
        }
10344
10345
        foreach ($studentIds as $studentId) {
10346
            $user = api_get_user_entity($studentId);
10347
10348
            $session->addUserInSession(Session::STUDENT, $user);
10349
        }
10350
    }
10351
10352
    /**
10353
     * @throws \Doctrine\ORM\Exception\ORMException
10354
     */
10355
    public static function insertUsersInCourse(
10356
        array $studentIds,
10357
        int $courseId,
10358
        int $sessionId,
10359
        array $relationInfo = [],
10360
        bool $updateSession = true,
10361
        bool $sendNotification = false
10362
    ) {
10363
        $em = Database::getManager();
10364
        $course = api_get_course_entity($courseId);
10365
        $session = api_get_session_entity($sessionId);
10366
10367
        $relationInfo = array_merge(['visibility' => 0, 'status' => Session::STUDENT], $relationInfo);
10368
10369
        $usersToInsert = [];
10370
        foreach ($studentIds as $studentId) {
10371
            $user = api_get_user_entity($studentId);
10372
            $session->addUserInCourse($relationInfo['status'], $user, $course)
10373
                ->setVisibility($relationInfo['visibility']);
10374
10375
            Event::logUserSubscribedInCourseSession($user, $course, $session);
10376
10377
            if ($updateSession) {
10378
                if (!$session->hasUserInSession($user, Session::STUDENT)) {
10379
                    $session->addUserInSession(Session::STUDENT, $user);
10380
                }
10381
            }
10382
10383
            $usersToInsert[] = $studentId;
10384
        }
10385
10386
        $em->persist($session);
10387
        $em->flush();
10388
10389
        if ($sendNotification && !empty($usersToInsert)) {
10390
            foreach ($usersToInsert as $userId) {
10391
                $user = api_get_user_entity($userId);
10392
                $courseTitle = $course->getTitle();
10393
                $sessionTitle = $session->getTitle();
10394
10395
                $subject = sprintf(get_lang('You have been enrolled in the course %s for the session %s'), $courseTitle, $sessionTitle);
10396
                $message = sprintf(
10397
                    get_lang('Hello %s, you have been enrolled in the course %s for the session %s.'),
10398
                    UserManager::formatUserFullName($user, true),
10399
                    $courseTitle,
10400
                    $sessionTitle
10401
                );
10402
10403
                MessageManager::send_message_simple(
10404
                    $userId,
10405
                    $subject,
10406
                    $message,
10407
                    api_get_user_id(),
10408
                    false,
10409
                    true,
10410
                    false
10411
                );
10412
            }
10413
        }
10414
    }
10415
10416
    public static function getCareersFromSession(int $sessionId): array
10417
    {
10418
        $extraFieldValueSession = new ExtraFieldValue('session');
10419
        $extraFieldValueCareer = new ExtraFieldValue('career');
10420
10421
        $value = $extraFieldValueSession->get_values_by_handler_and_field_variable($sessionId, 'careerid');
10422
        $careers = [];
10423
        if (isset($value['value']) && !empty($value['value'])) {
10424
            $careerList = str_replace(['[', ']'], '', $value['value']);
10425
            $careerList = explode(',', $careerList);
10426
10427
            $careerManager = new Career();
10428
            foreach ($careerList as $career) {
10429
                $careerIdValue = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
10430
                    'external_career_id',
10431
                    $career
10432
                );
10433
                if (isset($careerIdValue['item_id']) && !empty($careerIdValue['item_id'])) {
10434
                    $finalCareerId = $careerIdValue['item_id'];
10435
                    $careerInfo = $careerManager->get($finalCareerId);
10436
                    if (!empty($careerInfo)) {
10437
                        $careers[] = $careerInfo;
10438
                    }
10439
                }
10440
            }
10441
        }
10442
10443
        return $careers;
10444
    }
10445
10446
    public static function getCareerDiagramPerSessionList($sessionList, $userId)
10447
    {
10448
        if (empty($sessionList) || empty($userId)) {
10449
            return '';
10450
        }
10451
10452
        $userId = (int) $userId;
10453
        $content = Display::page_subheader(get_lang('Ongoing training'));
10454
        $content .= '
10455
           <script>
10456
            resizeIframe = function(iFrame) {
10457
                iFrame.height = iFrame.contentWindow.document.body.scrollHeight + 20;
10458
            }
10459
            </script>
10460
        ';
10461
        $careersAdded = [];
10462
        foreach ($sessionList as $sessionId) {
10463
            $visibility = api_get_session_visibility($sessionId, null, false, $userId);
10464
            if (SESSION_AVAILABLE === $visibility) {
10465
                $careerList = self::getCareersFromSession($sessionId);
10466
                if (empty($careerList)) {
10467
                    continue;
10468
                }
10469
                foreach ($careerList as $career) {
10470
                    $careerId = $career['id'];
10471
                    if (!in_array($careerId, $careersAdded)) {
10472
                        $careersAdded[] = $careerId;
10473
                        $careerUrl = api_get_path(WEB_CODE_PATH).'user/career_diagram.php?iframe=1&career_id='.$career['id'].'&user_id='.$userId;
10474
                        $content .= '
10475
                            <iframe
10476
                                onload="resizeIframe(this)"
10477
                                style="width:100%;"
10478
                                border="0"
10479
                                frameborder="0"
10480
                                scrolling="no"
10481
                                src="'.$careerUrl.'"
10482
                            ></iframe>';
10483
                    }
10484
                }
10485
            }
10486
        }
10487
10488
        return $content;
10489
    }
10490
10491
    private static function allowed(?Session $session = null): bool
10492
    {
10493
        if (api_is_platform_admin()) {
10494
            return true;
10495
        }
10496
10497
        if (null === $session) {
10498
            return false;
10499
        }
10500
10501
        $user = api_get_user_entity();
10502
10503
        if (api_is_session_admin() &&
10504
            'true' !== api_get_setting('session.allow_session_admins_to_manage_all_sessions')
10505
        ) {
10506
10507
            if (!$session->hasUserAsSessionAdmin($user)) {
10508
                return false;
10509
            }
10510
        }
10511
10512
        if (api_is_teacher() &&
10513
            'true' === api_get_setting('session.allow_teachers_to_create_sessions')
10514
        ) {
10515
            if (!$session->hasUserAsGeneralCoach($user))  {
10516
                return false;
10517
            }
10518
        }
10519
10520
        return true;
10521
    }
10522
10523
    /**
10524
     * Add classes (by their names) to a session.
10525
     *
10526
     * @param int   $sessionId
10527
     * @param array $classesNames
10528
     * @param bool  $deleteClassSessions Optional. Empty the session list for the usergroup (class)
10529
     */
10530
    private static function addClassesByName($sessionId, $classesNames, $deleteClassSessions = true)
10531
    {
10532
        if (!$classesNames) {
10533
            return;
10534
        }
10535
10536
        $usergroup = new UserGroupModel();
10537
10538
        foreach ($classesNames as $className) {
10539
            if (empty($className)) {
10540
                continue;
10541
            }
10542
10543
            $usergroup->subscribe_sessions_to_usergroup(
10544
                $usergroup->getIdByName($className),
10545
                [$sessionId],
10546
                $deleteClassSessions
10547
            );
10548
        }
10549
    }
10550
10551
    /**
10552
     * @param array $listA
10553
     * @param array $listB
10554
     *
10555
     * @return int
10556
     */
10557
    private static function compareCatSessionInfo($listA, $listB)
10558
    {
10559
        if ($listA['sessionName'] == $listB['sessionName']) {
10560
            return 0;
10561
        } elseif ($listA['sessionName'] > $listB['sessionName']) {
10562
            return 1;
10563
        } else {
10564
            return -1;
10565
        }
10566
    }
10567
10568
    /**
10569
     * @param array $listA
10570
     * @param array $listB
10571
     *
10572
     * @return int
10573
     */
10574
    private static function compareBySessionName($listA, $listB)
10575
    {
10576
        if ('' == $listB['catSessionName']) {
10577
            return -1;
10578
        } elseif ('' == $listA['catSessionName']) {
10579
            return 1;
10580
        } elseif ($listA['catSessionName'] == $listB['catSessionName']) {
10581
            return 0;
10582
        } elseif ($listA['catSessionName'] > $listB['catSessionName']) {
10583
            return 1;
10584
        } else {
10585
            return -1;
10586
        }
10587
    }
10588
10589
    /**
10590
     * @param array $listA
10591
     * @param array $listB
10592
     *
10593
     * @return int
10594
     */
10595
    private static function compareByUserCourseCat($listA, $listB)
10596
    {
10597
        if ($listA['courseInUserCategoryTitle'] == $listB['courseInUserCategoryTitle']) {
10598
            return 0;
10599
        } elseif ($listA['courseInUserCategoryTitle'] > $listB['courseInUserCategoryTitle']) {
10600
            return 1;
10601
        } else {
10602
            return -1;
10603
        }
10604
    }
10605
10606
    /**
10607
     * @param array $listA
10608
     * @param array $listB
10609
     *
10610
     * @return int
10611
     */
10612
    private static function compareByCourse($listA, $listB)
10613
    {
10614
        if ($listA['title'] == $listB['title']) {
10615
            return 0;
10616
        } elseif ($listA['title'] > $listB['title']) {
10617
            return 1;
10618
        } else {
10619
            return -1;
10620
        }
10621
    }
10622
10623
    public static function getGeneralCoachesIdForSession(int $sessionId): array
10624
    {
10625
        return api_get_session_entity($sessionId)
10626
            ->getGeneralCoaches()
10627
            ->map(fn(User $user) => $user->getId())
10628
            ->getValues();
10629
    }
10630
10631
    public static function getGeneralCoachesNamesForSession(int $sessionId): array
10632
    {
10633
        return api_get_session_entity($sessionId)
10634
            ->getGeneralCoaches()
10635
            ->map(fn(User $user) => $user->getFullName())
10636
            ->getValues();
10637
    }
10638
10639
    public static function sessionHasSessionAdmin(int $sessionId, int $userId): bool
10640
    {
10641
        $adminIds = api_get_session_entity($sessionId)
10642
            ->getSessionAdmins()
10643
            ->map(fn(User $user) => $user->getId())
10644
            ->getValues();
10645
10646
        return in_array($userId, $adminIds);
10647
    }
10648
10649
    /**
10650
     * Retrieves all user IDs associated with a session including coaches and students.
10651
     *
10652
     * @param int $sessionId The session ID.
10653
     * @return array An array of user IDs.
10654
     */
10655
    public static function getAllUserIdsInSession(int $sessionId): array
10656
    {
10657
        $users = [];
10658
        $session = api_get_session_entity($sessionId);
10659
        if ($session) {
10660
            $courses = $session->getCourses();
10661
            if (!empty($courses)) {
10662
                foreach ($courses as $sessionRelCourse) {
10663
                    $course = $sessionRelCourse->getCourse();
10664
                    $coachSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::COURSE_COACH);
10665
                    foreach ($coachSubscriptions as $coachSubscription) {
10666
                        $users[]['user_id'] = $coachSubscription->getUser()->getId();
10667
                    }
10668
10669
                    $userCourseSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::STUDENT);
10670
                    foreach ($userCourseSubscriptions as $courseSubscription) {
10671
                        $users[]['user_id'] = $courseSubscription->getUser()->getId();
10672
                    }
10673
10674
                }
10675
            }
10676
10677
            $generalCoachesId = self::getGeneralCoachesIdForSession($sessionId);
10678
            if (!empty($generalCoachesId)) {
10679
                foreach ($generalCoachesId as $generalCoachId) {
10680
                    $users[]['user_id'] = $generalCoachId;
10681
                }
10682
            }
10683
        }
10684
10685
        return $users;
10686
    }
10687
10688
    /**
10689
     * Retrieves a list of parent sessions.
10690
     */
10691
    public static function getListOfParentSessions(): array
10692
    {
10693
        $sessions = [];
10694
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
10695
        $sql = "SELECT id, title FROM $tbl_session ORDER BY title";
10696
        $result = Database::query($sql);
10697
10698
        while ($row = Database::fetch_array($result)) {
10699
            $sessions[$row['id']] = $row['title'];
10700
        }
10701
10702
        return $sessions;
10703
    }
10704
10705
10706
    /**
10707
     * Method to export sessions data as CSV
10708
     */
10709
    public static function exportSessionsAsCSV(array $selectedSessions): void
10710
    {
10711
        $csvData = [];
10712
        $headersGenerated = false;
10713
        $csvHeaders = [];
10714
10715
        foreach ($selectedSessions as $sessionId) {
10716
            $courses = SessionManager::get_course_list_by_session_id($sessionId);
10717
10718
            if (!empty($courses)) {
10719
                foreach ($courses as $course) {
10720
                    $courseCode = $course['course_code'];
10721
                    $courseId = $course['id'];
10722
                    $studentList = CourseManager::get_student_list_from_course_code(
10723
                        $courseCode,
10724
                        true,
10725
                        $sessionId
10726
                    );
10727
10728
                    $userIds = array_keys($studentList);
10729
10730
                    [$generatedHeaders, $csvContent] = self::generateSessionCourseReportData($sessionId, $courseId, $userIds);
10731
10732
                    if (!$headersGenerated) {
10733
                        $csvHeaders = $generatedHeaders;
10734
                        $headersGenerated = true;
10735
                    }
10736
10737
                    foreach ($csvContent as $row) {
10738
                        $csvData[] = $row;
10739
                    }
10740
                }
10741
            }
10742
        }
10743
10744
        if (!empty($csvData)) {
10745
            array_unshift($csvData, $csvHeaders);
10746
            $filename = 'export_session_courses_reports_complete_' . date('Y-m-d_H-i-s') . '.csv';
10747
            Export::arrayToCsvSimple($csvData, $filename);
10748
            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...
10749
        }
10750
    }
10751
10752
    /**
10753
     * Exports session data as a ZIP file with CSVs and sends it for download.
10754
     */
10755
    public static function exportSessionsAsZip(array $sessionList): void
10756
    {
10757
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH) . api_get_unique_id() . '.zip';
10758
        $tempDir = dirname($tempZipFile);
10759
10760
        if (!is_dir($tempDir) || !is_writable($tempDir)) {
10761
            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...
10762
        }
10763
10764
        $zip = new \ZipArchive();
10765
        if ($zip->open($tempZipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
10766
            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...
10767
        }
10768
10769
        foreach ($sessionList as $sessionItemId) {
10770
            $courses = SessionManager::get_course_list_by_session_id($sessionItemId);
10771
10772
            if (!empty($courses)) {
10773
                foreach ($courses as $course) {
10774
                    $courseCode = $course['course_code'];
10775
                    $courseId = $course['id'];
10776
                    $studentList = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionItemId);
10777
                    $userIds = array_keys($studentList);
10778
10779
                    [$csvHeaders, $csvContent] = self::generateSessionCourseReportData($sessionItemId, $courseId, $userIds);
10780
                    array_unshift($csvContent, $csvHeaders);
10781
10782
                    $sessionInfo = api_get_session_info($sessionItemId);
10783
                    $courseInfo = api_get_course_info_by_id($courseId);
10784
                    $csvFileName = $sessionInfo['name'] . '_' . $courseInfo['name'] . '.csv';
10785
10786
                    $csvFilePath = Export::arrayToCsvSimple($csvContent, $csvFileName, true);
10787
10788
                    if ($csvFilePath && file_exists($csvFilePath)) {
10789
                        $zip->addFile($csvFilePath, $csvFileName);
10790
                    }
10791
                }
10792
            }
10793
        }
10794
10795
        if (!$zip->close()) {
10796
            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...
10797
        }
10798
10799
        if (file_exists($tempZipFile)) {
10800
            DocumentManager::file_send_for_download($tempZipFile, true);
10801
            unlink($tempZipFile);
10802
        } else {
10803
            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...
10804
        }
10805
    }
10806
10807
    private static function generateSessionCourseReportData($sessionId, $courseId, $userIds): array
10808
    {
10809
        $em = Database::getManager();
10810
        $sessionRepository = $em->getRepository(Session::class);
10811
        $session = $sessionRepository->find($sessionId);
10812
10813
        if (!$session instanceof Session) {
10814
            throw new \InvalidArgumentException("Invalid session object for session ID $sessionId");
10815
        }
10816
10817
        $courseInfo = api_get_course_info_by_id($courseId);
10818
        $courseCode = $courseInfo['code'];
10819
10820
        $csvHeaders = [
10821
            get_lang('Session name'),
10822
            get_lang('Session access dates'),
10823
            get_lang('Session display dates'),
10824
            get_lang('Course name'),
10825
            get_lang('Official code'),
10826
            get_lang('First name'),
10827
            get_lang('Last name'),
10828
            get_lang('Login'),
10829
            get_lang('Time'),
10830
            get_lang('Course progress'),
10831
            get_lang('Exercise progress'),
10832
            get_lang('Exercise average'),
10833
            get_lang('Score'),
10834
            get_lang('Score') . ' - ' . get_lang('Best attempt'),
10835
            get_lang('Assignments'),
10836
            get_lang('Messages'),
10837
            get_lang('Classes'),
10838
            get_lang('Registration date'),
10839
            get_lang('First access to course'),
10840
            get_lang('Latest access in course'),
10841
        ];
10842
10843
        $csvData = TrackingCourseLog::getUserData(
10844
            null,
10845
            count($userIds),
10846
            null,
10847
            null,
10848
            [],
10849
            true,
10850
            true,
10851
            $courseCode,
10852
            $sessionId,
10853
            true,
10854
            $userIds
10855
        );
10856
10857
        $rawCsvContent = ChamiloSession::read('csv_content');
10858
10859
        if (empty($rawCsvContent)) {
10860
            throw new \RuntimeException("No CSV content found in session for course $courseCode and session $sessionId.");
10861
        }
10862
10863
        $csvContent = [];
10864
        foreach ($rawCsvContent as $row) {
10865
            $alignedRow = [
10866
                $row['session_name'] ?? '',
10867
                $row['session_startdate'] ?? '',
10868
                $row['session_enddate'] ?? '',
10869
                $row['course_name'] ?? '',
10870
                $row['official_code'] ?? '',
10871
                $row['firstname'] ?? '',
10872
                $row['lastname'] ?? '',
10873
                $row['username'] ?? '',
10874
                $row['time'] ?? '',
10875
                $row['average_progress'] ?? '',
10876
                $row['exercise_progress'] ?? '',
10877
                $row['exercise_average'] ?? '',
10878
                $row['student_score'] ?? '',
10879
                $row['student_score_best'] ?? '',
10880
                $row['count_assignments'] ?? '',
10881
                $row['count_messages'] ?? '',
10882
                $row['classes'] ?? '',
10883
                $row['registered_at'] ?? '',
10884
                $row['first_connection'] ?? '',
10885
                $row['last_connection'] ?? '',
10886
            ];
10887
            $csvContent[] = $alignedRow;
10888
        }
10889
10890
        return [$csvHeaders, $csvContent];
10891
    }
10892
}
10893