Passed
Pull Request — master (#5831)
by
unknown
10:22
created

SessionManager::addFlashSessionReadOnly()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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