Passed
Pull Request — master (#5831)
by
unknown
07:44
created

SessionManager::addFlashSessionReadOnly()   A

Complexity

Conditions 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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