Passed
Push — master ( b0a3eb...ac7306 )
by
unknown
29:43 queued 19:52
created

SessionManager::get_users_by_session()   B

Complexity

Conditions 9

Size

Total Lines 60
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 32
nop 4
dl 0
loc 60
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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