SessionManager::get_sessions_by_user()   A
last analyzed

Complexity

Conditions 5

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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