Passed
Pull Request — master (#5831)
by
unknown
47:54 queued 24:36
created

SessionManager::get_session_by_course()   A

Complexity

Conditions 2

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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