SessionManager::subscribeSessionsToDrh()   C
last analyzed

Complexity

Conditions 12

Size

Total Lines 74
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 42
nop 4
dl 0
loc 74
rs 6.9666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Asset;
6
use Chamilo\CoreBundle\Entity\Course;
7
use Chamilo\CoreBundle\Entity\ExtraField;
8
use Chamilo\CoreBundle\Entity\SequenceResource;
9
use Chamilo\CoreBundle\Entity\Session;
10
use Chamilo\CoreBundle\Entity\SessionCategory;
11
use Chamilo\CoreBundle\Entity\SessionRelCourse;
12
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
13
use Chamilo\CoreBundle\Entity\SessionRelUser;
14
use Chamilo\CoreBundle\Entity\User;
15
use Chamilo\CoreBundle\Entity\UserAuthSource;
16
use Chamilo\CoreBundle\Enums\ObjectIcon;
17
use Chamilo\CoreBundle\Enums\StateIcon;
18
use Chamilo\CoreBundle\Framework\Container;
19
use Chamilo\CourseBundle\Entity\CStudentPublication;
20
use Chamilo\CourseBundle\Entity\CSurvey;
21
use ExtraField as ExtraFieldModel;
22
use Monolog\Logger;
23
24
/**
25
 * This is the session library for Chamilo
26
 * (as in courses>session, not as in PHP session)
27
 * All main sessions functions should be placed here.
28
 * This class provides methods for sessions management.
29
 * Include/require it in your code to use its features.
30
 */
31
class SessionManager
32
{
33
    public const STATUS_PLANNED = 1;
34
    public const STATUS_PROGRESS = 2;
35
    public const STATUS_FINISHED = 3;
36
    public const STATUS_CANCELLED = 4;
37
    // See BT#4871
38
    public const SESSION_CHANGE_USER_REASON_SCHEDULE = 1;
39
    public const SESSION_CHANGE_USER_REASON_CLASSROOM = 2;
40
    public const SESSION_CHANGE_USER_REASON_LOCATION = 3;
41
    public const SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION = 4;
42
    public const DEFAULT_VISIBILITY = 4;  //SESSION_AVAILABLE
43
44
    public function __construct()
45
    {
46
    }
47
48
    /**
49
     * Fetches a session from the database.
50
     *
51
     * @param int $id Session Id
52
     *
53
     * @return array Session details
54
     */
55
    public static function fetch($id)
56
    {
57
        if (empty($id)) {
58
            return [];
59
        }
60
61
        $session = api_get_session_entity($id);
62
63
        if (!$session) {
64
            return [];
65
        }
66
67
        $result = [
68
            'id' => $session->getId(),
69
            'session_category_id' => $session->getCategory() ? $session->getCategory()->getId() : null,
70
            'name' => $session->getTitle(), // only provided for backwards compatibility - should be removed in the long run
71
            'title' => $session->getTitle(),
72
            'description' => $session->getDescription(),
73
            'show_description' => $session->getShowDescription(),
74
            'duration' => $session->getDuration(),
75
            'nbr_courses' => $session->getNbrCourses(),
76
            'nbr_users' => $session->getNbrUsers(),
77
            'nbr_classes' => $session->getNbrClasses(),
78
            'visibility' => $session->getVisibility(),
79
            'promotion_id' => $session->getPromotion() ? $session->getPromotion()->getId() : 0,
80
            'display_start_date' => $session->getDisplayStartDate()?->format('Y-m-d H:i:s'),
81
            'display_end_date' => $session->getDisplayEndDate()?->format('Y-m-d H:i:s'),
82
            'access_start_date' => $session->getAccessStartDate()?->format('Y-m-d H:i:s'),
83
            'access_end_date' => $session->getAccessEndDate()?->format('Y-m-d H:i:s'),
84
            'coach_access_start_date' => $session->getCoachAccessStartDate()?->format('Y-m-d H:i:s'),
85
            'coach_access_end_date' => $session->getCoachAccessEndDate()?->format('Y-m-d H:i:s'),
86
            'send_subscription_notification' => $session->getSendSubscriptionNotification(),
87
            'status' => $session->getStatus(),
88
            'status_label' => self::getStatusLabel($session->getStatus()),
89
        ];
90
91
        // Converted to local values
92
        $variables = [
93
            'display_start_date',
94
            'display_end_date',
95
            'access_start_date',
96
            'access_end_date',
97
            'coach_access_start_date',
98
            'coach_access_end_date',
99
        ];
100
101
        foreach ($variables as $value) {
102
            $result[$value.'_to_local_time'] = null;
103
            if (!empty($result[$value])) {
104
                $result[$value.'_to_local_time'] = api_get_local_time($result[$value]);
105
            }
106
        }
107
108
        return $result;
109
    }
110
111
    /**
112
     * Create a session.
113
     *
114
     * @author Carlos Vargas <[email protected]>, from existing code
115
     *
116
     * @param string $name
117
     * @param string $startDate                    (YYYY-MM-DD hh:mm:ss)
118
     * @param string $endDate                      (YYYY-MM-DD hh:mm:ss)
119
     * @param string $displayStartDate             (YYYY-MM-DD hh:mm:ss)
120
     * @param string $displayEndDate               (YYYY-MM-DD hh:mm:ss)
121
     * @param string $coachStartDate               (YYYY-MM-DD hh:mm:ss)
122
     * @param string $coachEndDate                 (YYYY-MM-DD hh:mm:ss)
123
     * @param array  $coachesId                      If int, this is the session coach id,
124
     *                                             if string, the coach ID will be looked for from the user table
125
     * @param int    $sessionCategoryId            ID of the session category in which this session is registered
126
     * @param int    $visibility                   Visibility after end date (0 = read-only, 1 = invisible, 2 = accessible)
127
     * @param bool   $fixSessionNameIfExists
128
     * @param string $duration
129
     * @param string $description                  Optional. The session description
130
     * @param int    $showDescription              Optional. Whether show the session description
131
     * @param array  $extraFields
132
     * @param int    $sessionAdminId               Optional. If this sessions was created by a session admin, assign it to him
133
     * @param bool   $sendSubscriptionNotification Optional.
134
     *                                             Whether send a mail notification to users being subscribed
135
     * @param int    $accessUrlId                  Optional.
136
     * @param int    $status
137
     *
138
     * @return mixed Session ID on success, error message otherwise
139
     *
140
     * @todo use an array to replace all this parameters or use the model.lib.php ...
141
     */
142
    public static function create_session(
143
        $name,
144
        $startDate,
145
        $endDate,
146
        $displayStartDate,
147
        $displayEndDate,
148
        $coachStartDate,
149
        $coachEndDate,
150
        array $coachesId,
151
        $sessionCategoryId,
152
        $visibility = 1,
153
        $fixSessionNameIfExists = false,
154
        $duration = null,
155
        $description = null,
156
        $showDescription = 0,
157
        $extraFields = [],
158
        $sessionAdminId = 0,
159
        $sendSubscriptionNotification = false,
160
        $accessUrlId = 0,
161
        $status = 0,
162
        $notifyBoss = false,
163
        $parentId = null,
164
        $daysBeforeFinishingForReinscription = null,
165
        $lastRepetition = false,
166
        $daysBeforeFinishingToCreateNewRepetition = null,
167
        $validityInDays = null
168
    ) {
169
        global $_configuration;
170
171
        // Check portal limits
172
        $accessUrlId = api_is_multiple_url_enabled()
173
            ? (empty($accessUrlId) ? api_get_current_access_url_id() : (int) $accessUrlId)
174
            : 1;
175
176
        $hostingLimitSessions = get_hosting_limit($accessUrlId, 'sessions');
177
178
        if ($hostingLimitSessions !== null && $hostingLimitSessions > 0) {
179
            $num = self::count_sessions();
180
            if ($num >= $hostingLimitSessions) {
181
                api_warn_hosting_contact('hosting_limit_sessions');
182
183
                return get_lang('The number of sessions limit for this portal has been reached');
184
            }
185
        }
186
187
        $name = trim($name);
188
        $sessionCategoryId = (int) $sessionCategoryId;
189
        $visibility = (int) $visibility;
190
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
191
192
        if (empty($name)) {
193
            return get_lang('A title is required');
194
        } elseif (!empty($startDate) && !api_is_valid_date($startDate, 'Y-m-d H:i') &&
195
            !api_is_valid_date($startDate, 'Y-m-d H:i:s')
196
        ) {
197
            return get_lang('Invalid start date was given.');
198
        } elseif (!empty($endDate) && !api_is_valid_date($endDate, 'Y-m-d H:i') &&
199
            !api_is_valid_date($endDate, 'Y-m-d H:i:s')
200
        ) {
201
            return get_lang('Invalid end date was given.');
202
        } elseif (!empty($startDate) && !empty($endDate) && $startDate >= $endDate) {
203
            return get_lang('The first date should be before the end date');
204
        } else {
205
            $ready_to_create = false;
206
            if ($fixSessionNameIfExists) {
207
                $name = self::generateNextSessionName($name);
208
                if ($name) {
209
                    $ready_to_create = true;
210
                } else {
211
                    return get_lang('Session title already exists');
212
                }
213
            } else {
214
                $sessionRepo = Database::getManager()->getRepository(Session::class);
215
                $existingSession = $sessionRepo->findOneBy(['title' => $name]);
216
                if ($existingSession !== null) {
217
                    return get_lang('Session title already exists');
218
                }
219
                $ready_to_create = true;
220
            }
221
222
            if ($ready_to_create) {
223
                $session = new Session();
224
                $session
225
                    ->setTitle($name)
226
                    ->setVisibility($visibility)
227
                    ->setDescription($description)
228
                    ->setShowDescription(1 === $showDescription)
229
                    ->setSendSubscriptionNotification((bool) $sendSubscriptionNotification)
230
                    ->setNotifyBoss((bool) $notifyBoss)
231
                    ->setParentId($parentId)
232
                    ->setDaysToReinscription((int) $daysBeforeFinishingForReinscription)
233
                    ->setLastRepetition($lastRepetition)
234
                    ->setDaysToNewRepetition((int) $daysBeforeFinishingToCreateNewRepetition)
235
                    ->setValidityInDays((int) $validityInDays)
236
                    ->setStatus($status)
237
                ;
238
239
                if (!empty($duration)) {
240
                    $session->setDuration((int) $duration);
241
                } else {
242
                    $startDate = $startDate ? api_get_utc_datetime($startDate, true, true) : null;
243
                    $endDate = $endDate ? api_get_utc_datetime($endDate, true, true) : null;
244
                    $displayStartDate = $displayStartDate ? api_get_utc_datetime($displayStartDate, true, true) : null;
245
                    $displayEndDate = $displayEndDate ? api_get_utc_datetime($displayEndDate, true, true) : null;
246
                    $coachStartDate = $coachStartDate ? api_get_utc_datetime($coachStartDate, true, true) : null;
247
                    $coachEndDate = $coachEndDate ? api_get_utc_datetime($coachEndDate, true, true) : null;
248
249
                    $session->setAccessStartDate($startDate);
250
                    $session->setAccessEndDate($endDate);
251
                    $session->setDisplayStartDate($displayStartDate);
252
                    $session->setDisplayEndDate($displayEndDate);
253
                    $session->setCoachAccessStartDate($coachStartDate);
254
                    $session->setCoachAccessEndDate($coachEndDate);
255
                }
256
257
                foreach ($coachesId as $coachId) {
258
                    $session->addGeneralCoach(api_get_user_entity($coachId));
259
                }
260
261
                $sessionAdminId = !empty($sessionAdminId) ? $sessionAdminId : api_get_user_id();
262
263
                $session->addSessionAdmin(api_get_user_entity($sessionAdminId));
264
265
                $em = Database::getManager();
266
                $em->persist($session);
267
                $em->flush();
268
                $session_id = $session->getId();
269
270
                if (!empty($session_id)) {
271
                    $extraFields['item_id'] = $session_id;
272
                    $sessionFieldValue = new ExtraFieldValue('session');
273
                    $sessionFieldValue->saveFieldValues($extraFields);
274
275
                    // add event to system log
276
                    $user_id = api_get_user_id();
277
                    Event::addEvent(
278
                        LOG_SESSION_CREATE,
279
                        LOG_SESSION_ID,
280
                        $session_id,
281
                        api_get_utc_datetime(),
282
                        $user_id
283
                    );
284
                }
285
286
                return $session_id;
287
            }
288
        }
289
    }
290
291
    /**
292
     * @param string $name
293
     *
294
     * @return bool
295
     */
296
    public static function sessionNameExists($name)
297
    {
298
        $name = Database::escape_string($name);
299
        $sql = "SELECT COUNT(*) as count FROM ".Database::get_main_table(TABLE_MAIN_SESSION)."
300
                WHERE title = '$name'";
301
        $result = Database::fetch_array(Database::query($sql));
302
303
        return $result['count'] > 0;
304
    }
305
306
    /**
307
     * @param string $where_condition
308
     *
309
     * @return mixed
310
     */
311
    public static function get_count_admin($where_condition = '')
312
    {
313
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
314
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
315
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
316
        $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
317
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
318
319
        $where = 'WHERE 1=1 ';
320
        $user_id = api_get_user_id();
321
        $extraJoin = '';
322
323
        if (api_is_session_admin() &&
324
            'false' == api_get_setting('allow_session_admins_to_manage_all_sessions')
325
        ) {
326
            $where .= " AND (
327
                            sru.user_id = '$user_id' AND
328
                            sru.relation_type IN ('".Session::DRH.", ".Session::SESSION_ADMIN."')
329
                            )
330
                      ";
331
332
            $extraJoin = " INNER JOIN $tbl_session_rel_user sru
333
                           ON sru.session_id = s.id ";
334
        }
335
336
        $today = api_get_utc_datetime();
337
        $today = api_strtotime($today, 'UTC');
338
        $today = date('Y-m-d', $today);
339
340
        if (!empty($where_condition)) {
341
            $where_condition = str_replace("(  session_active = ':'  )", '1=1', $where_condition);
342
343
            $where_condition = str_replace('category_name', 'sc.title', $where_condition);
344
            $where_condition = str_replace(
345
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
346
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
347
                $where_condition
348
            );
349
            $where_condition = str_replace(
350
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
351
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
352
                $where_condition
353
            );
354
        } else {
355
            $where_condition = " AND 1 = 1";
356
        }
357
358
        $courseCondition = null;
359
        if (strpos($where_condition, 'c.id')) {
360
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
361
            $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
362
            $courseCondition = " INNER JOIN $table course_rel_session
363
                                 ON (s.id = course_rel_session.session_id)
364
                                 INNER JOIN $tableCourse c
365
                                 ON (course_rel_session.c_id = c.id)
366
                                ";
367
        }
368
369
        $sql = "SELECT COUNT(id) as total_rows FROM (
370
                SELECT DISTINCT
371
                 IF (
372
					(s.access_start_date <= '$today' AND '$today' <= s.access_end_date) OR
373
                    (s.access_start_date IS NULL AND s.access_end_date IS NULL ) OR
374
					(s.access_start_date <= '$today' AND s.access_end_date IS NULL) OR
375
					('$today' <= s.access_end_date AND s.access_start_date IS NULL)
376
				, 1, 0) as session_active,
377
                s.id
378
                FROM $tbl_session s
379
                LEFT JOIN $tbl_session_category sc
380
                ON s.session_category_id = sc.id
381
                INNER JOIN $tbl_user u
382
                ON s.id_coach = u.id
383
                $courseCondition
384
                $extraJoin
385
                $where $where_condition ) as session_table";
386
387
        if (api_is_multiple_url_enabled()) {
388
            $access_url_id = api_get_current_access_url_id();
389
            if (-1 != $access_url_id) {
390
                $where .= " AND ar.access_url_id = $access_url_id ";
391
392
                $sql = "SELECT count(id) as total_rows FROM (
393
                SELECT DISTINCT
394
                  IF (
395
					(s.access_start_date <= '$today' AND '$today' <= s.access_end_date) OR
396
                    (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
397
					(s.access_start_date <= '$today' AND s.access_end_date IS NULL) OR
398
					('$today' <= s.access_end_date AND s.access_start_date IS NULL)
399
				, 1, 0)
400
				as session_active,
401
				s.id
402
                FROM $tbl_session s
403
                    LEFT JOIN  $tbl_session_category sc
404
                    ON s.session_category_id = sc.id
405
                    INNER JOIN $tbl_user u ON s.id_coach = u.id
406
                    INNER JOIN $table_access_url_rel_session ar
407
                    ON ar.session_id = s.id
408
                    $courseCondition
409
                    $extraJoin
410
                $where $where_condition) as session_table";
411
            }
412
        }
413
414
        $sql .= !str_contains($sql, 'WHERE') ? ' WHERE u.active <> '.USER_SOFT_DELETED : ' AND u.active <> '.USER_SOFT_DELETED;
415
416
        $result_rows = Database::query($sql);
417
        $row = Database::fetch_array($result_rows);
418
        $num = $row['total_rows'];
419
420
        return $num;
421
    }
422
423
    /**
424
     * Get session list for a session admin or platform admin.
425
     *
426
     * @param int   $userId   User Id for the session admin.
427
     * @param array $options  Order and limit keys.
428
     * @param bool  $getCount Whether to get all the results or only the count.
429
     * @param array $columns  Columns from jqGrid.
430
     * @param string $listType
431
     * @param array $extraFieldsToLoad
432
     * @param bool  $formatted
433
     *
434
     * @return array
435
     */
436
    public static function getSessionsForAdmin(
437
        $userId,
438
        $options = [],
439
        $getCount = false,
440
        $columns = [],
441
        $listType = 'all',
442
        $extraFieldsToLoad = [],
443
        $formatted = false,
444
        $language = ''
445
    ) {
446
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
447
        $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
448
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
449
450
        $where = 'WHERE 1 = 1 ';
451
452
        $userId = (int) $userId;
453
454
        $extraFieldModel = new ExtraFieldModel('session');
455
        $conditions = $extraFieldModel->parseConditions($options);
456
457
        $sqlInjectJoins = $conditions['inject_joins'];
458
        $where .= $conditions['where'];
459
        $sqlInjectWhere = $conditions['inject_where'];
460
        $injectExtraFields = $conditions['inject_extra_fields'];
461
        $order = empty($conditions['order']) ? ' ORDER BY s.title ASC' : $conditions['order'];
462
        $limit = $conditions['limit'];
463
464
        $isMakingOrder = false;
465
        $showCountUsers = false;
466
467
        if (true === $getCount) {
468
            $select = ' SELECT count(DISTINCT s.id) as total_rows ';
469
        } else {
470
            if (!empty($columns['column_model'])) {
471
                foreach ($columns['column_model'] as $column) {
472
                    if ('users' == $column['name']) {
473
                        $showCountUsers = true;
474
                        break;
475
                    }
476
                }
477
            }
478
479
            $select =
480
                "SELECT DISTINCT
481
                     s.title,
482
                     s.display_start_date,
483
                     s.display_end_date,
484
                     access_start_date,
485
                     access_end_date,
486
                     s.visibility,
487
                     s.session_category_id,
488
                     s.id
489
             ";
490
491
            // ofaj fix
492
            if (!empty($extraFieldsToLoad)) {
493
                $select = "SELECT DISTINCT s.* ";
494
            }
495
            $select .= ', status';
496
497
            if ('replication' === $listType) {
498
                $select .= ', parent_id';
499
            }
500
501
            if (isset($options['order'])) {
502
                $isMakingOrder = 0 === strpos($options['order'], 'category_name');
503
            }
504
        }
505
506
        $isFilteringSessionCategory = false !== strpos($where, 'category_name');
507
        $isFilteringSessionCategoryWithName = false !== strpos($where, 'sc.title');
508
509
        if ($isMakingOrder || $isFilteringSessionCategory || $isFilteringSessionCategoryWithName) {
510
            $sqlInjectJoins .= " LEFT JOIN $sessionCategoryTable sc ON s.session_category_id = sc.id ";
511
512
            if ($isFilteringSessionCategory) {
513
                $where = str_replace('category_name', 'sc.title', $where);
514
            }
515
516
            if ($isMakingOrder) {
517
                $order = str_replace('category_name', 'sc.title', $order);
518
            }
519
        }
520
521
        if (!empty($language)) {
522
            $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
523
            $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
524
            $sqlInjectJoins .= " INNER JOIN $table sc ON (sc.session_id = s.id)
525
                               INNER JOIN $tableCourse c ON (sc.c_id = c.id)";
526
            $language = Database::escape_string($language);
527
528
            // Get the isoCode to filter course_language
529
            $isoCode = '';
530
            $languageId = api_get_language_id($language);
531
            if (!empty($languageId)) {
532
                $languageInfo = api_get_language_info($languageId);
533
                $isoCode = $languageInfo['isocode'];
534
            }
535
            if ('true' === api_get_setting('language.allow_course_multiple_languages')) {
536
                $tblExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
537
                $tblExtraFieldValue = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
538
                $extraFieldType = ExtraField::COURSE_FIELD_TYPE;
539
                $sql = "SELECT id FROM $tblExtraField WHERE item_type = $extraFieldType AND variable = 'multiple_language'";
540
                $rs = Database::query($sql);
541
                if (Database::num_rows($rs) > 0) {
542
                    $fieldId = Database::result($rs, 0, 0);
543
                    $sqlInjectJoins .= " LEFT JOIN $tblExtraFieldValue cfv ON (c.id = cfv.item_id AND cfv.field_id = $fieldId)";
544
                    $where .= " AND (c.course_language = '$isoCode' OR cfv.field_value LIKE '%$language%')";
545
                } else {
546
                    $where .= " AND c.course_language = '$isoCode' ";
547
                }
548
            } else {
549
                $where .= " AND c.course_language = '$isoCode' ";
550
            }
551
        }
552
553
        $allowSessionAdminsToManageAllSessions = !api_is_platform_admin()
554
            && api_is_session_admin()
555
            && 'false' === api_get_setting('allow_session_admins_to_manage_all_sessions');
556
557
        $allowTeachersToCreateSessions = !api_is_platform_admin()
558
            && api_is_teacher()
559
            && 'true' === api_get_setting('allow_teachers_to_create_sessions');
560
561
        if ($allowSessionAdminsToManageAllSessions || $allowTeachersToCreateSessions) {
562
            $sqlInjectJoins .= " INNER JOIN $tblSessionRelUser sru ON sru.session_id = s.id ";
563
564
            $relationTypeList = [];
565
566
            if ($allowSessionAdminsToManageAllSessions) {
567
                $relationTypeList[] = Session::SESSION_ADMIN;
568
            }
569
570
            if ($allowTeachersToCreateSessions) {
571
                $relationTypeList[] = Session::GENERAL_COACH;
572
            }
573
574
            $where .= " AND (sru.user_id = $userId AND sru.relation_type IN(".implode(',', $relationTypeList)."))";
575
        }
576
577
        $query = "$select";
578
        if (!empty($injectExtraFields)) {
579
            $injectExtraFields = rtrim(trim($injectExtraFields), ',');
580
            $query .= ", $injectExtraFields";
581
        }
582
        $query .= " FROM $tblSession s $sqlInjectJoins $where $sqlInjectWhere";
583
584
        if (api_is_multiple_url_enabled()) {
585
            $tblAccessUrlRelSession = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
586
            $accessUrlId = api_get_current_access_url_id();
587
588
            if (-1 != $accessUrlId) {
589
                $where .= " AND ar.access_url_id = $accessUrlId ";
590
                $query = "$select
591
                    FROM $tblSession s $sqlInjectJoins
592
                    INNER JOIN $tblAccessUrlRelSession ar
593
                    ON (ar.session_id = s.id) $where";
594
            }
595
        }
596
597
        $date = api_get_utc_datetime();
598
599
        switch ($listType) {
600
            case 'all':
601
                break;
602
            case 'active':
603
                $query .= "AND (
604
                    (s.access_end_date IS NULL)
605
                    OR
606
                    (
607
                    s.access_start_date IS NOT NULL AND
608
                    s.access_end_date IS NOT NULL AND
609
                    s.access_start_date <= '$date' AND s.access_end_date >= '$date')
610
                    OR
611
                    (
612
                        s.access_start_date IS NULL AND
613
                        s.access_end_date IS NOT NULL AND
614
                        s.access_end_date >= '$date'
615
                    )
616
                )";
617
                break;
618
            case 'close':
619
                $query .= "AND (
620
                    (
621
                    s.access_start_date IS NOT NULL AND
622
                    s.access_end_date IS NOT NULL AND
623
                    s.access_start_date <= '$date' AND s.access_end_date <= '$date')
624
                    OR
625
                    (
626
                        s.access_start_date IS NULL AND
627
                        s.access_end_date IS NOT NULL AND
628
                        s.access_end_date <= '$date'
629
                    )
630
                )";
631
                break;
632
            case 'replication':
633
                $formatted = false;
634
                $query .= "AND s.days_to_new_repetition IS NOT NULL
635
               AND (SELECT COUNT(id) FROM session AS child WHERE child.parent_id = s.id) <= 1";
636
                break;
637
        }
638
639
        $query .= $order;
640
        $query .= $limit;
641
        if (!$formatted) {
642
            $result = Database::query($query);
643
            $sessions = Database::store_result($result, 'ASSOC');
644
            if ($showCountUsers && !$getCount) {
645
                foreach ($sessions as &$session) {
646
                    $result = Database::query("SELECT COUNT(session_id) AS nbr
647
                    FROM session_rel_user WHERE session_id = {$session['id']} AND relation_type = ".Session::STUDENT);
648
                    $session['users'] = Database::fetch_assoc($result)['nbr'];
649
                }
650
            }
651
652
            if ('replication' === $listType) {
653
                $formattedSessions = [];
654
                foreach ($sessions as $session) {
655
                    $formattedSessions[] = $session;
656
                    if (isset($session['id'])) {
657
                        $childSessions = array_filter($sessions, fn($s) => isset($s['parent_id']) && $s['parent_id'] === $session['id']);
658
                        foreach ($childSessions as $childSession) {
659
                            $childSession['title'] = '-- ' . $childSession['title'];
660
                            $formattedSessions[] = $childSession;
661
                        }
662
                    }
663
                }
664
665
                return $formattedSessions;
666
            }
667
668
            if ('all' === $listType) {
669
                if ($getCount) {
670
                    return $sessions[0]['total_rows'];
671
                }
672
                return $sessions;
673
            }
674
            return $sessions;
675
        }
676
677
        // For search diagnosis format (Ofaj)
678
        $categories = self::get_all_session_category();
679
        $orderedCategories = [];
680
        if (!empty($categories)) {
681
            foreach ($categories as $category) {
682
                $orderedCategories[$category['id']] = $category['title'];
683
            }
684
        }
685
        $result = Database::query($query);
686
        $formattedSessions = [];
687
        if (Database::num_rows($result)) {
688
            $sessions = Database::store_result($result, 'ASSOC');
689
            if ($getCount) {
690
                return $sessions[0]['total_rows'];
691
            }
692
693
            $activeIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
694
            $inactiveIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
695
696
            foreach ($sessions as $session) {
697
                $session_id = $session['id'];
698
                if ($showCountUsers) {
699
                    $session['users'] = self::get_users_by_session(
700
                        $session['id'],
701
                        0,
702
                        true
703
                    );
704
                    $usersLang = self::getCountUsersLangBySession($session['id'], api_get_current_access_url_id(), Session::STUDENT);
705
                    $tooltipUserLangs = '';
706
                    if (!empty($usersLang)) {
707
                        $tooltipUserLangs = implode(' | ', $usersLang);
708
                    }
709
                    $session['users'] = '<a href="#" title="'.$tooltipUserLangs.'">'.$session['users'].'</a>';
710
                    $courses = self::getCoursesInSession($session_id);
711
                    $teachers = '';
712
                    foreach ($courses as $courseId) {
713
                        $courseInfo = api_get_course_info_by_id($courseId);
714
715
                        // Ofaj
716
                        $teachers = CourseManager::get_coachs_from_course_to_string($session_id, $courseInfo['real_id']);
717
                    }
718
                    // ofaj
719
                    $session['teachers'] = '';
720
                    if (!empty($teachers)) {
721
                        $session['teachers'] = Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_SMALL, addslashes($teachers));
722
                    }
723
                }
724
                $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
725
                if (api_is_drh()) {
726
                    $url = api_get_path(WEB_CODE_PATH).'session/about.php?session_id='.$session['id'];
727
                }
728
                if (api_is_platform_admin()) {
729
                    $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
730
                }
731
732
                if ($extraFieldsToLoad) {
733
                    $url = api_get_path(WEB_CODE_PATH).'session/about.php?session_id='.$session['id'];
734
                }
735
                $session['title'] = Display::url($session['title'], $url);
736
737
                if (isset($session['session_active']) && $session['session_active'] == 1) {
738
                    $session['session_active'] = $activeIcon;
739
                } else {
740
                    $session['session_active'] = $inactiveIcon;
741
                }
742
743
                $session = self::convert_dates_to_local($session, true);
744
745
                switch ($session['visibility']) {
746
                    case SESSION_VISIBLE_READ_ONLY: //1
747
                        $session['visibility'] = get_lang('Read only');
748
                        break;
749
                    case SESSION_VISIBLE:           //2
750
                    case SESSION_AVAILABLE:         //4
751
                        $session['visibility'] = get_lang('Visible');
752
                        break;
753
                    case SESSION_INVISIBLE:         //3
754
                        $session['visibility'] = api_ucfirst(get_lang('Invisible'));
755
                        break;
756
                }
757
758
                if (!empty($extraFieldsToLoad)) {
759
                    foreach ($extraFieldsToLoad as $field) {
760
                        $extraFieldValue = new ExtraFieldValue('session');
761
                        $fieldData = $extraFieldValue->getAllValuesByItemAndField(
762
                            $session['id'],
763
                            $field['id']
764
                        );
765
                        $fieldDataArray = [];
766
                        $fieldDataToString = '';
767
                        if (!empty($fieldData)) {
768
                            foreach ($fieldData as $data) {
769
                                $fieldDataArray[] = $data['field_value'];
770
                            }
771
                            $fieldDataToString = implode(', ', $fieldDataArray);
772
                        }
773
                        $session[$field['variable']] = $fieldDataToString;
774
                    }
775
                }
776
777
                $categoryName = $orderedCategories[$session['session_category_id']] ?? '';
778
                $session['category_name'] = $categoryName;
779
                if (isset($session['status'])) {
780
                    $session['status'] = self::getStatusLabel($session['status']);
781
                }
782
783
                $formattedSessions[] = $session;
784
            }
785
        }
786
787
        return $formattedSessions;
788
    }
789
790
    /**
791
     * Get the count of users by language and session
792
     *
793
     * @param $sid
794
     * @param int $urlId
795
     * @param null $status
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $status is correct as it would always require null to be passed?
Loading history...
796
     *
797
     * @return array A list of ISO lang of users registered in the session , ex: FR 6
798
     */
799
    public static function getCountUsersLangBySession(
800
        $sid,
801
        $urlId = 0,
802
        $status = null
803
    ): array
804
    {
805
        $sid = (int) $sid;
806
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
807
808
        $tblUser = Database::get_main_table(TABLE_MAIN_USER);
809
        $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
810
        $tableAccessUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
811
        $tableLanguage = Database::get_main_table(TABLE_MAIN_LANGUAGE);
812
813
        $sql = "SELECT l.isocode, count(u.id) as cLang
814
                FROM $tblSessionUser su
815
                INNER JOIN $tblUser u ON (u.id = su.user_id)
816
                INNER JOIN $tableLanguage l ON (l.isocode = u.locale)
817
                LEFT OUTER JOIN $tableAccessUrlUser au ON (au.user_id = u.id)
818
                ";
819
820
        if (is_numeric($status)) {
821
            $status = (int) $status;
822
            $sql .= " WHERE su.relation_type = $status AND (au.access_url_id = $urlId OR au.access_url_id is null)";
823
        } else {
824
            $sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
825
        }
826
        $sql .= " AND su.session_id = $sid GROUP BY l.isocode";
827
828
        $rs = Database::query($sql);
829
        $usersLang = [];
830
        if (Database::num_rows($rs) > 0) {
831
            while ($row = Database::fetch_assoc($rs)) {
832
                $usersLang[] = strtoupper($row['isocode'])." ".$row['cLang'];
833
            }
834
        }
835
836
        return $usersLang;
837
    }
838
839
    /**
840
     * Gets the admin session list callback of the session/session_list.php page.
841
     *
842
     * @param array  $options           order and limit keys
843
     * @param bool   $getCount          Whether to get all the results or only the count
844
     * @param array  $columns
845
     * @param array  $extraFieldsToLoad
846
     * @param string $listType
847
     *
848
     * @return mixed Integer for number of rows, or array of results
849
     * @assert ([],true) !== false
850
     */
851
    public static function formatSessionsAdminForGrid(
852
        $options = [],
853
        $getCount = false,
854
        $columns = [],
855
        $extraFieldsToLoad = [],
856
        $listType = 'all'
857
    ) {
858
        $showCountUsers = false;
859
        if (!$getCount && !empty($columns['column_model'])) {
860
            foreach ($columns['column_model'] as $column) {
861
                if ('users' === $column['name']) {
862
                    $showCountUsers = true;
863
                }
864
            }
865
        }
866
867
        $userId = api_get_user_id();
868
        $sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns, $listType, $extraFieldsToLoad);
869
        if ($getCount) {
870
            return (int) $sessions;
871
        }
872
873
        $formattedSessions = [];
874
        $categories = self::get_all_session_category();
875
        $orderedCategories = [];
876
        if (!empty($categories)) {
877
            foreach ($categories as $category) {
878
                $orderedCategories[$category['id']] = $category['title'];
879
            }
880
        }
881
882
        $activeIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
883
        $inactiveIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
884
885
        foreach ($sessions as $session) {
886
            if ($showCountUsers) {
887
                $session['users'] = self::get_users_by_session($session['id'], 0, true);
888
                $usersLang = self::getCountUsersLangBySession($session['id'], api_get_current_access_url_id(), Session::STUDENT);
889
                $tooltipUserLangs = '';
890
                if (!empty($usersLang)) {
891
                    $tooltipUserLangs = implode(' | ', $usersLang);
892
                }
893
                $session['users'] = '<a href="#" title="'.$tooltipUserLangs.'">'.$session['users'].'</a>';
894
                $courses = self::getCoursesInSession($session['id']);
895
                $teachers = '';
896
                foreach ($courses as $courseId) {
897
                    $courseInfo = api_get_course_info_by_id($courseId);
898
899
                    // Ofaj
900
                    $teachers = CourseManager::get_coachs_from_course_to_string($session['id'], $courseInfo['real_id']);
901
                }
902
                // ofaj
903
                $session['teachers'] = '';
904
                if (!empty($teachers)) {
905
                    $session['teachers'] = Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_SMALL, addslashes($teachers));
906
                }
907
            }
908
            $url = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session['id'];
909
            if ($extraFieldsToLoad || api_is_drh()) {
910
                $url = api_get_path(WEB_PATH).'sessions/'.$session['id'].'/about/';
911
            }
912
913
            $session['title'] = Display::url($session['title'], $url);
914
915
            if (!empty($extraFieldsToLoad)) {
916
                foreach ($extraFieldsToLoad as $field) {
917
                    $extraFieldValue = new ExtraFieldValue('session');
918
                    $fieldData = $extraFieldValue->getAllValuesByItemAndField(
919
                        $session['id'],
920
                        $field['id']
921
                    );
922
                    $fieldDataArray = [];
923
                    $fieldDataToString = '';
924
                    if (!empty($fieldData)) {
925
                        foreach ($fieldData as $data) {
926
                            $fieldDataArray[] = $data['field_value'];
927
                        }
928
                        $fieldDataToString = implode(', ', $fieldDataArray);
929
                    }
930
                    $session[$field['variable']] = $fieldDataToString;
931
                }
932
            }
933
934
            if (isset($session['session_active']) && 1 == $session['session_active']) {
935
                $session['session_active'] = $activeIcon;
936
            } else {
937
                $session['session_active'] = $inactiveIcon;
938
            }
939
940
            $session = self::convert_dates_to_local($session, true);
941
942
            switch ($session['visibility']) {
943
                case SESSION_VISIBLE_READ_ONLY: //1
944
                    $session['visibility'] = get_lang('Read only');
945
                    break;
946
                case SESSION_VISIBLE:           //2
947
                case SESSION_AVAILABLE:         //4
948
                    $session['visibility'] = get_lang('Visible');
949
                    break;
950
                case SESSION_INVISIBLE:         //3
951
                    $session['visibility'] = api_ucfirst(get_lang('Invisible'));
952
                    break;
953
            }
954
955
            // Cleaning double selects.
956
            foreach ($session as $key => &$value) {
957
                /*if (isset($optionsByDouble[$key]) || isset($optionsByDouble[$key.'_second'])) {
958
                    $options = explode('::', $value);
959
                }*/
960
                $original_key = $key;
961
                if (false !== strpos($key, '_second')) {
962
                    $key = str_replace('_second', '', $key);
963
                }
964
965
                /*if (isset($optionsByDouble[$key]) &&
966
                    isset($options[0]) &&
967
                    isset($optionsByDouble[$key][$options[0]])
968
                ) {
969
                    if (false === strpos($original_key, '_second')) {
970
                        $value = $optionsByDouble[$key][$options[0]]['option_display_text'];
971
                    } else {
972
                        $value = $optionsByDouble[$key][$options[1]]['option_display_text'];
973
                    }
974
                }*/
975
            }
976
977
            $categoryName = isset($orderedCategories[$session['session_category_id']]) ? $orderedCategories[$session['session_category_id']] : '';
978
            $session['category_name'] = $categoryName;
979
            if (isset($session['status'])) {
980
                $session['status'] = self::getStatusLabel($session['status']);
981
            }
982
983
            $formattedSessions[] = $session;
984
        }
985
986
        return $formattedSessions;
987
    }
988
989
    /**
990
     * Gets the progress of learning paths in the given session.
991
     *
992
     * @param int    $sessionId
993
     * @param int    $courseId
994
     * @param string $date_from
995
     * @param string $date_to
996
     * @param array options order and limit keys
997
     *
998
     * @return array table with user name, lp name, progress
999
     */
1000
    public static function get_session_lp_progress(
1001
        $sessionId,
1002
        $courseId,
1003
        $date_from,
1004
        $date_to,
1005
        $options
1006
    ) {
1007
        //escaping vars
1008
        $sessionId = $sessionId === 'T' ? 'T' : intval($sessionId);
1009
        $courseId = intval($courseId);
1010
1011
        //tables
1012
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1013
        $user = Database::get_main_table(TABLE_MAIN_USER);
1014
        $tbl_course_lp_view = Database::get_course_table(TABLE_LP_VIEW);
1015
1016
        $course = api_get_course_info_by_id($courseId);
1017
        $sessionCond = 'and session_id = %s';
1018
        if ($sessionId === 'T') {
1019
            $sessionCond = '';
1020
        }
1021
1022
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT." $sessionCond";
1023
1024
        $limit = null;
1025
        if (!empty($options['limit'])) {
1026
            $limit = " LIMIT ".$options['limit'];
1027
        }
1028
1029
        if (!empty($options['where'])) {
1030
            $where .= ' '.$options['where'];
1031
        }
1032
1033
        $order = null;
1034
        if (!empty($options['order'])) {
1035
            $order = " ORDER BY ".$options['order']." ";
1036
        }
1037
1038
        $sql = "SELECT u.id as user_id, u.lastname, u.firstname, u.username, u.email, s.c_id
1039
                FROM $session_course_user s
1040
                INNER JOIN $user u ON u.id = s.user_id
1041
                $where
1042
                $order
1043
                $limit";
1044
1045
        $sql_query = sprintf($sql, Database::escape_string($course['real_id']), $sessionId);
1046
1047
        $rs = Database::query($sql_query);
1048
        while ($user = Database::fetch_array($rs)) {
1049
            $users[$user['user_id']] = $user;
1050
        }
1051
1052
        // Get lessons
1053
        $lessons = LearnpathList::get_course_lessons($course['code'], $sessionId);
1054
1055
        $table = [];
1056
        foreach ($users as $user) {
1057
            $data = [
1058
                'lastname' => $user[1],
1059
                'firstname' => $user[2],
1060
                'username' => $user[3],
1061
            ];
1062
1063
            $sessionCond = 'AND v.session_id = %d';
1064
            if ($sessionId == 'T') {
1065
                $sessionCond = "";
1066
            }
1067
1068
            //Get lessons progress by user
1069
            $sql = "SELECT v.lp_id as id, v.progress
1070
                    FROM  $tbl_course_lp_view v
1071
                    WHERE v.c_id = %d
1072
                    AND v.user_id = %d
1073
            $sessionCond";
1074
1075
            $sql_query = sprintf(
1076
                $sql,
1077
                intval($courseId),
1078
                intval($user['user_id']),
1079
                $sessionId
1080
            );
1081
1082
            $result = Database::query($sql_query);
1083
1084
            $user_lessons = [];
1085
            while ($row = Database::fetch_array($result)) {
1086
                $user_lessons[$row['id']] = $row;
1087
            }
1088
1089
            //Match course lessons with user progress
1090
            $progress = 0;
1091
            $count = 0;
1092
            foreach ($lessons as $lesson) {
1093
                $data[$lesson['id']] = (!empty($user_lessons[$lesson['id']]['progress'])) ? $user_lessons[$lesson['id']]['progress'] : 0;
1094
                $progress += $data[$lesson['id']];
1095
                $data[$lesson['id']] = $data[$lesson['id']].'%';
1096
                $count++;
1097
            }
1098
            if (0 == $count) {
1099
                $data['total'] = 0;
1100
            } else {
1101
                $data['total'] = round($progress / $count, 2).'%';
1102
            }
1103
            $table[] = $data;
1104
        }
1105
1106
        return $table;
1107
    }
1108
1109
    /**
1110
     * Gets the survey answers.
1111
     *
1112
     * @param int $sessionId
1113
     * @param int $courseId
1114
     * @param int $surveyId
1115
     * @param array options order and limit keys
1116
     *
1117
     * @todo fix the query
1118
     *
1119
     * @return array table with username, lp name, progress
1120
     */
1121
    public static function get_survey_overview(
1122
        $sessionId,
1123
        $courseId,
1124
        $surveyId,
1125
        $date_from,
1126
        $date_to,
1127
        $options
1128
    ) {
1129
        $sessionId = (int) $sessionId;
1130
        $courseId = (int) $courseId;
1131
        $surveyId = (int) $surveyId;
1132
1133
        //tables
1134
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1135
        $user = Database::get_main_table(TABLE_MAIN_USER);
1136
        $c_survey = Database::get_course_table(TABLE_SURVEY);
1137
        $c_survey_answer = Database::get_course_table(TABLE_SURVEY_ANSWER);
1138
        $c_survey_question = Database::get_course_table(TABLE_SURVEY_QUESTION);
1139
        $c_survey_question_option = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
1140
1141
        $course = api_get_course_info_by_id($courseId);
1142
1143
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT." AND session_id = %s";
1144
1145
        $limit = null;
1146
        if (!empty($options['limit'])) {
1147
            $limit = " LIMIT ".$options['limit'];
1148
        }
1149
1150
        if (!empty($options['where'])) {
1151
            $where .= ' '.$options['where'];
1152
        }
1153
1154
        $order = null;
1155
        if (!empty($options['order'])) {
1156
            $order = " ORDER BY ".$options['order'];
1157
        }
1158
1159
        $sql = "SELECT u.id as user_id, u.lastname, u.firstname, u.username, u.email, s.c_id
1160
                FROM $session_course_user s
1161
                INNER JOIN $user u ON u.id = s.user_id
1162
                $where $order $limit";
1163
1164
        $sql_query = sprintf($sql, intval($course['real_id']), $sessionId);
1165
        $rs = Database::query($sql_query);
1166
        while ($user = Database::fetch_array($rs)) {
1167
            $users[$user['user_id']] = $user;
1168
        }
1169
        $repo = Container::getSurveyRepository();
1170
        /** @var CSurvey $survey */
1171
        $survey = $repo->find($surveyId);
1172
        $questions = $survey->getQuestions();
1173
        $anonymous = (1 == $survey->getAnonymous()) ? true : false;
1174
1175
        $table = [];
1176
        foreach ($users as $user) {
1177
            $data = [
1178
                'lastname' => ($anonymous ? '***' : $user[1]),
1179
                'firstname' => ($anonymous ? '***' : $user[2]),
1180
                'username' => ($anonymous ? '***' : $user[3]),
1181
            ];
1182
1183
            //Get questions by user
1184
            $sql = "SELECT sa.question_id, sa.option_id, sqo.option_text, sq.type
1185
                    FROM $c_survey_answer sa
1186
                    INNER JOIN $c_survey_question sq
1187
                    ON sq.question_id = sa.question_id
1188
                    LEFT JOIN $c_survey_question_option sqo
1189
                    ON
1190
                      sqo.c_id = sa.c_id AND
1191
                      sqo.question_id = sq.question_id AND
1192
                      sqo.iid = sa.option_id AND
1193
                      sqo.survey_id = sq.survey_id
1194
                    WHERE
1195
                      sa.survey_id = %d AND
1196
                      sa.c_id = %d AND
1197
                      sa.user = %d
1198
            "; //. $where_survey;
1199
            $sql_query = sprintf($sql, $surveyId, $courseId, $user['user_id']);
1200
            $result = Database::query($sql_query);
1201
            $user_questions = [];
1202
            while ($row = Database::fetch_array($result)) {
1203
                $user_questions[$row['question_id']] = $row;
1204
            }
1205
1206
            //Match course lessons with user progress
1207
            foreach ($questions as $question) {
1208
                $questionId = $question->getIid();
1209
                $option_text = 'option_text';
1210
                if ('open' === $user_questions[$questionId]['type']) {
1211
                    $option_text = 'option_id';
1212
                }
1213
                $data[$questionId] = $user_questions[$questionId][$option_text];
1214
            }
1215
            $table[] = $data;
1216
        }
1217
1218
        return $table;
1219
    }
1220
1221
    /**
1222
     * Gets the progress of the given session.
1223
     *
1224
     * @param int $sessionId
1225
     * @param int $courseId
1226
     * @param array options order and limit keys
1227
     *
1228
     * @return array table with username, lp name, progress
1229
     */
1230
    public static function get_session_progress(
1231
        $sessionId,
1232
        $courseId,
1233
        $date_from,
1234
        $date_to,
1235
        $options
1236
    ) {
1237
        $sessionId = (int) $sessionId;
1238
1239
        $getAllSessions = false;
1240
        if (empty($sessionId)) {
1241
            $sessionId = 0;
1242
            $getAllSessions = true;
1243
        }
1244
1245
        //tables
1246
        $session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
1247
        $user = Database::get_main_table(TABLE_MAIN_USER);
1248
        $workTable = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
1249
        $workTableAssignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
1250
        $tbl_course_lp = Database::get_course_table(TABLE_LP_MAIN);
1251
        $wiki = Database::get_course_table(TABLE_WIKI);
1252
        $table_stats_default = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
1253
        $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
1254
1255
        $course = api_get_course_info_by_id($courseId);
1256
        $where = " WHERE c_id = '%s' AND s.status = ".Session::STUDENT;
1257
1258
        $limit = null;
1259
        if (!empty($options['limit'])) {
1260
            $limit = " LIMIT ".$options['limit'];
1261
        }
1262
1263
        if (!empty($options['where'])) {
1264
            $where .= ' '.$options['where'];
1265
        }
1266
1267
        $order = null;
1268
        if (!empty($options['order'])) {
1269
            $order = " ORDER BY ".$options['order'];
1270
        }
1271
1272
        //TODO, fix create report without session
1273
        $queryVariables = [$course['real_id']];
1274
        if (!empty($sessionId)) {
1275
            $where .= ' AND session_id = %s';
1276
            $queryVariables[] = $sessionId;
1277
            $sql = "SELECT
1278
                        u.id as user_id, u.lastname, u.firstname, u.username,
1279
                        u.email, s.c_id, s.session_id
1280
                    FROM $session_course_user s
1281
                    INNER JOIN $user u
1282
                    ON u.id = s.user_id
1283
                    $where $order $limit";
1284
        } else {
1285
            $sql = "SELECT
1286
                        u.id as user_id, u.lastname, u.firstname, u.username,
1287
                        u.email, s.c_id, s.session_id
1288
                    FROM $session_course_user s
1289
                    INNER JOIN $user u ON u.id = s.user_id
1290
                    $where $order $limit";
1291
        }
1292
1293
        $sql_query = vsprintf($sql, $queryVariables);
1294
        $rs = Database::query($sql_query);
1295
        while ($user = Database::fetch_array($rs)) {
1296
            $users[$user['user_id']] = $user;
1297
        }
1298
1299
        /**
1300
         *  Lessons.
1301
         */
1302
        $sql = "SELECT * FROM $tbl_course_lp WHERE c_id = %s "; //AND session_id = %s
1303
        $sql_query = sprintf($sql, $course['real_id']);
1304
        $result = Database::query($sql_query);
1305
        $arrLesson = [[]];
1306
        while ($row = Database::fetch_array($result)) {
1307
            if (empty($arrLesson[$row['session_id']]['lessons_total'])) {
1308
                $arrLesson[$row['session_id']]['lessons_total'] = 1;
1309
            } else {
1310
                $arrLesson[$row['session_id']]['lessons_total']++;
1311
            }
1312
        }
1313
        $session = api_get_session_entity($sessionId);
1314
        $qb = Container::getQuizRepository()->findAllByCourse($course, $session, null, 2);
1315
        $exercises = $qb->getQuery()->getResult();
1316
        $exercises_total = count($exercises);
1317
1318
        /*$exercises = ExerciseLib::get_all_exercises(
1319
            $course,
1320
            $sessionId,
1321
            false,
1322
            '',
1323
            $getAllSessions
1324
        );
1325
        $exercises_total = count($exercises);*/
1326
1327
        /**
1328
         *  Assignments.
1329
         */
1330
        //total
1331
        $params = [$course['real_id']];
1332
        if ($getAllSessions) {
1333
            $sql = "SELECT count(w.id) as count
1334
                    FROM $workTable w
1335
                    LEFT JOIN $workTableAssignment a
1336
                    ON (a.publication_id = w.id AND a.c_id = w.c_id)
1337
                    WHERE
1338
                        w.c_id = %s AND
1339
                        parent_id = 0 AND
1340
                        active IN (1, 0)";
1341
        } else {
1342
            $sql = "SELECT count(w.id) as count
1343
                    FROM $workTable w
1344
                    LEFT JOIN $workTableAssignment a
1345
                    ON (a.publication_id = w.id AND a.c_id = w.c_id)
1346
                    WHERE
1347
                        w.c_id = %s AND
1348
                        parent_id = 0 AND
1349
                        active IN (1, 0)";
1350
1351
            if (empty($sessionId)) {
1352
                $sql .= ' AND w.session_id = NULL ';
1353
            } else {
1354
                $sql .= ' AND w.session_id = %s ';
1355
                $params[] = $sessionId;
1356
            }
1357
        }
1358
1359
        $sql_query = vsprintf($sql, $params);
1360
        $result = Database::query($sql_query);
1361
        $row = Database::fetch_array($result);
1362
        $assignments_total = $row['count'];
1363
1364
        /**
1365
         * Wiki.
1366
         */
1367
        if ($getAllSessions) {
1368
            $sql = "SELECT count(distinct page_id)  as count FROM $wiki
1369
                    WHERE c_id = %s";
1370
        } else {
1371
            $sql = "SELECT count(distinct page_id)  as count FROM $wiki
1372
                    WHERE c_id = %s and session_id = %s";
1373
        }
1374
        $sql_query = sprintf($sql, $course['real_id'], $sessionId);
1375
        $result = Database::query($sql_query);
1376
        $row = Database::fetch_array($result);
1377
        $wiki_total = $row['count'];
1378
1379
        /**
1380
         * Surveys.
1381
         */
1382
        $survey_user_list = [];
1383
        $survey_list = SurveyManager::get_surveys($course['code'], $sessionId);
1384
1385
        $surveys_total = count($survey_list);
1386
        foreach ($survey_list as $survey) {
1387
            $user_list = SurveyManager::get_people_who_filled_survey(
1388
                $survey['survey_id'],
1389
                false,
1390
                $course['real_id']
1391
            );
1392
            foreach ($user_list as $user_id) {
1393
                isset($survey_user_list[$user_id]) ? $survey_user_list[$user_id]++ : $survey_user_list[$user_id] = 1;
1394
            }
1395
        }
1396
1397
        /**
1398
         * Forums.
1399
         */
1400
        $forums_total = CourseManager::getCountForum(
1401
            $course['real_id'],
1402
            $sessionId,
1403
            $getAllSessions
1404
        );
1405
1406
        //process table info
1407
        foreach ($users as $user) {
1408
            //Course description
1409
            $sql = "SELECT count(*) as count
1410
                    FROM $table_stats_access
1411
                    WHERE access_tool = 'course_description'
1412
                    AND c_id = '%s'
1413
                    AND session_id = %s
1414
                    AND access_user_id = %s ";
1415
            $sql_query = sprintf($sql, $course['real_id'], $user['id_session'], $user['user_id']);
1416
1417
            $result = Database::query($sql_query);
1418
            $row = Database::fetch_array($result);
1419
            $course_description_progress = ($row['count'] > 0) ? 100 : 0;
1420
1421
            if (!empty($arrLesson[$user['id_session']]['lessons_total'])) {
1422
                $lessons_total = $arrLesson[$user['id_session']]['lessons_total'];
1423
            } else {
1424
                $lessons_total = !empty($arrLesson[0]['lessons_total']) ? $arrLesson[0]['lessons_total'] : 0;
1425
            }
1426
1427
            //Lessons
1428
            //TODO: Lessons done and left is calculated by progress per item in lesson,
1429
            // maybe we should calculate it only per completed lesson?
1430
            $lessons_progress = Tracking::get_avg_student_progress(
1431
                $user['user_id'],
1432
                $course['code'],
1433
                [],
1434
                $user['id_session']
1435
            );
1436
            $lessons_done = ($lessons_progress * $lessons_total) / 100;
1437
            $lessons_left = $lessons_total - $lessons_done;
1438
1439
            // Exercises
1440
            $exercises_progress = str_replace(
1441
                '%',
1442
                '',
1443
                Tracking::get_exercise_student_progress(
1444
                    $exercises,
1445
                    $user['user_id'],
1446
                    $course['real_id'],
1447
                    $user['id_session']
1448
                )
1449
            );
1450
            $exercises_done = round(($exercises_progress * $exercises_total) / 100);
1451
            $exercises_left = $exercises_total - $exercises_done;
1452
1453
            //Assignments
1454
            $assignments_done = Container::getStudentPublicationRepository()->countUserPublications(
1455
                $user['user_id'],
1456
                $course['code'],
1457
                $user['id_session']
1458
            );
1459
            $assignments_left = $assignments_total - $assignments_done;
1460
            if (!empty($assignments_total)) {
1461
                $assignments_progress = round((($assignments_done * 100) / $assignments_total), 2);
1462
            } else {
1463
                $assignments_progress = 0;
1464
            }
1465
1466
            // Wiki
1467
            // total revisions per user
1468
            $sql = "SELECT count(*) as count
1469
                    FROM $wiki
1470
                    WHERE c_id = %s and session_id = %s and user_id = %s";
1471
            $sql_query = sprintf($sql, $course['real_id'], $user['id_session'], $user['user_id']);
1472
            $result = Database::query($sql_query);
1473
            $row = Database::fetch_array($result);
1474
            $wiki_revisions = $row['count'];
1475
            //count visited wiki pages
1476
            $sql = "SELECT count(distinct default_value) as count
1477
                    FROM $table_stats_default
1478
                    WHERE
1479
                        default_user_id = %s AND
1480
                        default_event_type = 'wiki_page_view' AND
1481
                        default_value_type = 'wiki_page_id' AND
1482
                        c_id = %s
1483
                    ";
1484
            $sql_query = sprintf($sql, $user['user_id'], $course['real_id']);
1485
            $result = Database::query($sql_query);
1486
            $row = Database::fetch_array($result);
1487
1488
            $wiki_read = $row['count'];
1489
            $wiki_unread = $wiki_total - $wiki_read;
1490
            if (!empty($wiki_total)) {
1491
                $wiki_progress = round((($wiki_read * 100) / $wiki_total), 2);
1492
            } else {
1493
                $wiki_progress = 0;
1494
            }
1495
1496
            // Surveys
1497
            $surveys_done = isset($survey_user_list[$user['user_id']]) ? $survey_user_list[$user['user_id']] : 0;
1498
            $surveys_left = $surveys_total - $surveys_done;
1499
            if (!empty($surveys_total)) {
1500
                $surveys_progress = round((($surveys_done * 100) / $surveys_total), 2);
1501
            } else {
1502
                $surveys_progress = 0;
1503
            }
1504
1505
            //Forums
1506
            $forums_done = CourseManager::getCountForumPerUser(
1507
                $user['user_id'],
1508
                $course['real_id'],
1509
                $user['id_session']
1510
            );
1511
            $forums_left = $forums_total - $forums_done;
1512
            if (!empty($forums_total)) {
1513
                $forums_progress = round((($forums_done * 100) / $forums_total), 2);
1514
            } else {
1515
                $forums_progress = 0;
1516
            }
1517
1518
            // Overall Total
1519
            $overall_total = ($course_description_progress + $exercises_progress + $forums_progress + $assignments_progress + $wiki_progress + $surveys_progress) / 6;
1520
1521
            $link = '<a href="'.api_get_path(WEB_CODE_PATH).'my_space/myStudents.php?student='.$user[0].'&details=true&course='.$course['code'].'&sid='.$sessionId.'"> %s </a>';
1522
            $linkForum = '<a href="'.api_get_path(WEB_CODE_PATH).'forum/index.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1523
            $linkWork = '<a href="'.api_get_path(WEB_CODE_PATH).'work/work.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1524
            $linkWiki = '<a href="'.api_get_path(WEB_CODE_PATH).'wiki/index.php?cid='.$course['real_id'].'&sid='.$sessionId.'&action=statistics"> %s </a>';
1525
            $linkSurvey = '<a href="'.api_get_path(WEB_CODE_PATH).'survey/survey_list.php?cid='.$course['real_id'].'&sid='.$sessionId.'"> %s </a>';
1526
1527
            $table[] = [
1528
                'lastname' => $user[1],
1529
                'firstname' => $user[2],
1530
                'username' => $user[3],
1531
                //'profile'   => '',
1532
                'total' => round($overall_total, 2).'%',
1533
                'courses' => sprintf($link, $course_description_progress.'%'),
1534
                'lessons' => sprintf($link, $lessons_progress.'%'),
1535
                'exercises' => sprintf($link, $exercises_progress.'%'),
1536
                'forums' => sprintf($link, $forums_progress.'%'),
1537
                'homeworks' => sprintf($link, $assignments_progress.'%'),
1538
                'wikis' => sprintf($link, $wiki_progress.'%'),
1539
                'surveys' => sprintf($link, $surveys_progress.'%'),
1540
                //course description
1541
                'course_description_progress' => $course_description_progress.'%',
1542
                //lessons
1543
                'lessons_total' => sprintf($link, $lessons_total),
1544
                'lessons_done' => sprintf($link, $lessons_done),
1545
                'lessons_left' => sprintf($link, $lessons_left),
1546
                'lessons_progress' => sprintf($link, $lessons_progress.'%'),
1547
                //exercises
1548
                'exercises_total' => sprintf($link, $exercises_total),
1549
                'exercises_done' => sprintf($link, $exercises_done),
1550
                'exercises_left' => sprintf($link, $exercises_left),
1551
                'exercises_progress' => sprintf($link, $exercises_progress.'%'),
1552
                //forums
1553
                'forums_total' => sprintf($linkForum, $forums_total),
1554
                'forums_done' => sprintf($linkForum, $forums_done),
1555
                'forums_left' => sprintf($linkForum, $forums_left),
1556
                'forums_progress' => sprintf($linkForum, $forums_progress.'%'),
1557
                //assignments
1558
                'assignments_total' => sprintf($linkWork, $assignments_total),
1559
                'assignments_done' => sprintf($linkWork, $assignments_done),
1560
                'assignments_left' => sprintf($linkWork, $assignments_left),
1561
                'assignments_progress' => sprintf($linkWork, $assignments_progress.'%'),
1562
                //wiki
1563
                'wiki_total' => sprintf($linkWiki, $wiki_total),
1564
                'wiki_revisions' => sprintf($linkWiki, $wiki_revisions),
1565
                'wiki_read' => sprintf($linkWiki, $wiki_read),
1566
                'wiki_unread' => sprintf($linkWiki, $wiki_unread),
1567
                'wiki_progress' => sprintf($linkWiki, $wiki_progress.'%'),
1568
                //survey
1569
                'surveys_total' => sprintf($linkSurvey, $surveys_total),
1570
                'surveys_done' => sprintf($linkSurvey, $surveys_done),
1571
                'surveys_left' => sprintf($linkSurvey, $surveys_left),
1572
                'surveys_progress' => sprintf($linkSurvey, $surveys_progress.'%'),
1573
            ];
1574
        }
1575
1576
        return $table;
1577
    }
1578
1579
    /**
1580
     * Get the ip, total of clicks, login date and time logged in for all user, in one session.
1581
     *
1582
     * @todo track_e_course_access table should have ip so we dont have to look for it in track_e_login
1583
     *
1584
     * @author César Perales <[email protected]>, Beeznest Team
1585
     *
1586
     * @version 1.9.6
1587
     */
1588
    public static function get_user_data_access_tracking_overview(
1589
        $sessionId,
1590
        $courseId,
1591
        $studentId = 0,
1592
        $profile = '',
1593
        $date_from = '',
1594
        $date_to = '',
1595
        $options = []
1596
    ) {
1597
        $sessionId = intval($sessionId);
1598
        $courseId = intval($courseId);
1599
        $studentId = intval($studentId);
1600
        $profile = intval($profile);
1601
        $date_from = Database::escape_string($date_from);
1602
        $date_to = Database::escape_string($date_to);
1603
1604
        // database table definition
1605
        $user = Database::get_main_table(TABLE_MAIN_USER);
1606
        $course = Database::get_main_table(TABLE_MAIN_COURSE);
1607
        $track_e_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
1608
        $track_e_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
1609
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
1610
1611
        global $export_csv;
1612
        if ($export_csv) {
1613
            $is_western_name_order = api_is_western_name_order(PERSON_NAME_DATA_EXPORT);
1614
        } else {
1615
            $is_western_name_order = api_is_western_name_order();
1616
        }
1617
1618
        $where = null;
1619
        if (isset($sessionId) && !empty($sessionId)) {
1620
            $where = sprintf(" WHERE a.session_id = %d", $sessionId);
1621
        }
1622
        if (isset($courseId) && !empty($courseId)) {
1623
            $where .= sprintf(" AND c.id = %d", $courseId);
1624
        }
1625
        if (isset($studentId) && !empty($studentId)) {
1626
            $where .= sprintf(" AND u.id = %d", $studentId);
1627
        }
1628
        if (isset($profile) && !empty($profile)) {
1629
            $where .= sprintf(" AND u.status = %d", $profile);
1630
        }
1631
        if (!empty($date_to) && !empty($date_from)) {
1632
            $where .= sprintf(
1633
                " AND a.login_course_date >= '%s 00:00:00'
1634
                 AND a.login_course_date <= '%s 23:59:59'",
1635
                $date_from,
1636
                $date_to
1637
            );
1638
        }
1639
1640
        $limit = null;
1641
        if (!empty($options['limit'])) {
1642
            $limit = " LIMIT ".$options['limit'];
1643
        }
1644
1645
        if (!empty($options['where'])) {
1646
            $where .= ' '.$options['where'];
1647
        }
1648
1649
        $order = null;
1650
        if (!empty($options['order'])) {
1651
            $order = " ORDER BY ".$options['order'];
1652
        }
1653
1654
        //TODO add course name
1655
        $sql = "SELECT
1656
                a.login_course_date ,
1657
                u.username ,
1658
                ".($is_western_name_order ? "
1659
                    u.firstname,
1660
                    u.lastname,
1661
                    " : "
1662
                    u.lastname,
1663
                    u.firstname,
1664
                ")."
1665
                a.logout_course_date,
1666
                a.counter,
1667
                c.title,
1668
                c.code,
1669
                u.id as user_id,
1670
                a.session_id
1671
            FROM $track_e_course_access a
1672
            INNER JOIN $user u ON a.user_id = u.id
1673
            INNER JOIN $course c ON a.c_id = c.id
1674
            $where $order $limit";
1675
        $result = Database::query(sprintf($sql, $sessionId, $courseId));
1676
1677
        $data = [];
1678
        while ($user = Database::fetch_assoc($result)) {
1679
            $data[] = $user;
1680
        }
1681
1682
        foreach ($data as $key => $info) {
1683
            $sql = "SELECT
1684
                    title
1685
                    FROM $sessionTable
1686
                    WHERE
1687
                    id = {$info['session_id']}";
1688
            $result = Database::query($sql);
1689
            $session = Database::fetch_assoc($result);
1690
1691
            // building array to display
1692
            $return[] = [
1693
                'user_id' => $info['user_id'],
1694
                'logindate' => $info['login_course_date'],
1695
                'username' => $info['username'],
1696
                'firstname' => $info['firstname'],
1697
                'lastname' => $info['lastname'],
1698
                'clicks' => $info['counter'], //+ $clicks[$info['user_id']],
1699
                'ip' => '',
1700
                'timeLoggedIn' => gmdate("H:i:s", strtotime($info['logout_course_date']) - strtotime($info['login_course_date'])),
1701
                'session' => $session['title'],
1702
            ];
1703
        }
1704
1705
        foreach ($return as $key => $info) {
1706
            //Search for ip, we do less querys if we iterate the final array
1707
            $sql = sprintf(
1708
                "SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date < '%s' ORDER BY login_date DESC LIMIT 1",
1709
                $info['user_id'],
1710
                $info['logindate']
1711
            ); //TODO add select by user too
1712
            $result = Database::query($sql);
1713
            $ip = Database::fetch_assoc($result);
1714
            //if no ip founded, we search the closest higher ip
1715
            if (empty($ip['user_ip'])) {
1716
                $sql = sprintf(
1717
                    "SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date > '%s'  ORDER BY login_date ASC LIMIT 1",
1718
                    $info['user_id'],
1719
                    $info['logindate']
1720
                ); //TODO add select by user too
1721
                $result = Database::query($sql);
1722
                $ip = Database::fetch_assoc($result);
1723
            }
1724
            //add ip to final array
1725
            $return[$key]['ip'] = $ip['user_ip'];
1726
        }
1727
1728
        return $return;
1729
    }
1730
1731
    /**
1732
     * Creates a new course code based in given code.
1733
     *
1734
     * @param string $session_name
1735
     *                             <code>
1736
     *                             $wanted_code = 'curse' if there are in the DB codes like curse1 curse2 the function will return: course3
1737
     *                             if the course code doest not exist in the DB the same course code will be returned
1738
     *                             </code>
1739
     *
1740
     * @return string wanted unused code
1741
     */
1742
    public static function generateNextSessionName($session_name)
1743
    {
1744
        $session_name_ok = !self::sessionNameExists($session_name);
1745
        if (!$session_name_ok) {
1746
            $table = Database::get_main_table(TABLE_MAIN_SESSION);
1747
            $session_name = Database::escape_string($session_name);
1748
            $sql = "SELECT count(*) as count FROM $table
1749
                    WHERE title LIKE '$session_name%'";
1750
            $result = Database::query($sql);
1751
            if (Database::num_rows($result) > 0) {
1752
                $row = Database::fetch_array($result);
1753
                $count = $row['count'] + 1;
1754
                $session_name = $session_name.'_'.$count;
1755
                $result = self::sessionNameExists($session_name);
1756
                if (!$result) {
1757
                    return $session_name;
1758
                }
1759
            }
1760
1761
            return false;
1762
        }
1763
1764
        return $session_name;
1765
    }
1766
1767
    /**
1768
     * Edit a session.
1769
     *
1770
     * @author Carlos Vargas from existing code
1771
     *
1772
     * @param int    $id                           Session primary key
1773
     * @param string $name
1774
     * @param string $startDate
1775
     * @param string $endDate
1776
     * @param string $displayStartDate
1777
     * @param string $displayEndDate
1778
     * @param string $coachStartDate
1779
     * @param string $coachEndDate
1780
     * @param array  $coachesId
1781
     * @param int    $sessionCategoryId
1782
     * @param int    $visibility
1783
     * @param string $description
1784
     * @param int    $showDescription
1785
     * @param int    $duration
1786
     * @param array  $extraFields
1787
     * @param int    $sessionAdminId
1788
     * @param bool   $sendSubscriptionNotification Optional. Whether send a mail notification to users being subscribed
1789
     * @param int    $status
1790
     *
1791
     * @return mixed
1792
     */
1793
    public static function edit_session(
1794
        $id,
1795
        $name,
1796
        $startDate,
1797
        $endDate,
1798
        $displayStartDate,
1799
        $displayEndDate,
1800
        $coachStartDate,
1801
        $coachEndDate,
1802
        $coachesId,
1803
        $sessionCategoryId,
1804
        $visibility,
1805
        $description = null,
1806
        $showDescription = 0,
1807
        $duration = 0,
1808
        $extraFields = [],
1809
        $sessionAdminId = 0,
1810
        $sendSubscriptionNotification = false,
1811
        $status = 0,
1812
        $notifyBoss = 0,
1813
        $parentId = 0,
1814
        $daysBeforeFinishingForReinscription = null,
1815
        $daysBeforeFinishingToCreateNewRepetition = null,
1816
        $lastRepetition = false,
1817
        $validityInDays = null
1818
    ) {
1819
        $id = (int) $id;
1820
        $status = (int) $status;
1821
        $coachesId = array_map(fn($id) => (int) $id, $coachesId);
1822
        $sessionCategoryId = (int) $sessionCategoryId;
1823
        $visibility = (int) $visibility;
1824
        $duration = (int) $duration;
1825
1826
        $em = Database::getManager();
1827
1828
        if (empty($name)) {
1829
            Display::addFlash(
1830
                Display::return_message(get_lang('A name is required for the session'), 'warning')
1831
            );
1832
1833
            return false;
1834
        } elseif (empty($coachesId)) {
1835
            Display::addFlash(
1836
                Display::return_message(get_lang('You must select a coach'), 'warning')
1837
            );
1838
1839
            return false;
1840
        } elseif (!empty($startDate) &&
1841
            !api_is_valid_date($startDate, 'Y-m-d H:i') &&
1842
            !api_is_valid_date($startDate, 'Y-m-d H:i:s')
1843
        ) {
1844
            Display::addFlash(
1845
                Display::return_message(get_lang('Invalid start date was given.'), 'warning')
1846
            );
1847
1848
            return false;
1849
        } elseif (!empty($endDate) &&
1850
            !api_is_valid_date($endDate, 'Y-m-d H:i') &&
1851
            !api_is_valid_date($endDate, 'Y-m-d H:i:s')
1852
        ) {
1853
            Display::addFlash(
1854
                Display::return_message(get_lang('Invalid end date was given.'), 'warning')
1855
            );
1856
1857
            return false;
1858
        } elseif (!empty($startDate) && !empty($endDate) && $startDate >= $endDate) {
1859
            Display::addFlash(
1860
                Display::return_message(get_lang('The first date should be before the end date'), 'warning')
1861
            );
1862
1863
            return false;
1864
        } else {
1865
            $sessionInfo = self::get_session_by_name($name);
1866
            $exists = false;
1867
            if (!empty($sessionInfo) && (int) $sessionInfo['id'] !== $id) {
1868
                $exists = true;
1869
            }
1870
1871
            if ($exists) {
1872
                Display::addFlash(
1873
                    Display::return_message(get_lang('Session title already exists'), 'warning')
1874
                );
1875
1876
                return false;
1877
            } else {
1878
                $sessionEntity = api_get_session_entity($id);
1879
                $sessionEntity
1880
                    ->setTitle($name)
1881
                    ->setDuration($duration)
1882
                    ->setDescription($description)
1883
                    ->setShowDescription(1 === $showDescription)
1884
                    ->setVisibility($visibility)
1885
                    ->setSendSubscriptionNotification((bool) $sendSubscriptionNotification)
1886
                    ->setNotifyBoss((bool) $notifyBoss)
1887
                    ->setParentId($parentId)
1888
                    ->setDaysToReinscription((int) $daysBeforeFinishingForReinscription)
1889
                    ->setLastRepetition($lastRepetition)
1890
                    ->setDaysToNewRepetition((int) $daysBeforeFinishingToCreateNewRepetition)
1891
                    ->setValidityInDays((int) $validityInDays)
1892
                    ->setAccessStartDate(null)
1893
                    ->setAccessStartDate(null)
1894
                    ->setDisplayStartDate(null)
1895
                    ->setDisplayEndDate(null)
1896
                    ->setCoachAccessStartDate(null)
1897
                    ->setCoachAccessEndDate(null)
1898
                ;
1899
1900
                if ($parentId) {
1901
                    $sessionEntity->setParentId($parentId);
1902
                } else {
1903
                    $sessionEntity->setParentId(null);
1904
                }
1905
1906
                $sessionEntity->setDaysToReinscription($daysBeforeFinishingForReinscription);
1907
                $sessionEntity->setLastRepetition($lastRepetition);
1908
                $sessionEntity->setDaysToNewRepetition($daysBeforeFinishingToCreateNewRepetition);
1909
1910
                $newGeneralCoaches = array_map(
1911
                    fn($coachId) => api_get_user_entity($coachId),
1912
                    $coachesId
1913
                );
1914
                $currentGeneralCoaches = $sessionEntity->getGeneralCoaches();
1915
1916
                foreach ($newGeneralCoaches as $generalCoach) {
1917
                    if (!$sessionEntity->hasUserAsGeneralCoach($generalCoach)) {
1918
                        $sessionEntity->addGeneralCoach($generalCoach);
1919
                    }
1920
                }
1921
1922
                foreach ($currentGeneralCoaches as $generalCoach) {
1923
                    if (!in_array($generalCoach, $newGeneralCoaches, true)) {
1924
                        $sessionEntity->removeGeneralCoach($generalCoach);
1925
                    }
1926
                }
1927
1928
                if (!empty($sessionAdminId)) {
1929
                    $sessionEntity->addSessionAdmin(api_get_user_entity($sessionAdminId));
1930
                }
1931
1932
                if (!empty($startDate)) {
1933
                    $sessionEntity->setAccessStartDate(api_get_utc_datetime($startDate, true, true));
1934
                }
1935
1936
                if (!empty($endDate)) {
1937
                    $sessionEntity->setAccessEndDate(api_get_utc_datetime($endDate, true, true));
1938
                }
1939
1940
                if (!empty($displayStartDate)) {
1941
                    $sessionEntity->setDisplayStartDate(api_get_utc_datetime($displayStartDate, true, true));
1942
                }
1943
1944
                if (!empty($displayEndDate)) {
1945
                    $sessionEntity->setDisplayEndDate(api_get_utc_datetime($displayEndDate, true, true));
1946
                }
1947
1948
                if (!empty($coachStartDate)) {
1949
                    $sessionEntity->setCoachAccessStartDate(api_get_utc_datetime($coachStartDate, true, true));
1950
                }
1951
1952
                if (!empty($coachEndDate)) {
1953
                    $sessionEntity->setCoachAccessEndDate(api_get_utc_datetime($coachEndDate, true, true));
1954
                }
1955
1956
                if (!empty($sessionCategoryId)) {
1957
                    $category = $em->getRepository(SessionCategory::class)->find($sessionCategoryId);
1958
                    $sessionEntity->setCategory($category);
1959
                } else {
1960
                    $sessionEntity->setCategory(null);
1961
                }
1962
                $sessionEntity->setStatus($status);
1963
1964
                $em->flush();
1965
1966
                if (!empty($extraFields)) {
1967
                    $extraFields['item_id'] = $id;
1968
                    $sessionFieldValue = new ExtraFieldValue('session');
1969
                    $sessionFieldValue->saveFieldValues($extraFields);
1970
                }
1971
1972
                return $id;
1973
            }
1974
        }
1975
    }
1976
1977
    /**
1978
     * Delete session.
1979
     *
1980
     * @author Carlos Vargas  from existing code
1981
     *
1982
     * @param array $idChecked an array to delete sessions
1983
     * @param bool  $fromWs    optional, true if the function is called
1984
     *                          by a webservice, false otherwise
1985
     *
1986
     * @return bool
1987
     * */
1988
    public static function delete($idChecked, $fromWs = false)
1989
    {
1990
        $sessionId = null;
1991
        if (is_array($idChecked)) {
1992
            foreach ($idChecked as $sessionId) {
1993
                self::delete($sessionId);
1994
            }
1995
        } else {
1996
            $sessionId = (int) $idChecked;
1997
        }
1998
1999
        if (empty($sessionId)) {
2000
            return false;
2001
        }
2002
2003
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2004
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2005
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2006
        $tblUrlSession = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
2007
        $userGroupSessionTable = Database::get_main_table(TABLE_USERGROUP_REL_SESSION);
2008
        $trackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
2009
        $trackAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
2010
2011
        $ticket = Database::get_main_table(TABLE_TICKET_TICKET);
2012
        $em = Database::getManager();
2013
        $userId = api_get_user_id();
2014
        $user = api_get_user_entity();
2015
2016
        $repo = Container::getSequenceResourceRepository();
2017
        $sequenceResource = $repo->findRequirementForResource(
2018
            $sessionId,
2019
            SequenceResource::SESSION_TYPE
2020
        );
2021
2022
        $sessionEntity = api_get_session_entity($sessionId);
2023
        if (null === $sessionEntity) {
2024
            return false;
2025
        }
2026
2027
        if ($sequenceResource) {
2028
            Display::addFlash(
2029
                Display::return_message(
2030
                    get_lang('There is a sequence resource linked to this session. You must delete this link first.'),
2031
                    'error'
2032
                )
2033
            );
2034
2035
            return false;
2036
        }
2037
2038
        if (self::allowed($sessionEntity) && !$fromWs) {
2039
            if (!$sessionEntity->hasUserAsSessionAdmin($user) && !api_is_platform_admin()) {
2040
                api_not_allowed(true);
2041
            }
2042
        }
2043
2044
        // Delete Picture Session
2045
        SessionManager::deleteAsset($sessionId);
2046
2047
        $sessionName = $sessionEntity->getTitle();
2048
        $em->remove($sessionEntity);
2049
        $em->flush();
2050
2051
        // Delete explicitly from tables not directly related to 'session'
2052
        $tables = [
2053
            'track_e_lastaccess',
2054
            'track_e_default',
2055
            'track_e_exercise_confirmation',
2056
            'track_e_links',
2057
            'track_e_online',
2058
            'track_e_attempt_qualify',
2059
            'track_e_access_complete',
2060
            'track_e_uploads',
2061
            'c_dropbox_file',
2062
            'c_forum_thread_qualify_log',
2063
            'c_dropbox_post',
2064
            'c_survey_answer',
2065
            'c_wiki_mailcue',
2066
            'c_dropbox_category',
2067
            'skill_rel_item',
2068
            'scheduled_announcements',
2069
            'sequence_row_entity',
2070
        ];
2071
2072
        foreach ($tables as $table) {
2073
            Database::delete($table, ['session_id = ?' => $sessionId]);
2074
        }
2075
2076
        // Delete other related tables
2077
        Database::delete($userGroupSessionTable, ['session_id = ?' => $sessionId]);
2078
        Database::delete($tblSessionRelCourse, ['session_id = ?' => $sessionId]);
2079
        Database::delete($tblSessionRelCourseRelUser, ['session_id = ?' => $sessionId]);
2080
        Database::delete($tblSessionRelUser, ['session_id = ?' => $sessionId]);
2081
        Database::delete($tblUrlSession, ['session_id = ?' => $sessionId]);
2082
        Database::delete($trackCourseAccess, ['session_id = ?' => $sessionId]);
2083
        Database::delete($trackAccess, ['session_id = ?' => $sessionId]);
2084
        Database::update($ticket, ['session_id' => null], ['session_id = ?' => $sessionId]);
2085
2086
        $extraFieldValue = new ExtraFieldValue('session');
2087
        $extraFieldValue->deleteValuesByItem($sessionId);
2088
2089
        $repo->deleteSequenceResource($sessionId, SequenceResource::SESSION_TYPE);
2090
2091
        // Add event to system log
2092
        Event::addEvent(
2093
            LOG_SESSION_DELETE,
2094
            LOG_SESSION_ID,
2095
            $sessionName.' - id:'.$sessionId,
2096
            api_get_utc_datetime(),
2097
            $userId
2098
        );
2099
2100
        return true;
2101
    }
2102
2103
    /**
2104
     * @param int $id promotion id
2105
     *
2106
     * @return bool
2107
     */
2108
    public static function clear_session_ref_promotion($id)
2109
    {
2110
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2111
        $id = intval($id);
2112
        $sql = "UPDATE $tbl_session
2113
                SET promotion_id = 0
2114
                WHERE promotion_id = $id";
2115
        if (Database::query($sql)) {
2116
            return true;
2117
        } else {
2118
            return false;
2119
        }
2120
    }
2121
2122
    /**
2123
     * Subscribes students to the given session and optionally (default)
2124
     * unsubscribes previous users.
2125
     *
2126
     * @author Carlos Vargas from existing code
2127
     * @author Julio Montoya. Cleaning code.
2128
     *
2129
     * @param int   $sessionId
2130
     * @param array $userList
2131
     * @param int   $session_visibility
2132
     * @param bool  $empty_users
2133
     * @param bool  $registerUsersToAllCourses
2134
     *
2135
     * @return bool
2136
     */
2137
    public static function subscribeUsersToSession(
2138
        $sessionId,
2139
        $userList,
2140
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2141
        $empty_users = true,
2142
        $registerUsersToAllCourses = true
2143
    ) {
2144
        $sessionId = (int) $sessionId;
2145
2146
        if (empty($sessionId)) {
2147
            return false;
2148
        }
2149
2150
        foreach ($userList as $intUser) {
2151
            if ($intUser != strval(intval($intUser))) {
2152
                return false;
2153
            }
2154
        }
2155
2156
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2157
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2158
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2159
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2160
2161
        $session = api_get_session_entity($sessionId);
2162
2163
        // from function parameter
2164
        if (empty($session_visibility)) {
2165
            $session_visibility = $session->getVisibility();
2166
            //default status loaded if empty
2167
            // by default readonly 1
2168
            if (empty($session_visibility)) {
2169
                $session_visibility = SESSION_VISIBLE_READ_ONLY;
2170
            }
2171
        } elseif (!in_array($session_visibility, [SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_INVISIBLE])) {
2172
            $session_visibility = SESSION_VISIBLE_READ_ONLY;
2173
        }
2174
2175
        $sql = "SELECT user_id FROM $tbl_session_rel_course_rel_user
2176
                WHERE session_id = $sessionId AND status = ".Session::STUDENT;
2177
        $result = Database::query($sql);
2178
        $existingUsers = [];
2179
        while ($row = Database::fetch_array($result)) {
2180
            $existingUsers[] = $row['user_id'];
2181
        }
2182
2183
        $sql = "SELECT c_id FROM $tbl_session_rel_course
2184
                WHERE session_id = $sessionId";
2185
        $result = Database::query($sql);
2186
        $course_list = [];
2187
        while ($row = Database::fetch_array($result)) {
2188
            $course_list[] = $row['c_id'];
2189
        }
2190
2191
        if ($session->getSendSubscriptionNotification() && is_array($userList)) {
2192
            foreach ($userList as $user_id) {
2193
                $tplSubject = new Template(
2194
                    null,
2195
                    false,
2196
                    false,
2197
                    false,
2198
                    false,
2199
                    false
2200
                );
2201
                $layoutSubject = $tplSubject->get_template(
2202
                    'mail/subject_subscription_to_session_confirmation.tpl'
2203
                );
2204
                $subject = $tplSubject->fetch($layoutSubject);
2205
                $user_info = api_get_user_info($user_id);
2206
2207
                $tplContent = new Template(
2208
                    null,
2209
                    false,
2210
                    false,
2211
                    false,
2212
                    false,
2213
                    false
2214
                );
2215
                // Variables for default template
2216
                $tplContent->assign('complete_name', stripslashes($user_info['complete_name']));
2217
                $tplContent->assign('session_name', $session->getTitle());
2218
                $tplContent->assign(
2219
                    'session_coaches',
2220
                    $session->getGeneralCoaches()->map(fn(User $coach) => UserManager::formatUserFullName($coach))
2221
                );
2222
                $layoutContent = $tplContent->get_template(
2223
                    'mail/content_subscription_to_session_confirmation.tpl'
2224
                );
2225
                $content = $tplContent->fetch($layoutContent);
2226
2227
                // Send email
2228
                api_mail_html(
2229
                    $user_info['complete_name'],
2230
                    $user_info['mail'],
2231
                    $subject,
2232
                    $content,
2233
                    api_get_person_name(
2234
                        api_get_setting('administratorName'),
2235
                        api_get_setting('administratorSurname')
2236
                    ),
2237
                    api_get_setting('emailAdministrator')
2238
                );
2239
2240
                // Record message in system
2241
                MessageManager::send_message_simple(
2242
                    $user_id,
2243
                    $subject,
2244
                    $content,
2245
                    api_get_user_id(),
2246
                    false,
2247
                    true
2248
                );
2249
            }
2250
        }
2251
2252
        if ($session->getNotifyBoss()) {
2253
            foreach ($userList as $user_id) {
2254
                $studentBossList = UserManager::getStudentBossList($user_id);
2255
2256
                if (!empty($studentBossList)) {
2257
                    $studentBossList = array_column($studentBossList, 'boss_id');
2258
                    foreach ($studentBossList as $bossId) {
2259
                        $boss = api_get_user_entity($bossId);
2260
                        self::notifyBossOfInscription($boss, $session, $user_id);
2261
                    }
2262
                }
2263
            }
2264
        }
2265
2266
        if ($registerUsersToAllCourses) {
2267
            foreach ($course_list as $courseId) {
2268
                // for each course in the session
2269
                $nbr_users = 0;
2270
                $courseId = (int) $courseId;
2271
2272
                $sql = "SELECT DISTINCT user_id
2273
                        FROM $tbl_session_rel_course_rel_user
2274
                        WHERE
2275
                            session_id = $sessionId AND
2276
                            c_id = $courseId AND
2277
                            status = ".Session::STUDENT;
2278
                $result = Database::query($sql);
2279
                $existingUsers = [];
2280
                while ($row = Database::fetch_array($result)) {
2281
                    $existingUsers[] = $row['user_id'];
2282
                }
2283
2284
                // Delete existing users
2285
                if ($empty_users) {
2286
                    foreach ($existingUsers as $existing_user) {
2287
                        if (!in_array($existing_user, $userList)) {
2288
                            self::unSubscribeUserFromCourseSession($existing_user, $courseId, $sessionId);
2289
                        }
2290
                    }
2291
                }
2292
2293
                $usersToSubscribeInCourse = array_filter(
2294
                    $userList,
2295
                    function ($userId) use ($existingUsers) {
2296
                        return !in_array($userId, $existingUsers);
2297
                    }
2298
                );
2299
2300
                self::insertUsersInCourse(
2301
                    $usersToSubscribeInCourse,
2302
                    $courseId,
2303
                    $sessionId,
2304
                    ['visibility' => $session_visibility],
2305
                    false
2306
                );
2307
            }
2308
        }
2309
2310
        // Delete users from the session
2311
        if (true === $empty_users) {
2312
            $sql = "DELETE FROM $tbl_session_rel_user
2313
                    WHERE
2314
                      session_id = $sessionId AND
2315
                      relation_type = ".Session::STUDENT;
2316
            // Don't reset session_rel_user.registered_at of users that will be registered later anyways.
2317
            if (!empty($userList)) {
2318
                $avoidDeleteThisUsers = " AND user_id NOT IN ('".implode("','", $userList)."')";
2319
                $sql .= $avoidDeleteThisUsers;
2320
            }
2321
            Event::addEvent(
2322
                LOG_SESSION_DELETE_USER,
2323
                LOG_USER_ID,
2324
                'all',
2325
                api_get_utc_datetime(),
2326
                api_get_user_id(),
2327
                null,
2328
                $sessionId
2329
            );
2330
            Database::query($sql);
2331
        }
2332
2333
        // Insert missing users into session
2334
        foreach ($userList as $enreg_user) {
2335
            $isUserSubscribed = self::isUserSubscribedAsStudent($sessionId, $enreg_user);
2336
            if (false === $isUserSubscribed) {
2337
                $enreg_user = (int) $enreg_user;
2338
                if ($session->getDuration() > 0) {
2339
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at)
2340
                        VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."')";
2341
                } else {
2342
                    if (null != ($accessStartDate = $session->getAccessStartDate())) {
2343
                        $accessStartDate = "'".$accessStartDate->format('Y-m-d H:i:s')."'";
2344
                    } else {
2345
                        $accessStartDate = "NULL";
2346
                    }
2347
                    if (null != ($accessEndDate = $session->getAccessEndDate())) {
2348
                        $accessEndDate = "'".$accessEndDate->format('Y-m-d H:i:s')."'";
2349
                    } else {
2350
                        $accessEndDate = "NULL";
2351
                    }
2352
                    $sql = "INSERT IGNORE INTO $tbl_session_rel_user (relation_type, session_id, user_id, registered_at, access_start_date, access_end_date)
2353
                            VALUES (".Session::STUDENT.", $sessionId, $enreg_user, '".api_get_utc_datetime()."', ".$accessStartDate.", ".$accessEndDate.")";
2354
                }
2355
                Database::query($sql);
2356
                Event::addEvent(
2357
                    LOG_SESSION_ADD_USER,
2358
                    LOG_USER_ID,
2359
                    $enreg_user,
2360
                    api_get_utc_datetime(),
2361
                    api_get_user_id(),
2362
                    null,
2363
                    $sessionId
2364
                );
2365
            }
2366
        }
2367
2368
        // update number of users in the session
2369
        $sql = "UPDATE $tbl_session
2370
                SET nbr_users = (SELECT count(user_id) FROM $tbl_session_rel_user WHERE session_id = $sessionId)
2371
                WHERE id = $sessionId";
2372
        Database::query($sql);
2373
2374
        return true;
2375
    }
2376
2377
    /**
2378
     * Sends a notification email to the student's boss when the student is enrolled in a session.
2379
     *
2380
     * @param User $boss The boss of the student to be notified.
2381
     * @param Session $session The session the student has been enrolled in.
2382
     * @param int $userId The ID of the student being enrolled.
2383
     */
2384
    public static function notifyBossOfInscription(User $boss, Session $session, int $userId): void
2385
    {
2386
        $tpl = Container::getTwig();
2387
2388
        $user_info = api_get_user_info($userId);
2389
2390
        $subject = $tpl->render(
2391
            '@ChamiloCore/Mailer/Legacy/subject_subscription_to_boss_notification.html.twig',
2392
            [
2393
                'locale' => $boss->getLocale(),
2394
                'boss_name' => $boss->getFullname(),
2395
                'student_name' => $user_info['complete_name'],
2396
                'session_name' => $session->getTitle(),
2397
            ]
2398
        );
2399
2400
        $content = $tpl->render(
2401
            '@ChamiloCore/Mailer/Legacy/content_subscription_to_boss_notification.html.twig',
2402
            [
2403
                'locale' => $boss->getLocale(),
2404
                'boss_name' => $boss->getFullname(),
2405
                'student_name' => $user_info['complete_name'],
2406
                'session_name' => $session->getTitle(),
2407
            ]
2408
        );
2409
2410
        // Send email
2411
        api_mail_html(
2412
            $boss->getFullname(),
2413
            $boss->getEmail(),
2414
            $subject,
2415
            $content,
2416
            api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname')),
2417
            api_get_setting('emailAdministrator')
2418
        );
2419
2420
        // Record message in system
2421
        MessageManager::send_message_simple(
2422
            $boss->getId(),
2423
            $subject,
2424
            $content,
2425
            api_get_user_id(),
2426
            false,
2427
            true
2428
        );
2429
    }
2430
2431
    /**
2432
     * Returns user list of the current users subscribed in the course-session.
2433
     *
2434
     * @param int   $sessionId
2435
     * @param array $courseInfo
2436
     * @param int   $status
2437
     *
2438
     * @return array
2439
     */
2440
    public static function getUsersByCourseSession(
2441
        $sessionId,
2442
        $courseInfo,
2443
        $status = null
2444
    ) {
2445
        $sessionId = (int) $sessionId;
2446
        $courseId = $courseInfo['real_id'];
2447
2448
        if (empty($sessionId) || empty($courseId)) {
2449
            return [];
2450
        }
2451
2452
        $statusCondition = null;
2453
        if (isset($status) && !is_null($status)) {
2454
            $status = (int) $status;
2455
            $statusCondition = " AND status = $status";
2456
        }
2457
2458
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2459
2460
        $sql = "SELECT DISTINCT user_id
2461
                FROM $table
2462
                WHERE
2463
                    session_id = $sessionId AND
2464
                    c_id = $courseId
2465
                    $statusCondition
2466
                ";
2467
2468
        $result = Database::query($sql);
2469
        $existingUsers = [];
2470
        while ($row = Database::fetch_array($result)) {
2471
            $existingUsers[] = $row['user_id'];
2472
        }
2473
2474
        return $existingUsers;
2475
    }
2476
2477
    /**
2478
     * Returns user list of the current users subscribed in the course-session.
2479
     *
2480
     * @param array $sessionList
2481
     * @param array $courseList
2482
     * @param int   $status
2483
     * @param int   $start
2484
     * @param int   $limit
2485
     *
2486
     * @return array
2487
     */
2488
    public static function getUsersByCourseAndSessionList(
2489
        $sessionList,
2490
        $courseList,
2491
        $status = null,
2492
        $start = null,
2493
        $limit = null
2494
    ) {
2495
        if (empty($sessionList) || empty($courseList)) {
2496
            return [];
2497
        }
2498
        $sessionListToString = implode("','", $sessionList);
2499
        $courseListToString = implode("','", $courseList);
2500
2501
        $statusCondition = null;
2502
        if (isset($status) && !is_null($status)) {
2503
            $status = (int) $status;
2504
            $statusCondition = " AND status = $status";
2505
        }
2506
2507
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2508
2509
        $sql = "SELECT DISTINCT user_id
2510
                FROM $table
2511
                WHERE
2512
                    session_id IN ('$sessionListToString') AND
2513
                    c_id IN ('$courseListToString')
2514
                    $statusCondition
2515
                ";
2516
        if (!is_null($start) && !is_null($limit)) {
2517
            $start = (int) $start;
2518
            $limit = (int) $limit;
2519
            $sql .= "LIMIT $start, $limit";
2520
        }
2521
        $result = Database::query($sql);
2522
        $existingUsers = [];
2523
        while ($row = Database::fetch_array($result)) {
2524
            $existingUsers[] = $row['user_id'];
2525
        }
2526
2527
        return $existingUsers;
2528
    }
2529
2530
    /**
2531
     * Remove a list of users from a course-session.
2532
     *
2533
     * @param array $userList
2534
     * @param int   $sessionId
2535
     * @param array $courseInfo
2536
     * @param int   $status
2537
     * @param bool  $updateTotal
2538
     *
2539
     * @return bool
2540
     */
2541
    public static function removeUsersFromCourseSession(
2542
        $userList,
2543
        $sessionId,
2544
        $courseInfo,
2545
        $status = null,
2546
        $updateTotal = true
2547
    ) {
2548
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2549
        $tableSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2550
        $sessionId = (int) $sessionId;
2551
2552
        if (empty($sessionId) || empty($userList) || empty($courseInfo)) {
2553
            return false;
2554
        }
2555
2556
        $courseId = is_array($courseInfo) ? $courseInfo['real_id'] : $courseInfo;
2557
2558
        $statusCondition = null;
2559
        if (isset($status) && !is_null($status)) {
2560
            $status = (int) $status;
2561
            $statusCondition = " AND status = $status";
2562
        }
2563
2564
        foreach ($userList as $userId) {
2565
            $userId = (int) $userId;
2566
            $sql = "DELETE FROM $table
2567
                    WHERE
2568
                        session_id = $sessionId AND
2569
                        c_id = $courseId AND
2570
                        user_id = $userId
2571
                        $statusCondition
2572
                    ";
2573
            Database::query($sql);
2574
2575
            Event::addEvent(
2576
                LOG_SESSION_DELETE_USER_COURSE,
2577
                LOG_USER_ID,
2578
                $userId,
2579
                api_get_utc_datetime(),
2580
                api_get_user_id(),
2581
                $courseId,
2582
                $sessionId
2583
            );
2584
        }
2585
2586
        if ($updateTotal) {
2587
            // Count users in this session-course relation
2588
            $sql = "SELECT COUNT(user_id) as nbUsers
2589
                    FROM $table
2590
                    WHERE
2591
                        session_id = $sessionId AND
2592
                        c_id = $courseId AND
2593
                        status = ".Session::STUDENT;
2594
            $result = Database::query($sql);
2595
            [$userCount] = Database::fetch_array($result);
2596
2597
            // update the session-course relation to add the users total
2598
            $sql = "UPDATE $tableSessionCourse
2599
                    SET nbr_users = $userCount
2600
                    WHERE
2601
                        session_id = $sessionId AND
2602
                        c_id = $courseId";
2603
            Database::query($sql);
2604
        }
2605
    }
2606
2607
    /**
2608
     * Subscribe a user to an specific course inside a session.
2609
     *
2610
     * @param array  $user_list
2611
     * @param int    $session_id
2612
     * @param string $course_code
2613
     * @param int    $session_visibility
2614
     * @param bool   $removeUsersNotInList
2615
     *
2616
     * @return bool
2617
     */
2618
    public static function subscribe_users_to_session_course(
2619
        $user_list,
2620
        $session_id,
2621
        $course_code,
2622
        $session_visibility = SESSION_VISIBLE_READ_ONLY,
2623
        $removeUsersNotInList = false
2624
    ) {
2625
        if (empty($session_id) || empty($course_code)) {
2626
            return false;
2627
        }
2628
2629
        $session_id = (int) $session_id;
2630
        $session_visibility = (int) $session_visibility;
2631
        $course_code = Database::escape_string($course_code);
2632
        $courseInfo = api_get_course_info($course_code);
2633
        $courseId = $courseInfo['real_id'];
2634
        $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseInfo);
2635
        $forums = [];
2636
        if (1 === $subscribe) {
2637
            $forums = get_forums($courseId, $session_id);
2638
        }
2639
2640
        if ($removeUsersNotInList) {
2641
            $currentUsers = self::getUsersByCourseSession($session_id, $courseInfo, 0);
2642
2643
            if (!empty($user_list)) {
2644
                $userToDelete = array_diff($currentUsers, $user_list);
2645
            } else {
2646
                $userToDelete = $currentUsers;
2647
            }
2648
2649
            if (!empty($userToDelete)) {
2650
                self::removeUsersFromCourseSession(
2651
                    $userToDelete,
2652
                    $session_id,
2653
                    $courseInfo,
2654
                    0,
2655
                    true
2656
                );
2657
            }
2658
        }
2659
2660
        self::insertUsersInCourse(
2661
            $user_list,
2662
            $courseId,
2663
            $session_id,
2664
            ['visibility' => $session_visibility],
2665
            true,
2666
            true
2667
        );
2668
    }
2669
2670
    /**
2671
     * Unsubscribe user from session.
2672
     *
2673
     * @param int Session id
2674
     * @param int User id
2675
     *
2676
     * @return bool True in case of success, false in case of error
2677
     */
2678
    public static function unsubscribe_user_from_session($session_id, $user_id)
2679
    {
2680
        $session_id = (int) $session_id;
2681
        $user_id = (int) $user_id;
2682
2683
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2684
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2685
2686
        $sql = "DELETE FROM $tbl_session_rel_user
2687
                WHERE
2688
                    session_id = $session_id AND
2689
                    user_id = $user_id ";
2690
        Database::query($sql);
2691
2692
        // Update number of users
2693
        $sql = "UPDATE $tbl_session
2694
                SET nbr_users = nbr_users - 1
2695
                WHERE id = $session_id ";
2696
        Database::query($sql);
2697
2698
        Event::addEvent(
2699
            LOG_SESSION_DELETE_USER,
2700
            LOG_USER_ID,
2701
            $user_id,
2702
            api_get_utc_datetime(),
2703
            api_get_user_id(),
2704
            null,
2705
            $session_id
2706
        );
2707
2708
        // Get the list of courses related to this session
2709
        $course_list = self::get_course_list_by_session_id($session_id);
2710
        if (!empty($course_list)) {
2711
            foreach ($course_list as $course) {
2712
                self::unSubscribeUserFromCourseSession($user_id, $course['id'], $session_id);
2713
            }
2714
        }
2715
2716
        return true;
2717
    }
2718
2719
    /**
2720
     * @param int $user_id
2721
     * @param int $courseId
2722
     * @param int $session_id
2723
     */
2724
    public static function unSubscribeUserFromCourseSession($user_id, $courseId, $session_id)
2725
    {
2726
        $user_id = (int) $user_id;
2727
        $courseId = (int) $courseId;
2728
        $session_id = (int) $session_id;
2729
2730
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2731
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2732
2733
        // Delete user from course
2734
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2735
                WHERE session_id = $session_id AND c_id = $courseId AND user_id = $user_id";
2736
        $result = Database::query($sql);
2737
2738
        if (Database::affected_rows($result)) {
2739
            // Update number of users in this relation
2740
            $sql = "UPDATE $tbl_session_rel_course SET
2741
                    nbr_users = nbr_users - 1
2742
                    WHERE session_id = $session_id AND c_id = $courseId";
2743
            Database::query($sql);
2744
        }
2745
2746
        Event::addEvent(
2747
            LOG_SESSION_DELETE_USER_COURSE,
2748
            LOG_USER_ID,
2749
            $user_id,
2750
            api_get_utc_datetime(),
2751
            api_get_user_id(),
2752
            $courseId,
2753
            $session_id
2754
        );
2755
    }
2756
2757
    /**
2758
     * Subscribes courses to the given session and optionally (default)
2759
     * unsubscribe previous users.
2760
     *
2761
     * @author Carlos Vargas from existing code
2762
     *
2763
     * @param int   $sessionId
2764
     * @param array $courseList                     List of courses int ids
2765
     * @param bool  $removeExistingCoursesWithUsers Whether to unsubscribe
2766
     *                                              existing courses and users (true, default) or not (false)
2767
     * @param bool  $copyEvaluation                 from base course to session course
2768
     * @param bool  $copyCourseTeachersAsCoach
2769
     * @param bool  $importAssignments
2770
     *
2771
     * @throws Exception
2772
     *
2773
     * @return bool False on failure, true otherwise
2774
     * */
2775
    public static function add_courses_to_session(
2776
        $sessionId,
2777
        $courseList,
2778
        $removeExistingCoursesWithUsers = true,
2779
        $copyEvaluation = false,
2780
        $copyCourseTeachersAsCoach = false,
2781
        $importAssignments = false
2782
    ) {
2783
        $sessionId = (int) $sessionId;
2784
2785
        if (empty($sessionId) || empty($courseList)) {
2786
            return false;
2787
        }
2788
2789
        $session = api_get_session_entity($sessionId);
2790
2791
        if (!$session) {
2792
            return false;
2793
        }
2794
        $sessionVisibility = $session->getVisibility();
2795
2796
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
2797
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2798
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
2799
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
2800
2801
        // Get list of courses subscribed to this session
2802
        $sql = "SELECT c_id
2803
                FROM $tbl_session_rel_course
2804
                WHERE session_id = $sessionId";
2805
        $rs = Database::query($sql);
2806
        $existingCourses = Database::store_result($rs);
2807
        $nbr_courses = count($existingCourses);
2808
2809
        // Get list of users subscribed to this session
2810
        $sql = "SELECT user_id
2811
                FROM $tbl_session_rel_user
2812
                WHERE
2813
                    session_id = $sessionId AND
2814
                    relation_type = ".Session::STUDENT;
2815
        $result = Database::query($sql);
2816
        $user_list = Database::store_result($result);
2817
2818
        // Remove existing courses from the session.
2819
        if (true === $removeExistingCoursesWithUsers && !empty($existingCourses)) {
2820
            foreach ($existingCourses as $existingCourse) {
2821
                if (!in_array($existingCourse['c_id'], $courseList)) {
2822
                    $sql = "DELETE FROM $tbl_session_rel_course
2823
                            WHERE
2824
                                c_id = ".$existingCourse['c_id']." AND
2825
                                session_id = $sessionId";
2826
                    Database::query($sql);
2827
2828
                    $sql = "DELETE FROM $tbl_session_rel_course_rel_user
2829
                            WHERE
2830
                                c_id = ".$existingCourse['c_id']." AND
2831
                                session_id = $sessionId";
2832
                    Database::query($sql);
2833
2834
                    Event::addEvent(
2835
                        LOG_SESSION_DELETE_COURSE,
2836
                        LOG_COURSE_ID,
2837
                        $existingCourse['c_id'],
2838
                        api_get_utc_datetime(),
2839
                        api_get_user_id(),
2840
                        $existingCourse['c_id'],
2841
                        $sessionId
2842
                    );
2843
2844
                    CourseManager::remove_course_ranking($existingCourse['c_id']);
2845
                    $nbr_courses--;
2846
                }
2847
            }
2848
        }
2849
2850
        // Pass through the courses list we want to add to the session
2851
        foreach ($courseList as $courseId) {
2852
            $courseInfo = api_get_course_info_by_id($courseId);
2853
2854
            // If course doesn't exist continue!
2855
            if (empty($courseInfo)) {
2856
                continue;
2857
            }
2858
2859
            $exists = false;
2860
            // check if the course we want to add is already subscribed
2861
            foreach ($existingCourses as $existingCourse) {
2862
                if ($courseId == $existingCourse['c_id']) {
2863
                    $exists = true;
2864
                }
2865
            }
2866
2867
            if (!$exists) {
2868
                // Copy gradebook categories and links (from base course)
2869
                // to the new course session
2870
                if ($copyEvaluation) {
2871
                    $cats = Category::load(null, null, $courseId);
2872
                    if (!empty($cats)) {
2873
                        $sessionCategory = Category:: load(
2874
                            null,
2875
                            null,
2876
                            $courseId,
2877
                            null,
2878
                            null,
2879
                            $sessionId,
2880
                            null
2881
                        );
2882
2883
                        // @todo remove commented code
2884
                        if (empty($sessionCategory)) {
2885
                            // There is no category for this course+session, so create one
2886
                            $cat = new Category();
2887
                            $sessionName = $session->getTitle();
2888
                            $cat->set_name($courseInfo['code'].' - '.get_lang('Session').' '.$sessionName);
2889
                            $cat->set_session_id($sessionId);
2890
                            $cat->setCourseId($courseId);
2891
                            $cat->set_description(null);
2892
                            //$cat->set_user_id($stud_id);
2893
                            $cat->set_parent_id(0);
2894
                            $cat->set_weight(100);
2895
                            $cat->set_visible(0);
2896
                            $cat->set_certificate_min_score(75);
2897
                            $cat->setGenerateCertificates(1);
2898
                            $cat->setIsRequirement(1);
2899
                            $cat->add();
2900
                            $sessionGradeBookCategoryId = $cat->get_id();
2901
                        } else {
2902
                            if (!empty($sessionCategory[0])) {
2903
                                $sessionGradeBookCategoryId = $sessionCategory[0]->get_id();
2904
                            }
2905
                        }
2906
2907
                        $categoryIdList = [];
2908
                        /** @var Category $cat */
2909
                        foreach ($cats as $cat) {
2910
                            $categoryIdList[$cat->get_id()] = $cat->get_id();
2911
                        }
2912
2913
                        $newCategoryIdList = [];
2914
                        foreach ($cats as $cat) {
2915
                            $links = $cat->get_links(
2916
                                null,
2917
                                false,
2918
                                $courseId,
2919
                                $sessionId
2920
                            );
2921
2922
                            //$cat->set_session_id($sessionId);
2923
                            //$oldCategoryId = $cat->get_id();
2924
                            //$newId = $cat->add();
2925
                            //$newCategoryIdList[$oldCategoryId] = $newId;
2926
                            //$parentId = $cat->get_parent_id();
2927
2928
                            /*if (!empty($parentId)) {
2929
                                $newParentId = $newCategoryIdList[$parentId];
2930
                                $cat->set_parent_id($newParentId);
2931
                                $cat->save();
2932
                            }*/
2933
2934
                            if (!empty($links)) {
2935
                                /** @var AbstractLink $link */
2936
                                foreach ($links as $link) {
2937
                                    //$newCategoryId = $newCategoryIdList[$link->get_category_id()];
2938
                                    $link->set_category_id($sessionGradeBookCategoryId);
2939
                                    $link->add();
2940
                                }
2941
                            }
2942
2943
                            $evaluationList = $cat->get_evaluations(
2944
                                null,
2945
                                false,
2946
                                $courseId,
2947
                                $sessionId
2948
                            );
2949
2950
                            if (!empty($evaluationList)) {
2951
                                /** @var Evaluation $evaluation */
2952
                                foreach ($evaluationList as $evaluation) {
2953
                                    //$evaluationId = $newCategoryIdList[$evaluation->get_category_id()];
2954
                                    $evaluation->set_category_id($sessionGradeBookCategoryId);
2955
                                    $evaluation->add();
2956
                                }
2957
                            }
2958
                        }
2959
2960
                        // Create
2961
                        DocumentManager::generateDefaultCertificate(
2962
                            $courseInfo,
2963
                            true,
2964
                            $sessionId
2965
                        );
2966
                    }
2967
                }
2968
2969
                if ($importAssignments) {
2970
                    $repo = Container::getStudentPublicationRepository();
2971
                    $course = api_get_course_entity($courseId);
2972
                    $session = api_get_session_entity($sessionId);
2973
                    $user = api_get_user_entity();
2974
2975
                    $qb = $repo->getResourcesByCourse($course, null);
2976
                    $qb
2977
                        ->andWhere('resource.active = 1')
2978
                        ->andWhere('resource.filetype = :filetype')
2979
                        ->andWhere('resource.publicationParent IS NULL')
2980
                        ->setParameter('filetype', 'folder');
2981
2982
                    $baseAssignments = $qb->getQuery()->getResult();
2983
2984
                    foreach ($baseAssignments as $originalAssignment) {
2985
                        if (!$originalAssignment instanceof CStudentPublication) {
2986
                            continue;
2987
                        }
2988
2989
                        $newAssignment = new CStudentPublication();
2990
                        $newAssignment
2991
                            ->setTitle($originalAssignment->getTitle())
2992
                            ->setDescription($originalAssignment->getDescription() ?? '')
2993
                            ->setActive(1)
2994
                            ->setAccepted(true)
2995
                            ->setFiletype('folder')
2996
                            ->setPostGroupId(0)
2997
                            ->setSentDate(new \DateTime())
2998
                            ->setQualification($originalAssignment->getQualification())
2999
                            ->setWeight($originalAssignment->getWeight())
3000
                            ->setAllowTextAssignment($originalAssignment->getAllowTextAssignment())
3001
                            ->setUser($user)
3002
                            ->setParent($course)
3003
                            ->addCourseLink($course, $session, null);
3004
3005
                        $repo->create($newAssignment);
3006
                    }
3007
                }
3008
                // If the course isn't subscribed yet
3009
                $sql = "INSERT INTO $tbl_session_rel_course (session_id, c_id, nbr_users, position)
3010
                        VALUES ($sessionId, $courseId, 0, 0)";
3011
                Database::query($sql);
3012
3013
                Event::addEvent(
3014
                    LOG_SESSION_ADD_COURSE,
3015
                    LOG_COURSE_ID,
3016
                    $courseId,
3017
                    api_get_utc_datetime(),
3018
                    api_get_user_id(),
3019
                    $courseId,
3020
                    $sessionId
3021
                );
3022
3023
                // We add the current course in the existing courses array,
3024
                // to avoid adding another time the current course
3025
                $existingCourses[] = ['c_id' => $courseId];
3026
                $nbr_courses++;
3027
3028
                // Subscribe all the users from the session to this course inside the session
3029
                self::insertUsersInCourse(
3030
                    array_column($user_list, 'user_id'),
3031
                    $courseId,
3032
                    $sessionId,
3033
                    ['visibility' => $sessionVisibility],
3034
                    false
3035
                );
3036
            }
3037
3038
            if ($copyCourseTeachersAsCoach) {
3039
                $teachers = CourseManager::get_teacher_list_from_course_code($courseInfo['code']);
3040
                if (!empty($teachers)) {
3041
                    foreach ($teachers as $teacher) {
3042
                        self::updateCoaches(
3043
                            $sessionId,
3044
                            $courseId,
3045
                            [$teacher['user_id']],
3046
                            false
3047
                        );
3048
                    }
3049
                }
3050
            }
3051
        }
3052
3053
        $sql = "UPDATE $tbl_session SET nbr_courses = $nbr_courses WHERE id = $sessionId";
3054
        Database::query($sql);
3055
3056
        return true;
3057
    }
3058
3059
    /**
3060
     * Unsubscribe course from a session.
3061
     *
3062
     * @param int $session_id
3063
     * @param int $course_id
3064
     *
3065
     * @return bool True in case of success, false otherwise
3066
     */
3067
    public static function unsubscribe_course_from_session($session_id, $course_id)
3068
    {
3069
        $session_id = (int) $session_id;
3070
        $course_id = (int) $course_id;
3071
3072
        if (empty($course_id) || empty($session_id)) {
3073
            return false;
3074
        }
3075
3076
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3077
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3078
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3079
3080
        // Unsubscribe course.
3081
        $sql = "DELETE FROM $tbl_session_rel_course
3082
                WHERE c_id = $course_id AND session_id = $session_id";
3083
        $result = Database::query($sql);
3084
        $nb_affected = Database::affected_rows($result);
3085
3086
        $sql = "DELETE FROM $tbl_session_rel_course_rel_user
3087
                WHERE c_id = $course_id AND session_id = $session_id";
3088
        Database::query($sql);
3089
3090
        Event::addEvent(
3091
            LOG_SESSION_DELETE_COURSE,
3092
            LOG_COURSE_ID,
3093
            $course_id,
3094
            api_get_utc_datetime(),
3095
            api_get_user_id(),
3096
            $course_id,
3097
            $session_id
3098
        );
3099
3100
        if ($nb_affected > 0) {
3101
            // Update number of courses in the session
3102
            $sql = "UPDATE $tbl_session SET nbr_courses= nbr_courses - $nb_affected
3103
                    WHERE id = $session_id";
3104
            Database::query($sql);
3105
3106
            return true;
3107
        }
3108
3109
        return false;
3110
    }
3111
3112
    /**
3113
     * Creates a new extra field for a given session.
3114
     *
3115
     * @param string $variable    Field's internal variable name
3116
     * @param int    $fieldType   Field's type
3117
     * @param string $displayText Field's language var name
3118
     * @param string $default     Field's default value
3119
     *
3120
     * @return int new extra field id
3121
     */
3122
    public static function create_session_extra_field(
3123
        $variable,
3124
        $valueType,
3125
        $displayText,
3126
        $default = ''
3127
    ) {
3128
        $extraField = new ExtraFieldModel('session');
3129
        $params = [
3130
            'variable' => $variable,
3131
            'value_type' => $valueType,
3132
            'display_text' => $displayText,
3133
            'default_value' => $default,
3134
        ];
3135
3136
        return $extraField->save($params);
3137
    }
3138
3139
    /**
3140
     * Update an extra field value for a given session.
3141
     *
3142
     * @param int    $sessionId Session ID
3143
     * @param string $variable  Field variable name
3144
     * @param string $value     Optional. Default field value
3145
     *
3146
     * @return bool|int An integer when register a new extra field. And boolean when update the extrafield
3147
     */
3148
    public static function update_session_extra_field_value($sessionId, $variable, $value = '')
3149
    {
3150
        $extraFieldValue = new ExtraFieldValue('session');
3151
        $params = [
3152
            'item_id' => $sessionId,
3153
            'variable' => $variable,
3154
            'value' => $value,
3155
        ];
3156
3157
        return $extraFieldValue->save($params);
3158
    }
3159
3160
    /**
3161
     * Checks the relationship between a session and a course.
3162
     *
3163
     * @param int $session_id
3164
     * @param int $courseId
3165
     *
3166
     * @return bool returns TRUE if the session and the course are related, FALSE otherwise
3167
     * */
3168
    public static function relation_session_course_exist($session_id, $courseId)
3169
    {
3170
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3171
        $return_value = false;
3172
        $sql = "SELECT c_id FROM $tbl_session_course
3173
                WHERE
3174
                  session_id = ".intval($session_id)." AND
3175
                  c_id = ".intval($courseId);
3176
        $result = Database::query($sql);
3177
        $num = Database::num_rows($result);
3178
        if ($num > 0) {
3179
            $return_value = true;
3180
        }
3181
3182
        return $return_value;
3183
    }
3184
3185
    /**
3186
     * Get the session information by name.
3187
     *
3188
     * @param string $name
3189
     *
3190
     * @return mixed false if the session does not exist, array if the session exist
3191
     */
3192
    public static function get_session_by_name($name)
3193
    {
3194
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3195
        $name = Database::escape_string(trim($name));
3196
        if (empty($name)) {
3197
            return false;
3198
        }
3199
3200
        $sql = 'SELECT *
3201
		        FROM '.$tbl_session.'
3202
		        WHERE title = "'.$name.'"';
3203
        $result = Database::query($sql);
3204
        $num = Database::num_rows($result);
3205
        if ($num > 0) {
3206
            return Database::fetch_array($result);
3207
        } else {
3208
            return false;
3209
        }
3210
    }
3211
3212
    /**
3213
     * @param int $sessionId
3214
     * @param int $name
3215
     *
3216
     * @return bool
3217
     */
3218
    public static function sessionNameExistBesidesMySession($sessionId, $name)
3219
    {
3220
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
3221
        $name = Database::escape_string(trim($name));
3222
        $sessionId = (int) $sessionId;
3223
3224
        if (empty($name)) {
3225
            return false;
3226
        }
3227
3228
        $sql = "SELECT *
3229
		        FROM $table
3230
		        WHERE title = '$name' AND id <> $sessionId ";
3231
        $result = Database::query($sql);
3232
        $num = Database::num_rows($result);
3233
        if ($num > 0) {
3234
            return true;
3235
        }
3236
3237
        return false;
3238
    }
3239
3240
    /**
3241
     * Create a session category.
3242
     *
3243
     * @author Jhon Hinojosa <[email protected]>, from existing code
3244
     *
3245
     * @param string        name
3246
     * @param int        year_start
3247
     * @param int        month_start
3248
     * @param int        day_start
3249
     * @param int        year_end
3250
     * @param int        month_end
3251
     * @param int        day_end
3252
     *
3253
     * @return int session ID
3254
     * */
3255
    public static function create_category_session(
3256
        $sname,
3257
        $syear_start,
3258
        $smonth_start,
3259
        $sday_start,
3260
        $syear_end,
3261
        $smonth_end,
3262
        $sday_end
3263
    ) {
3264
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3265
        $name = html_filter(trim($sname));
3266
        $year_start = intval($syear_start);
3267
        $month_start = intval($smonth_start);
3268
        $day_start = intval($sday_start);
3269
        $year_end = intval($syear_end);
3270
        $month_end = intval($smonth_end);
3271
        $day_end = intval($sday_end);
3272
3273
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3274
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3275
3276
        if (empty($name)) {
3277
            $msg = get_lang('Please give a name to the sessions category');
3278
3279
            return $msg;
3280
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3281
            $msg = get_lang('Invalid start date was given.');
3282
3283
            return $msg;
3284
        } elseif (!$month_end && !$day_end && !$year_end) {
3285
            $date_end = '';
3286
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3287
            $msg = get_lang('Invalid end date was given.');
3288
3289
            return $msg;
3290
        } elseif ($date_start >= $date_end) {
3291
            $msg = get_lang('The first date should be before the end date');
3292
3293
            return $msg;
3294
        }
3295
3296
        $access_url_id = api_get_current_access_url_id();
3297
        $params = [
3298
            'title' => $name,
3299
            'date_start' => $date_start,
3300
            'access_url_id' => $access_url_id,
3301
        ];
3302
3303
        if (!empty($date_end)) {
3304
            $params['date_end'] = $date_end;
3305
        }
3306
3307
        $id = Database::insert($tbl_session_category, $params);
3308
3309
        // Add event to system log
3310
        $user_id = api_get_user_id();
3311
        Event::addEvent(
3312
            LOG_SESSION_CATEGORY_CREATE,
3313
            LOG_SESSION_CATEGORY_ID,
3314
            $id,
3315
            api_get_utc_datetime(),
3316
            $user_id
3317
        );
3318
3319
        return $id;
3320
    }
3321
3322
    /**
3323
     * Edit a sessions category.
3324
     *
3325
     * @author Jhon Hinojosa <[email protected]>,from existing code
3326
     *
3327
     * @param int        id
3328
     * @param string        name
3329
     * @param int        year_start
3330
     * @param int        month_start
3331
     * @param int        day_start
3332
     * @param int        year_end
3333
     * @param int        month_end
3334
     * @param int        day_end
3335
     *
3336
     * @return bool
3337
     *              The parameter id is a primary key
3338
     * */
3339
    public static function edit_category_session(
3340
        $id,
3341
        $sname,
3342
        $syear_start,
3343
        $smonth_start,
3344
        $sday_start,
3345
        $syear_end,
3346
        $smonth_end,
3347
        $sday_end
3348
    ) {
3349
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3350
        $name = html_filter(trim($sname));
3351
        $year_start = intval($syear_start);
3352
        $month_start = intval($smonth_start);
3353
        $day_start = intval($sday_start);
3354
        $year_end = intval($syear_end);
3355
        $month_end = intval($smonth_end);
3356
        $day_end = intval($sday_end);
3357
        $id = intval($id);
3358
        $date_start = "$year_start-".(($month_start < 10) ? "0$month_start" : $month_start)."-".(($day_start < 10) ? "0$day_start" : $day_start);
3359
        $date_end = "$year_end-".(($month_end < 10) ? "0$month_end" : $month_end)."-".(($day_end < 10) ? "0$day_end" : $day_end);
3360
3361
        if (empty($name)) {
3362
            $msg = get_lang('Please give a name to the sessions category');
3363
3364
            return $msg;
3365
        } elseif (!$month_start || !$day_start || !$year_start || !checkdate($month_start, $day_start, $year_start)) {
3366
            $msg = get_lang('Invalid start date was given.');
3367
3368
            return $msg;
3369
        } elseif (!$month_end && !$day_end && !$year_end) {
3370
            $date_end = null;
3371
        } elseif (!$month_end || !$day_end || !$year_end || !checkdate($month_end, $day_end, $year_end)) {
3372
            $msg = get_lang('Invalid end date was given.');
3373
3374
            return $msg;
3375
        } elseif ($date_start >= $date_end) {
3376
            $msg = get_lang('The first date should be before the end date');
3377
3378
            return $msg;
3379
        }
3380
        if (null != $date_end) {
3381
            $sql = "UPDATE $tbl_session_category
3382
                    SET
3383
                        title = '".Database::escape_string($name)."',
3384
                        date_start = '$date_start' ,
3385
                        date_end = '$date_end'
3386
                    WHERE id= $id";
3387
        } else {
3388
            $sql = "UPDATE $tbl_session_category SET
3389
                        title = '".Database::escape_string($name)."',
3390
                        date_start = '$date_start',
3391
                        date_end = NULL
3392
                    WHERE id= $id";
3393
        }
3394
        $result = Database::query($sql);
3395
3396
        return $result ? true : false;
3397
    }
3398
3399
    /**
3400
     * Delete sessions categories.
3401
     *
3402
     * @param array|int $categoryId
3403
     * @param bool      $deleteSessions Optional. Include delete session.
3404
     * @param bool      $fromWs         Optional. True if the function is called by a webservice, false otherwise.
3405
     *
3406
     * @return bool Nothing, or false on error
3407
     *              The parameters is a array to delete sessions
3408
     *
3409
     * @author Jhon Hinojosa <[email protected]>, from existing code
3410
     */
3411
    public static function delete_session_category($categoryId, $deleteSessions = false, $fromWs = false)
3412
    {
3413
        $tblSessionCategory = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3414
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
3415
3416
        if (is_array($categoryId)) {
3417
            $categoryId = array_map('intval', $categoryId);
3418
        } else {
3419
            $categoryId = [(int) $categoryId];
3420
        }
3421
3422
        $categoryId = implode(', ', $categoryId);
3423
3424
        if ($deleteSessions) {
3425
            $sql = "SELECT id FROM $tblSession WHERE session_category_id IN ($categoryId)";
3426
            $result = Database::query($sql);
3427
            while ($rows = Database::fetch_array($result)) {
3428
                $sessionId = $rows['id'];
3429
                self::delete($sessionId, $fromWs);
3430
            }
3431
        } else {
3432
            $sql = "UPDATE $tblSession SET session_category_id = NULL WHERE session_category_id IN ($categoryId)";
3433
            Database::query($sql);
3434
        }
3435
3436
        $sql = "DELETE FROM $tblSessionCategory WHERE id IN ($categoryId)";
3437
        Database::query($sql);
3438
3439
        // Add event to system log
3440
        Event::addEvent(
3441
            LOG_SESSION_CATEGORY_DELETE,
3442
            LOG_SESSION_CATEGORY_ID,
3443
            $categoryId,
3444
            api_get_utc_datetime(),
3445
            api_get_user_id()
3446
        );
3447
3448
        return true;
3449
    }
3450
3451
    /**
3452
     * Get a list of sessions of which the given conditions match with an = 'cond'.
3453
     *
3454
     * @param array $conditions          a list of condition example :
3455
     *                                   array('status' => STUDENT) or
3456
     *                                   array('s.title' => array('operator' => 'LIKE', value = '%$needle%'))
3457
     * @param array $order_by            a list of fields on which sort
3458
     * @param int   $urlId
3459
     * @param array $onlyThisSessionList
3460
     *
3461
     * @return array an array with all sessions of the platform
3462
     *
3463
     * @todo   optional course code parameter, optional sorting parameters...
3464
     */
3465
    public static function get_sessions_list(
3466
        $conditions = [],
3467
        $order_by = [],
3468
        $from = null,
3469
        $to = null,
3470
        $urlId = 0,
3471
        $onlyThisSessionList = []
3472
    ) {
3473
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
3474
        $session_category_table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3475
        $user_table = Database::get_main_table(TABLE_MAIN_USER);
3476
        $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3477
        $session_course_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
3478
        $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
3479
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
3480
        $return_array = [];
3481
3482
        $sql_query = " SELECT
3483
                    DISTINCT(s.id),
3484
                    s.title,
3485
                    s.nbr_courses,
3486
                    s.access_start_date,
3487
                    s.access_end_date,
3488
                    sc.title as category_name,
3489
                    s.promotion_id
3490
				FROM $session_table s
3491
				INNER JOIN $table_access_url_rel_session ar ON ar.session_id = s.id
3492
				LEFT JOIN  $session_category_table sc ON s.session_category_id = sc.id
3493
				LEFT JOIN $session_course_table sco ON (sco.session_id = s.id)
3494
				INNER JOIN $course_table c ON sco.c_id = c.id
3495
				WHERE ar.access_url_id = $urlId ";
3496
3497
        $availableFields = [
3498
            's.id',
3499
            's.title',
3500
            'c.id',
3501
        ];
3502
3503
        $availableOperator = [
3504
            'like',
3505
            '>=',
3506
            '<=',
3507
            '=',
3508
        ];
3509
3510
        if (count($conditions) > 0) {
3511
            foreach ($conditions as $field => $options) {
3512
                $operator = strtolower($options['operator']);
3513
                $value = Database::escape_string($options['value']);
3514
                if (in_array($field, $availableFields) && in_array($operator, $availableOperator)) {
3515
                    $sql_query .= ' AND '.$field." $operator '".$value."'";
3516
                }
3517
            }
3518
        }
3519
3520
        if (!empty($onlyThisSessionList)) {
3521
            $onlyThisSessionList = array_map('intval', $onlyThisSessionList);
3522
            $onlyThisSessionList = implode("','", $onlyThisSessionList);
3523
            $sql_query .= " AND s.id IN ('$onlyThisSessionList') ";
3524
        }
3525
3526
        $orderAvailableList = ['title'];
3527
        if (count($order_by) > 0) {
3528
            $order = null;
3529
            $direction = null;
3530
            if (isset($order_by[0]) && in_array($order_by[0], $orderAvailableList)) {
3531
                $order = $order_by[0];
3532
            }
3533
            if (isset($order_by[1]) && in_array(strtolower($order_by[1]), ['desc', 'asc'])) {
3534
                $direction = $order_by[1];
3535
            }
3536
3537
            if (!empty($order)) {
3538
                $sql_query .= " ORDER BY $order $direction ";
3539
            }
3540
        }
3541
3542
        if (!is_null($from) && !is_null($to)) {
3543
            $to = (int) $to;
3544
            $from = (int) $from;
3545
            $sql_query .= "LIMIT $from, $to";
3546
        }
3547
3548
        $sql_result = Database::query($sql_query);
3549
        if (Database::num_rows($sql_result) > 0) {
3550
            while ($result = Database::fetch_array($sql_result)) {
3551
                $return_array[$result['id']] = $result;
3552
            }
3553
        }
3554
3555
        return $return_array;
3556
    }
3557
3558
    /**
3559
     * Get the session category information by id.
3560
     *
3561
     * @param string session category ID
3562
     *
3563
     * @return mixed false if the session category does not exist, array if the session category exists
3564
     */
3565
    public static function get_session_category($id)
3566
    {
3567
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3568
        $id = (int) $id;
3569
        $sql = "SELECT id, title, date_start, date_end
3570
                FROM $table
3571
                WHERE id= $id";
3572
        $result = Database::query($sql);
3573
        $num = Database::num_rows($result);
3574
        if ($num > 0) {
3575
            return Database::fetch_array($result);
3576
        } else {
3577
            return false;
3578
        }
3579
    }
3580
3581
    /**
3582
     * Get Hot Sessions (limit 8).
3583
     *
3584
     * @return array with sessions
3585
     */
3586
    public static function getHotSessions()
3587
    {
3588
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3589
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3590
        $tbl_users = Database::get_main_table(TABLE_MAIN_USER);
3591
        $tbl_extra_fields = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3592
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3593
        $tbl_lp = Database::get_course_table(TABLE_LP_MAIN);
3594
3595
        $extraField = new ExtraFieldModel('session');
3596
        $field = $extraField->get_handler_field_info_by_field_variable('image');
3597
3598
        $sql = "SELECT
3599
                s.id,
3600
                s.title,
3601
                s.session_category_id,
3602
                c.title as category_name,
3603
                s.description,
3604
                s.nbr_users as users,
3605
				(SELECT COUNT(*) FROM $tbl_lp WHERE session_id = s.id) as lessons ";
3606
        if (false !== $field) {
3607
            $fieldId = $field['id'];
3608
            $sql .= ",(SELECT value FROM $tbl_extra_fields WHERE field_id = $fieldId AND item_id = s.id) as image ";
3609
        }
3610
        $sql .= " FROM $tbl_session s
3611
                LEFT JOIN $tbl_session_category c
3612
                    ON s.session_category_id = c.id
3613
                ORDER BY 8 DESC
3614
                LIMIT 8";
3615
        $result = Database::query($sql);
3616
3617
        if (Database::num_rows($result) > 0) {
3618
            $plugin = BuyCoursesPlugin::create();
3619
            $checker = $plugin->isEnabled();
3620
            $sessions = [];
3621
            while ($row = Database::fetch_assoc($result)) {
3622
                if (!isset($row['image'])) {
3623
                    $row['image'] = '';
3624
                }
3625
                $row['on_sale'] = '';
3626
                if ($checker) {
3627
                    $row['on_sale'] = $plugin->getItemByProduct(
3628
                        $row['id'],
3629
                        BuyCoursesPlugin::PRODUCT_TYPE_SESSION
3630
                    );
3631
                }
3632
                $sessions[] = $row;
3633
            }
3634
3635
            return $sessions;
3636
        }
3637
3638
        return false;
3639
    }
3640
3641
    /**
3642
     * Get all session categories (filter by access_url_id).
3643
     *
3644
     * @return mixed false if the session category does not exist, array if the session category exists
3645
     */
3646
    public static function get_all_session_category()
3647
    {
3648
        $table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
3649
        $id = api_get_current_access_url_id();
3650
        $sql = 'SELECT * FROM '.$table.'
3651
                WHERE access_url_id = '.$id.'
3652
                ORDER BY title ASC';
3653
        $result = Database::query($sql);
3654
        if (Database::num_rows($result) > 0) {
3655
            $data = Database::store_result($result, 'ASSOC');
3656
3657
            return $data;
3658
        }
3659
3660
        return false;
3661
    }
3662
3663
    /**
3664
     * Assign a coach to course in session with status = 2.
3665
     *
3666
     * @param int  $userId
3667
     * @param int  $sessionId
3668
     * @param int  $courseId
3669
     * @param bool $noCoach   optional, if is true the user don't be a coach now,
3670
     *                        otherwise it'll assign a coach
3671
     *
3672
     * @return bool true if there are affected rows, otherwise false
3673
     */
3674
    public static function set_coach_to_course_session(
3675
        $userId,
3676
        $sessionId = 0,
3677
        $courseId = 0,
3678
        $noCoach = false
3679
    ) {
3680
        $userId = (int) $userId;
3681
3682
        $sessionId = !empty($sessionId) ? (int) $sessionId : api_get_session_id();
3683
        $courseId = !empty($courseId) ? (int) $courseId : api_get_course_id();
3684
3685
        if (empty($sessionId) || empty($courseId) || empty($userId)) {
3686
            return false;
3687
        }
3688
3689
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
3690
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3691
3692
        $user = api_get_user_entity($userId);
3693
3694
        if (!$user->isTeacher()) {
3695
            return false;
3696
        }
3697
3698
        if ($noCoach) {
3699
            // Delete the course-specific coach record
3700
            $sql = "DELETE FROM $tblSessionRelCourseRelUser
3701
                WHERE
3702
                    session_id = $sessionId AND
3703
                    c_id = $courseId AND
3704
                    user_id = $userId AND
3705
                    status = ".Session::COURSE_COACH;
3706
            $result = Database::query($sql);
3707
3708
            // Check if the user is still a coach for any course in this session
3709
            $sql = "SELECT COUNT(*) AS count FROM $tblSessionRelCourseRelUser
3710
                WHERE
3711
                    session_id = $sessionId AND
3712
                    user_id = $userId AND
3713
                    status = ".Session::COURSE_COACH;
3714
            $res = Database::query($sql);
3715
            $resultRow = Database::fetch_assoc($res);
3716
3717
            // If the user is no longer a coach for any course in this session, remove the session relationship
3718
            if (0 === (int) $resultRow['count']) {
3719
                $sql = "DELETE FROM $tblSessionRelUser
3720
                    WHERE
3721
                        session_id = $sessionId AND
3722
                        user_id = $userId AND
3723
                        relation_type = ".Session::COURSE_COACH;
3724
                Database::query($sql);
3725
            }
3726
3727
            return Database::affected_rows($result) > 0;
3728
        }
3729
3730
        // Assign user as a coach to course
3731
        // First check if the user is registered to the course
3732
        $sql = "SELECT user_id FROM $tblSessionRelCourseRelUser
3733
                WHERE
3734
                    session_id = $sessionId AND
3735
                    c_id = $courseId AND
3736
                    user_id = $userId";
3737
        $rs_check = Database::query($sql);
3738
3739
        // Then update or insert.
3740
        if (Database::num_rows($rs_check) > 0) {
3741
            $sql = "UPDATE $tblSessionRelCourseRelUser
3742
                    SET status = ".Session::COURSE_COACH."
3743
                    WHERE
3744
                        session_id = $sessionId AND
3745
                        c_id = $courseId AND
3746
                        user_id = $userId ";
3747
            $result = Database::query($sql);
3748
3749
            return Database::affected_rows($result) > 0;
3750
        }
3751
3752
        $em = Container::getEntityManager();
3753
        $em->clear();
3754
        $session = $em->getRepository(Session::class)->find($sessionId);
3755
        $course = api_get_course_entity($courseId);
3756
        if (!$session->hasCourse($course)) {
3757
            $session->addCourse($course);
3758
        }
3759
        $sessionRepo = Container::getSessionRepository();
3760
        $sessionRepo->addUserInCourse(
3761
            Session::COURSE_COACH,
3762
            api_get_user_entity($userId),
3763
            $course,
3764
            $session
3765
        );
3766
3767
        $sessionRepo->update($session);
3768
3769
        return true;
3770
    }
3771
3772
    /**
3773
     * Subscribes sessions to human resource manager (Dashboard feature).
3774
     *
3775
     * @param array $userInfo               Human Resource Manager info
3776
     * @param array $sessions_list          Sessions id
3777
     * @param bool  $sendEmail
3778
     * @param bool  $removeSessionsFromUser
3779
     *
3780
     * @return int
3781
     * */
3782
    public static function subscribeSessionsToDrh(
3783
        $userInfo,
3784
        $sessions_list,
3785
        $sendEmail = false,
3786
        $removeSessionsFromUser = true
3787
    ) {
3788
        // Database Table Definitions
3789
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3790
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3791
3792
        if (empty($userInfo)) {
3793
            return 0;
3794
        }
3795
3796
        $userId = $userInfo['user_id'];
3797
        $user = api_get_user_entity();
3798
3799
        // Only subscribe DRH users.
3800
        $rolesAllowed = [
3801
            DRH,
3802
            SESSIONADMIN,
3803
            PLATFORM_ADMIN,
3804
            COURSE_TUTOR,
3805
        ];
3806
        $isAdmin = api_is_platform_admin_by_id($userInfo['user_id']);
3807
        if (!$isAdmin && !in_array($userInfo['status'], $rolesAllowed)) {
3808
            return 0;
3809
        }
3810
3811
        $affected_rows = 0;
3812
        // Deleting assigned sessions to hrm_id.
3813
        if ($removeSessionsFromUser) {
3814
            if (api_is_multiple_url_enabled()) {
3815
                $sql = "SELECT s.session_id
3816
                        FROM $tbl_session_rel_user s
3817
                        INNER JOIN $tbl_session_rel_access_url a
3818
                        ON (a.session_id = s.session_id)
3819
                        WHERE
3820
                            s.user_id = $userId AND
3821
                            relation_type = ".Session::DRH." AND
3822
                            access_url_id = ".api_get_current_access_url_id();
3823
            } else {
3824
                $sql = "SELECT s.session_id
3825
                        FROM $tbl_session_rel_user s
3826
                        WHERE user_id = $userId AND relation_type=".Session::DRH;
3827
            }
3828
            $result = Database::query($sql);
3829
3830
            if (Database::num_rows($result) > 0) {
3831
                while ($row = Database::fetch_array($result)) {
3832
                    $sql = "DELETE FROM $tbl_session_rel_user
3833
                            WHERE
3834
                                session_id = {$row['session_id']} AND
3835
                                user_id = $userId AND
3836
                                relation_type =".Session::DRH;
3837
                    Database::query($sql);
3838
                }
3839
            }
3840
        }
3841
3842
        // Inserting new sessions list.
3843
        if (!empty($sessions_list) && is_array($sessions_list)) {
3844
            foreach ($sessions_list as $session_id) {
3845
                $session = api_get_session_entity($session_id);
3846
3847
                if (!$session->hasUserInSession($user, Session::DRH)) {
3848
                    $session->addUserInSession(Session::DRH, $user);
3849
3850
                    $affected_rows++;
3851
                }
3852
            }
3853
        }
3854
3855
        return $affected_rows;
3856
    }
3857
3858
    /**
3859
     * @param int $sessionId
3860
     *
3861
     * @return array
3862
     */
3863
    public static function getDrhUsersInSession($sessionId)
3864
    {
3865
        return self::get_users_by_session($sessionId, Session::DRH);
3866
    }
3867
3868
    /**
3869
     * @param int $userId
3870
     * @param int $sessionId
3871
     *
3872
     * @return array
3873
     */
3874
    public static function getSessionFollowedByDrh($userId, $sessionId)
3875
    {
3876
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3877
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
3878
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3879
3880
        $userId = (int) $userId;
3881
        $sessionId = (int) $sessionId;
3882
3883
        $select = " SELECT * ";
3884
        if (api_is_multiple_url_enabled()) {
3885
            $sql = " $select FROM $tbl_session s
3886
                    INNER JOIN $tbl_session_rel_user sru ON (sru.session_id = s.id)
3887
                    LEFT JOIN $tbl_session_rel_access_url a ON (s.id = a.session_id)
3888
                    WHERE
3889
                        sru.user_id = '$userId' AND
3890
                        sru.session_id = '$sessionId' AND
3891
                        sru.relation_type = '".Session::DRH."' AND
3892
                        access_url_id = ".api_get_current_access_url_id()."
3893
                    ";
3894
        } else {
3895
            $sql = "$select FROM $tbl_session s
3896
                     INNER JOIN $tbl_session_rel_user sru
3897
                     ON
3898
                        sru.session_id = s.id AND
3899
                        sru.user_id = '$userId' AND
3900
                        sru.session_id = '$sessionId' AND
3901
                        sru.relation_type = '".Session::DRH."'
3902
                    ";
3903
        }
3904
3905
        $result = Database::query($sql);
3906
        if (Database::num_rows($result)) {
3907
            $row = Database::fetch_assoc($result);
3908
            $row['course_list'] = self::get_course_list_by_session_id($sessionId);
3909
3910
            return $row;
3911
        }
3912
3913
        return [];
3914
    }
3915
3916
    /**
3917
     * Get sessions followed by human resources manager.
3918
     *
3919
     * @param int    $userId
3920
     * @param int    $start
3921
     * @param int    $limit
3922
     * @param bool   $getCount
3923
     * @param bool   $getOnlySessionId
3924
     * @param bool   $getSql
3925
     * @param string $orderCondition
3926
     * @param string $keyword
3927
     * @param string $description
3928
     * @param array  $options
3929
     *
3930
     * @return array sessions
3931
     */
3932
    public static function get_sessions_followed_by_drh(
3933
        $userId,
3934
        $start = null,
3935
        $limit = null,
3936
        $getCount = false,
3937
        $getOnlySessionId = false,
3938
        $getSql = false,
3939
        $orderCondition = null,
3940
        $keyword = '',
3941
        $description = '',
3942
        $options = []
3943
    ) {
3944
        return self::getSessionsFollowedByUser(
3945
            $userId,
3946
            DRH,
3947
            $start,
3948
            $limit,
3949
            $getCount,
3950
            $getOnlySessionId,
3951
            $getSql,
3952
            $orderCondition,
3953
            $keyword,
3954
            $description,
3955
            $options
3956
        );
3957
    }
3958
3959
    /**
3960
     * Get sessions followed by human resources manager.
3961
     *
3962
     * @param int    $userId
3963
     * @param int    $status           DRH Optional
3964
     * @param int    $start
3965
     * @param int    $limit
3966
     * @param bool   $getCount
3967
     * @param bool   $getOnlySessionId
3968
     * @param bool   $getSql
3969
     * @param string $orderCondition
3970
     * @param string $keyword
3971
     * @param string $description
3972
     * @param array  $options
3973
     *
3974
     * @return array|string sessions
3975
     */
3976
    public static function getSessionsFollowedByUser(
3977
        $userId,
3978
        $status = null,
3979
        $start = null,
3980
        $limit = null,
3981
        $getCount = false,
3982
        $getOnlySessionId = false,
3983
        $getSql = false,
3984
        $orderCondition = null,
3985
        $keyword = '',
3986
        $description = '',
3987
        $options = []
3988
    ) {
3989
        // Database Table Definitions
3990
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
3991
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
3992
3993
        $extraFieldModel = new ExtraFieldModel('session');
3994
        $conditions = $extraFieldModel->parseConditions($options);
3995
        $sqlInjectJoins = $conditions['inject_joins'];
3996
        $extraFieldsConditions = $conditions['where'];
3997
        $sqlInjectWhere = $conditions['inject_where'];
3998
        $injectExtraFields = $conditions['inject_extra_fields'];
3999
4000
        if (!empty($injectExtraFields)) {
4001
            $injectExtraFields = ' , '.$injectExtraFields.' s.id';
4002
        }
4003
4004
        $userId = (int) $userId;
4005
        $user = api_get_user_entity($userId);
4006
4007
        $select = ' SELECT DISTINCT * '.$injectExtraFields;
4008
        if ($getCount) {
4009
            $select = ' SELECT count(DISTINCT(s.id)) as count ';
4010
        }
4011
4012
        if ($getOnlySessionId) {
4013
            $select = ' SELECT DISTINCT(s.id) ';
4014
        }
4015
4016
        $limitCondition = null;
4017
        if (!is_null($start) && !is_null($limit)) {
4018
            $limitCondition = " LIMIT ".intval($start).", ".intval($limit);
4019
        }
4020
4021
        if (empty($orderCondition)) {
4022
            $orderCondition = ' ORDER BY s.title ';
4023
        }
4024
4025
        $whereConditions = null;
4026
4027
        switch ($status) {
4028
            case DRH:
4029
                $sessionsQuery = array_map(
4030
                    fn(Session $session) => $session->getId(),
4031
                    $user->getDRHSessions()
4032
                );
4033
                break;
4034
            case COURSEMANAGER:
4035
                $coachSessions = array_map(
4036
                    fn(Session $session) => $session->getId(),
4037
                    $user->getSessionsByStatusInCourseSubscription(Session::COURSE_COACH)->getValues()
4038
                );
4039
                $generalCoachSessions = array_map(
4040
                    fn(Session $session) => $session->getId(),
4041
                    $user->getSessionsAsGeneralCoach()
4042
                );
4043
4044
                $sessionsQuery = array_merge($coachSessions, $generalCoachSessions);
4045
                break;
4046
            case SESSIONADMIN:
4047
                $sessionsQuery = array_map(
4048
                    fn(Session $session) => $session->getId(),
4049
                    $user->getSessionsAsAdmin()
4050
                );
4051
                break;
4052
            default:
4053
                $sessionsQuery = array_map(
4054
                    fn(Session $session) => $session->getId(),
4055
                    $user->getSessionsAsStudent()
4056
                );
4057
                break;
4058
        }
4059
4060
        $keywordCondition = '';
4061
        if (!empty($keyword)) {
4062
            $keyword = Database::escape_string($keyword);
4063
            $keywordCondition = " AND (s.title LIKE '%$keyword%' ) ";
4064
            if (!empty($description)) {
4065
                $description = Database::escape_string($description);
4066
                $keywordCondition = " AND (s.title LIKE '%$keyword%' OR s.description LIKE '%$description%' ) ";
4067
            }
4068
        }
4069
4070
        $whereConditions .= $keywordCondition;
4071
        $subQuery = !empty($sessionsQuery) ? (' AND s.id IN ('.implode(',', $sessionsQuery).')') : '';
4072
4073
        $sql = " $select
4074
                FROM $tbl_session s
4075
                INNER JOIN $tbl_session_rel_access_url a
4076
                ON (s.id = a.session_id)
4077
                $sqlInjectJoins
4078
                WHERE
4079
                    access_url_id = ".api_get_current_access_url_id()."
4080
                    $subQuery
4081
                    $whereConditions
4082
                    $extraFieldsConditions
4083
                    $sqlInjectWhere
4084
                    $orderCondition
4085
                    $limitCondition";
4086
4087
        if ($getSql) {
4088
            return $sql;
4089
        }
4090
        $result = Database::query($sql);
4091
4092
        if ($getCount) {
4093
            $row = Database::fetch_array($result);
4094
            if ($row) {
4095
                return (int) $row['count'];
4096
            }
4097
4098
            return 0;
4099
        }
4100
4101
        $sessions = [];
4102
        if (Database::num_rows($result) > 0) {
4103
            $imgPath = Display::return_icon(
4104
                'session_default_small.png',
4105
                null,
4106
                [],
4107
                ICON_SIZE_SMALL,
4108
                false,
4109
                true
4110
            );
4111
4112
            $extraFieldValue = new ExtraFieldValue('session');
4113
            while ($row = Database::fetch_array($result)) {
4114
                if ($getOnlySessionId) {
4115
                    $sessions[$row['id']] = $row;
4116
                    continue;
4117
                }
4118
4119
                $extraFieldImage = $extraFieldValue->get_values_by_handler_and_field_variable($row['id'], 'image');
4120
                $image = $imgPath;
4121
                if (!empty($extraFieldImage) && isset($extraFieldImage['url'])) {
4122
                    $image = $extraFieldImage['url'];
4123
                }
4124
                $row['image'] = $image;
4125
                if ('0000-00-00 00:00:00' === $row['display_start_date'] || '0000-00-00' === $row['display_start_date']) {
4126
                    $row['display_start_date'] = null;
4127
                }
4128
4129
                if ('0000-00-00 00:00:00' === $row['display_end_date'] || '0000-00-00' === $row['display_end_date']) {
4130
                    $row['display_end_date'] = null;
4131
                }
4132
4133
                if ('0000-00-00 00:00:00' === $row['access_start_date'] || '0000-00-00' === $row['access_start_date']) {
4134
                    $row['access_start_date'] = null;
4135
                }
4136
4137
                if ('0000-00-00 00:00:00' === $row['access_end_date'] || '0000-00-00' === $row['access_end_date']) {
4138
                    $row['access_end_date'] = null;
4139
                }
4140
4141
                if ('0000-00-00 00:00:00' === $row['coach_access_start_date'] ||
4142
                    '0000-00-00' === $row['coach_access_start_date']
4143
                ) {
4144
                    $row['coach_access_start_date'] = null;
4145
                }
4146
4147
                if ('0000-00-00 00:00:00' === $row['coach_access_end_date'] ||
4148
                    '0000-00-00' === $row['coach_access_end_date']
4149
                ) {
4150
                    $row['coach_access_end_date'] = null;
4151
                }
4152
4153
                $sessions[$row['id']] = $row;
4154
            }
4155
        }
4156
4157
        return $sessions;
4158
    }
4159
4160
    /**
4161
     * Gets the list (or the count) of courses by session filtered by access_url.
4162
     *
4163
     * @param int    $session_id  The session id
4164
     * @param string $course_name The course code
4165
     * @param string $orderBy     Field to order the data
4166
     * @param bool   $getCount    Optional. Count the session courses
4167
     *
4168
     * @return array|int List of courses. Whether $getCount is true, return the count
4169
     */
4170
    public static function get_course_list_by_session_id(
4171
        $session_id,
4172
        $course_name = '',
4173
        $orderBy = null,
4174
        $getCount = false
4175
    ) {
4176
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4177
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4178
        $session_id = (int) $session_id;
4179
        $sqlSelect = '*, c.id, c.id as real_id, c.code as course_code';
4180
4181
        if ($getCount) {
4182
            $sqlSelect = 'COUNT(1) as count';
4183
        }
4184
4185
        // select the courses
4186
        $sql = "SELECT $sqlSelect
4187
                FROM $tbl_course c
4188
                INNER JOIN $tbl_session_rel_course src
4189
                ON (c.id = src.c_id)
4190
		        WHERE src.session_id = '$session_id' ";
4191
4192
        if (!empty($course_name)) {
4193
            $course_name = Database::escape_string($course_name);
4194
            $sql .= " AND c.title LIKE '%$course_name%' ";
4195
        }
4196
4197
        if (!empty($orderBy)) {
4198
            $orderBy = Database::escape_string($orderBy);
4199
            $orderBy = " ORDER BY $orderBy";
4200
        } else {
4201
            if (self::orderCourseIsEnabled()) {
4202
                $orderBy .= ' ORDER BY position ';
4203
            } else {
4204
                $orderBy .= ' ORDER BY title ';
4205
            }
4206
        }
4207
4208
        $sql .= Database::escape_string($orderBy);
4209
        $result = Database::query($sql);
4210
        $num_rows = Database::num_rows($result);
4211
        $courses = [];
4212
        if ($num_rows > 0) {
4213
            if ($getCount) {
4214
                $count = Database::fetch_assoc($result);
4215
4216
                return (int) $count['count'];
4217
            }
4218
4219
            while ($row = Database::fetch_assoc($result)) {
4220
                $courses[$row['real_id']] = $row;
4221
            }
4222
        }
4223
4224
        return $courses;
4225
    }
4226
4227
    /**
4228
     * Gets the list of courses by session filtered by access_url.
4229
     *
4230
     * @param $userId
4231
     * @param $sessionId
4232
     * @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...
4233
     * @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...
4234
     * @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...
4235
     * @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...
4236
     * @param bool   $getCount
4237
     * @param string $keyword
4238
     *
4239
     * @return array
4240
     */
4241
    public static function getAllCoursesFollowedByUser(
4242
        $userId,
4243
        $sessionId,
4244
        $from = null,
4245
        $limit = null,
4246
        $column = null,
4247
        $direction = null,
4248
        $getCount = false,
4249
        $keyword = ''
4250
    ) {
4251
        if (empty($sessionId)) {
4252
            $sessionsSQL = self::get_sessions_followed_by_drh(
4253
                $userId,
4254
                null,
4255
                null,
4256
                null,
4257
                true,
4258
                true
4259
            );
4260
        } else {
4261
            $sessionsSQL = intval($sessionId);
4262
        }
4263
4264
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4265
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4266
4267
        if ($getCount) {
4268
            $select = "SELECT COUNT(DISTINCT(c.code)) as count ";
4269
        } else {
4270
            $select = "SELECT DISTINCT c.* ";
4271
        }
4272
4273
        $keywordCondition = null;
4274
        if (!empty($keyword)) {
4275
            $keyword = Database::escape_string($keyword);
4276
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4277
        }
4278
4279
        // Select the courses
4280
        $sql = "$select
4281
                FROM $tbl_course c
4282
                INNER JOIN $tbl_session_rel_course src
4283
                ON c.id = src.c_id
4284
		        WHERE
4285
		            src.session_id IN ($sessionsSQL)
4286
		            $keywordCondition
4287
		        ";
4288
        if ($getCount) {
4289
            $result = Database::query($sql);
4290
            $row = Database::fetch_assoc($result);
4291
4292
            return $row['count'];
4293
        }
4294
4295
        if (isset($from) && isset($limit)) {
4296
            $from = intval($from);
4297
            $limit = intval($limit);
4298
            $sql .= " LIMIT $from, $limit";
4299
        }
4300
4301
        $result = Database::query($sql);
4302
        $num_rows = Database::num_rows($result);
4303
        $courses = [];
4304
4305
        if ($num_rows > 0) {
4306
            while ($row = Database::fetch_assoc($result)) {
4307
                $courses[$row['id']] = $row;
4308
            }
4309
        }
4310
4311
        return $courses;
4312
    }
4313
4314
    /**
4315
     * Gets the list of courses by session filtered by access_url.
4316
     *
4317
     * @param int    $session_id
4318
     * @param string $course_name
4319
     *
4320
     * @return array list of courses
4321
     */
4322
    public static function get_course_list_by_session_id_like($session_id, $course_name = '')
4323
    {
4324
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4325
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4326
4327
        $session_id = (int) $session_id;
4328
        $course_name = Database::escape_string($course_name);
4329
4330
        // select the courses
4331
        $sql = "SELECT c.id, c.title FROM $tbl_course c
4332
                INNER JOIN $tbl_session_rel_course src
4333
                ON c.id = src.c_id
4334
		        WHERE ";
4335
4336
        if (!empty($session_id)) {
4337
            $sql .= "src.session_id LIKE '$session_id' AND ";
4338
        }
4339
4340
        if (!empty($course_name)) {
4341
            $sql .= "UPPER(c.title) LIKE UPPER('%$course_name%') ";
4342
        }
4343
4344
        $sql .= "ORDER BY title;";
4345
        $result = Database::query($sql);
4346
        $num_rows = Database::num_rows($result);
4347
        $courses = [];
4348
        if ($num_rows > 0) {
4349
            while ($row = Database::fetch_assoc($result)) {
4350
                $courses[$row['id']] = $row;
4351
            }
4352
        }
4353
4354
        return $courses;
4355
    }
4356
4357
    /**
4358
     * Gets the count of courses by session filtered by access_url.
4359
     *
4360
     * @param int session id
4361
     * @param string $keyword
4362
     *
4363
     * @return array list of courses
4364
     */
4365
    public static function getCourseCountBySessionId($session_id, $keyword = '')
4366
    {
4367
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
4368
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4369
        $session_id = (int) $session_id;
4370
4371
        // select the courses
4372
        $sql = "SELECT COUNT(c.code) count
4373
                FROM $tbl_course c
4374
                INNER JOIN $tbl_session_rel_course src
4375
                ON c.id = src.c_id
4376
		        WHERE src.session_id = '$session_id' ";
4377
4378
        $keywordCondition = null;
4379
        if (!empty($keyword)) {
4380
            $keyword = Database::escape_string($keyword);
4381
            $keywordCondition = " AND (c.code LIKE '%$keyword%' OR c.title LIKE '%$keyword%' ) ";
4382
        }
4383
        $sql .= $keywordCondition;
4384
4385
        $result = Database::query($sql);
4386
        $num_rows = Database::num_rows($result);
4387
        if ($num_rows > 0) {
4388
            $row = Database::fetch_assoc($result);
4389
4390
            return $row['count'];
4391
        }
4392
4393
        return null;
4394
    }
4395
4396
    /**
4397
     * Get the session id based on the original id and field name in the extra fields.
4398
     * Returns 0 if session was not found.
4399
     *
4400
     * @param string $value    Original session id
4401
     * @param string $variable Original field name
4402
     *
4403
     * @return int Session id
4404
     */
4405
    public static function getSessionIdFromOriginalId($value, $variable)
4406
    {
4407
        $extraFieldValue = new ExtraFieldValue('session');
4408
        $result = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
4409
            $variable,
4410
            $value
4411
        );
4412
4413
        if (!empty($result)) {
4414
            return $result['item_id'];
4415
        }
4416
4417
        return 0;
4418
    }
4419
4420
    /**
4421
     * Get users by session.
4422
     *
4423
     * @param int  $id       session id
4424
     * @param int  $status   filter by status coach = 2
4425
     * @param bool $getCount Optional. Allow get the number of rows from the result
4426
     * @param int  $urlId
4427
     *
4428
     * @return array|int A list with an user list. If $getCount is true then return a the count of registers
4429
     */
4430
    public static function get_users_by_session(
4431
        $id,
4432
        $status = null,
4433
        $getCount = false,
4434
        $urlId = 0
4435
    ) {
4436
        if (empty($id)) {
4437
            return [];
4438
        }
4439
        $id = (int) $id;
4440
        $urlId = empty($urlId) ? api_get_current_access_url_id() : (int) $urlId;
4441
4442
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4443
        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
4444
        $table_access_url_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
4445
4446
        $selectedField = '
4447
            u.id as user_id, u.lastname, u.firstname, u.username, su.relation_type, au.access_url_id,
4448
            su.moved_to, su.moved_status, su.moved_at, su.registered_at
4449
        ';
4450
4451
        if ($getCount) {
4452
            $selectedField = 'count(1) AS count';
4453
        }
4454
4455
        $sql = "SELECT $selectedField
4456
                FROM $tbl_user u
4457
                INNER JOIN $tbl_session_rel_user su
4458
                ON u.id = su.user_id AND
4459
                su.session_id = $id
4460
                LEFT OUTER JOIN $table_access_url_user au
4461
                ON (au.user_id = u.id)
4462
                ";
4463
4464
        if (is_numeric($status)) {
4465
            $status = (int) $status;
4466
            $sql .= " WHERE su.relation_type = $status AND (au.access_url_id = $urlId OR au.access_url_id is null)";
4467
        } else {
4468
            $sql .= " WHERE (au.access_url_id = $urlId OR au.access_url_id is null )";
4469
        }
4470
4471
        $sql .= ' AND u.active <> '.USER_SOFT_DELETED.' ORDER BY su.relation_type, ';
4472
        $sql .= api_sort_by_first_name() ? ' u.firstname, u.lastname' : '  u.lastname, u.firstname';
4473
4474
        $result = Database::query($sql);
4475
        if ($getCount) {
4476
            $count = Database::fetch_assoc($result);
4477
            if ($count) {
4478
                return (int) $count['count'];
4479
            }
4480
4481
            return 0;
4482
        }
4483
4484
        $return = [];
4485
        while ($row = Database::fetch_assoc($result)) {
4486
            $return[] = $row;
4487
        }
4488
4489
        return $return;
4490
    }
4491
4492
    /**
4493
     * The general coach (session_rel_user.relation_type = Session::GENERAL_COACH).
4494
     *
4495
     * @param int  $user_id         user id
4496
     * @param bool $asPlatformAdmin The user is platform admin, return everything
4497
     *
4498
     * @return array
4499
     */
4500
    public static function get_sessions_by_general_coach($user_id, $asPlatformAdmin = false)
4501
    {
4502
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
4503
        $user_id = (int) $user_id;
4504
4505
        $innerJoin = '';
4506
        $whereConditions = '';
4507
4508
        if (!$asPlatformAdmin) {
4509
            $innerJoin = " INNER JOIN session_rel_user AS sru ON (s.id = sru.session_id) ";
4510
            $whereConditions = "sru.user_id = $user_id AND sru.relation_type = ".Session::GENERAL_COACH;
4511
        }
4512
4513
        if (api_is_multiple_url_enabled()) {
4514
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4515
            $access_url_id = api_get_current_access_url_id();
4516
4517
            if (-1 != $access_url_id) {
4518
                $innerJoin .= " INNER JOIN $tblSessionRelAccessUrl session_rel_url
4519
                    ON (s.id = access_url_rel_session.session_id)";
4520
                $whereConditions .= " AND access_url_rel_session.access_url_id = $access_url_id";
4521
            }
4522
        }
4523
        $sql = "SELECT s.* FROM $sessionTable AS s $innerJoin ";
4524
        if (!empty($whereConditions)) {
4525
            $sql .= "WHERE $whereConditions ";
4526
        }
4527
        $sql .= "ORDER BY s.title";
4528
        $result = Database::query($sql);
4529
4530
        return Database::store_result($result, 'ASSOC');
4531
    }
4532
4533
    /**
4534
     * @param int $user_id
4535
     * @param int $courseId
4536
     * @param int $session_id
4537
     *
4538
     * @return array|bool
4539
     */
4540
    public static function get_user_status_in_course_session($user_id, $courseId, $session_id)
4541
    {
4542
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
4543
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
4544
        $sql = "SELECT session_rcru.status
4545
                FROM $table session_rcru
4546
                INNER JOIN $tbl_user user
4547
                ON (session_rcru.user_id = user.id)
4548
                WHERE
4549
                    session_rcru.session_id = '".intval($session_id)."' AND
4550
                    session_rcru.c_id ='".intval($courseId)."' AND
4551
                    user.id = ".intval($user_id);
4552
4553
        $result = Database::query($sql);
4554
        $status = false;
4555
        if (Database::num_rows($result)) {
4556
            $status = Database::fetch_row($result);
4557
            $status = $status['0'];
4558
        }
4559
4560
        return $status;
4561
    }
4562
4563
    /**
4564
     * Gets user status within a session.
4565
     *
4566
     * @param int $userId
4567
     * @param int $sessionId
4568
     *
4569
     * @return SessionRelUser
4570
     */
4571
    public static function getUserStatusInSession($userId, $sessionId)
4572
    {
4573
        $em = Database::getManager();
4574
        $subscriptions = $em
4575
            ->getRepository(SessionRelUser::class)
4576
            ->findBy(['session' => $sessionId, 'user' => $userId]);
4577
4578
        /** @var SessionRelUser $subscription */
4579
        $subscription = current($subscriptions);
4580
4581
        return $subscription;
4582
    }
4583
4584
    /**
4585
     * @param int $id
4586
     *
4587
     * @return array
4588
     */
4589
    public static function get_all_sessions_by_promotion($id)
4590
    {
4591
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4592
4593
        return Database::select(
4594
            '*',
4595
            $table,
4596
            ['where' => ['promotion_id = ?' => $id]]
4597
        );
4598
    }
4599
4600
    /**
4601
     * @param int   $promotion_id
4602
     * @param array $list
4603
     */
4604
    public static function subscribe_sessions_to_promotion($promotion_id, $list)
4605
    {
4606
        $table = Database::get_main_table(TABLE_MAIN_SESSION);
4607
        $params = [];
4608
        $params['promotion_id'] = 0;
4609
        Database::update(
4610
            $table,
4611
            $params,
4612
            ['promotion_id = ?' => $promotion_id]
4613
        );
4614
4615
        $params['promotion_id'] = $promotion_id;
4616
        if (!empty($list)) {
4617
            foreach ($list as $session_id) {
4618
                $session_id = (int) $session_id;
4619
                Database::update($table, $params, ['id = ?' => $session_id]);
4620
            }
4621
        }
4622
    }
4623
4624
    /**
4625
     * Updates a session status.
4626
     *
4627
     * @param int session id
4628
     * @param int status
4629
     */
4630
    public static function set_session_status($session_id, $status)
4631
    {
4632
        $t = Database::get_main_table(TABLE_MAIN_SESSION);
4633
        $params['visibility'] = $status;
4634
        Database::update($t, $params, ['id = ?' => $session_id]);
4635
    }
4636
4637
    /**
4638
     * Copies a session with the same data to a new session.
4639
     * The new copy is not assigned to the same promotion.
4640
     *
4641
     * @param int  $id                         Session ID
4642
     * @param bool $copy_courses               Whether to copy the relationship with courses
4643
     * @param bool $copyTeachersAndDrh
4644
     * @param bool $create_new_courses         New courses will be created
4645
     * @param bool $set_exercises_lp_invisible Set exercises and LPs in the new session to invisible by default
4646
     * @param bool $copyWithSessionContent     Copy course session content into the courses
4647
     *
4648
     * @return int The new session ID on success, 0 otherwise
4649
     *
4650
     * @see subscribe_sessions_to_promotions() for that.
4651
     *
4652
     * @todo make sure the extra session fields are copied too
4653
     */
4654
    public static function copy(
4655
        int $id,
4656
        bool $copy_courses = true,
4657
        bool $copyTeachersAndDrh = true,
4658
        bool $create_new_courses = false,
4659
        bool $set_exercises_lp_invisible = false,
4660
        bool $copyWithSessionContent = false,
4661
    ) {
4662
        $id = (int) $id;
4663
        $s = self::fetch($id);
4664
4665
        if (empty($s)) {
4666
            return false;
4667
        }
4668
4669
        // Check all dates before copying
4670
        // Get timestamp for now in UTC - see http://php.net/manual/es/function.time.php#117251
4671
        $now = time() - date('Z');
4672
        // Timestamp in one month
4673
        $inOneMonth = $now + (30 * 24 * 3600);
4674
        $inOneMonth = api_get_local_time($inOneMonth);
4675
        if (api_strtotime($s['access_start_date']) < $now) {
4676
            $s['access_start_date'] = api_get_local_time($now);
4677
        } else {
4678
            $s['access_start_date'] = api_get_local_time($s['access_start_date']);
4679
        }
4680
        if (api_strtotime($s['display_start_date']) < $now) {
4681
            $s['display_start_date'] = api_get_local_time($now);
4682
        } else {
4683
            $s['display_start_date'] = api_get_local_time($s['display_start_date']);
4684
        }
4685
        if (api_strtotime($s['coach_access_start_date']) < $now) {
4686
            $s['coach_access_start_date'] = api_get_local_time($now);
4687
        } else {
4688
            $s['coach_access_start_date'] = api_get_local_time($s['coach_access_start_date']);
4689
        }
4690
        if (api_strtotime($s['access_end_date']) < $now) {
4691
            $s['access_end_date'] = $inOneMonth;
4692
        } else {
4693
            $s['access_end_date'] = api_get_local_time($s['access_end_date']);
4694
        }
4695
        if (api_strtotime($s['display_end_date']) < $now) {
4696
            $s['display_end_date'] = $inOneMonth;
4697
        } else {
4698
            $s['display_end_date'] = api_get_local_time($s['display_end_date']);
4699
        }
4700
        if (api_strtotime($s['coach_access_end_date']) < $now) {
4701
            $s['coach_access_end_date'] = $inOneMonth;
4702
        } else {
4703
            $s['coach_access_end_date'] = api_get_local_time($s['coach_access_end_date']);
4704
        }
4705
4706
        $extraFieldValue = new ExtraFieldValue('session');
4707
        $extraFieldsValues = $extraFieldValue->getAllValuesByItem($id);
4708
        $extraFieldsValuesToCopy = [];
4709
        if (!empty($extraFieldsValues)) {
4710
            foreach ($extraFieldsValues as $extraFieldValue) {
4711
                //$extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4712
                $extraFieldsValuesToCopy['extra_'.$extraFieldValue['variable']]['extra_'.$extraFieldValue['variable']] = $extraFieldValue['value'];
4713
            }
4714
        }
4715
4716
        // @todo fix session image url copy.
4717
        /*if (isset($extraFieldsValuesToCopy['extra_image']) &&
4718
            isset($extraFieldsValuesToCopy['extra_image']['extra_image'])
4719
        ) {
4720
            $extraFieldsValuesToCopy['extra_image'] = [
4721
                'tmp_name' => api_get_path(SYS_UPLOAD_PATH).$extraFieldsValuesToCopy['extra_image']['extra_image'],
4722
                'error' => 0,
4723
            ];
4724
        }*/
4725
4726
        $generalCoaches = self::getGeneralCoachesIdForSession($id);
4727
4728
        // Now try to create the session
4729
        $sid = self::create_session(
4730
            $s['title'].' '.get_lang('Copy'),
4731
            $s['access_start_date'],
4732
            $s['access_end_date'],
4733
            $s['display_start_date'],
4734
            $s['display_end_date'],
4735
            $s['coach_access_start_date'],
4736
            $s['coach_access_end_date'],
4737
            $generalCoaches,
4738
            $s['session_category_id'],
4739
            (int) $s['visibility'],
4740
            true,
4741
            $s['duration'],
4742
            $s['description'],
4743
            $s['show_description'],
4744
            $extraFieldsValuesToCopy
4745
        );
4746
4747
        if (!is_numeric($sid) || empty($sid)) {
4748
            return false;
4749
        }
4750
4751
        if ($copy_courses) {
4752
            // Register courses from the original session to the new session
4753
            $courses = self::get_course_list_by_session_id($id);
4754
            $short_courses = $new_short_courses = [];
4755
            if (is_array($courses) && count($courses) > 0) {
4756
                foreach ($courses as $course) {
4757
                    $short_courses[] = $course;
4758
                }
4759
            }
4760
4761
            // We will copy the current courses of the session to new courses
4762
            if (!empty($short_courses)) {
4763
                if ($create_new_courses) {
4764
                    api_set_more_memory_and_time_limits();
4765
                    $params = [];
4766
                    $params['skip_lp_dates'] = true;
4767
4768
                    foreach ($short_courses as $course_data) {
4769
                        $course = CourseManager::copy_course_simple(
4770
                            $course_data['title'].' '.get_lang('Copy'),
4771
                            $course_data['course_code'],
4772
                            $id,
4773
                            $sid,
4774
                            $params
4775
                        );
4776
4777
                        if (null !== $course) {
4778
                            $course_info = api_get_course_info($course->getCode());
4779
                            //By default new elements are invisible
4780
                            if ($set_exercises_lp_invisible) {
4781
                                $list = new LearnpathList('', $course_info, $sid);
4782
                                $flat_list = $list->get_flat_list();
4783
                                if (!empty($flat_list)) {
4784
                                    foreach ($flat_list as $lp_id => $data) {
4785
                                        // @todo fix
4786
                                        /*api_item_property_update(
4787
                                            $course_info,
4788
                                            TOOL_LEARNPATH,
4789
                                            $lp_id,
4790
                                            'invisible',
4791
                                            api_get_user_id(),
4792
                                            0,
4793
                                            0,
4794
                                            0,
4795
                                            0,
4796
                                            $sid
4797
                                        );*/
4798
                                    }
4799
                                }
4800
                                $quiz_table = Database::get_course_table(TABLE_QUIZ_TEST);
4801
                                $course_id = $course_info['real_id'];
4802
                                //@todo check this query
4803
                                $sql = "UPDATE $quiz_table SET active = 0
4804
                                        WHERE c_id = $course_id AND session_id = $sid";
4805
                                Database::query($sql);
4806
                            }
4807
                            $new_short_courses[] = $course_info['real_id'];
4808
                        }
4809
                    }
4810
                } else {
4811
                    foreach ($short_courses as $course_data) {
4812
                        $new_short_courses[] = $course_data['id'];
4813
                    }
4814
                }
4815
4816
                $short_courses = $new_short_courses;
4817
                self::add_courses_to_session($sid, $short_courses, true);
4818
4819
                if ($copyWithSessionContent) {
4820
                    foreach ($courses as $course) {
4821
                        CourseManager::copy_course(
4822
                            $course['code'],
4823
                            $id,
4824
                            $course['code'],
4825
                            $sid,
4826
                            [],
4827
                            false,
4828
                            true
4829
                        );
4830
                    }
4831
                }
4832
4833
                if (false === $create_new_courses && $copyTeachersAndDrh) {
4834
                    foreach ($short_courses as $courseItemId) {
4835
                        $coachList = self::getCoachesByCourseSession($id, $courseItemId);
4836
                        foreach ($coachList as $userId) {
4837
                            self::set_coach_to_course_session($userId, $sid, $courseItemId);
4838
                        }
4839
                    }
4840
                }
4841
            }
4842
        }
4843
4844
        if ($copyTeachersAndDrh) {
4845
            // Register users from the original session to the new session
4846
            $users = self::get_users_by_session($id);
4847
            if (!empty($users)) {
4848
                $userListByStatus = [];
4849
                foreach ($users as $userData) {
4850
                    $userData['relation_type'] = (int) $userData['relation_type'];
4851
                    $userListByStatus[$userData['relation_type']][] = $userData;
4852
                }
4853
4854
                foreach ($userListByStatus as $status => $userList) {
4855
                    $userList = array_column($userList, 'user_id');
4856
                    switch ($status) {
4857
                        case 0:
4858
                            /*self::subscribeUsersToSession(
4859
                                $sid,
4860
                                $userList,
4861
                                SESSION_VISIBLE_READ_ONLY,
4862
                                false,
4863
                                true
4864
                            );*/
4865
                            break;
4866
                        case 1:
4867
                            // drh users
4868
                            foreach ($userList as $drhId) {
4869
                                $userInfo = api_get_user_info($drhId);
4870
                                self::subscribeSessionsToDrh($userInfo, [$sid], false, false);
4871
                            }
4872
                            break;
4873
                    }
4874
                }
4875
            }
4876
        }
4877
4878
        return $sid;
4879
    }
4880
4881
    /**
4882
     * Get the number of sessions.
4883
     *
4884
     * @param int $access_url_id ID of the URL we want to filter on (optional)
4885
     *
4886
     * @return int Number of sessions
4887
     */
4888
    public static function count_sessions($access_url_id = 0)
4889
    {
4890
        $session_table = Database::get_main_table(TABLE_MAIN_SESSION);
4891
        $access_url_rel_session_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
4892
        $access_url_id = (int) $access_url_id;
4893
        $sql = "SELECT count(s.id) FROM $session_table s";
4894
        if (!empty($access_url_id)) {
4895
            $sql .= ", $access_url_rel_session_table u ".
4896
                " WHERE s.id = u.session_id AND u.access_url_id = $access_url_id";
4897
        }
4898
        $res = Database::query($sql);
4899
        $row = Database::fetch_row($res);
4900
4901
        return $row[0];
4902
    }
4903
4904
    public static function cantEditSession(?Session $session = null, bool $checkSession = true): bool
4905
    {
4906
        if (!self::allowToManageSessions()) {
4907
            return false;
4908
        }
4909
4910
        if (api_is_platform_admin() && self::allowed($session)) {
4911
            return true;
4912
        }
4913
4914
        if ($checkSession) {
4915
            if (self::allowed($session)) {
4916
                return true;
4917
            }
4918
4919
            return false;
4920
        }
4921
4922
        return true;
4923
    }
4924
4925
    /**
4926
     * Protect a session to be edited.
4927
     *
4928
     * @return mixed | bool true if pass the check, api_not_allowed otherwise
4929
     */
4930
    public static function protectSession(?Session $session = null, bool $checkSession = true)
4931
    {
4932
        if (!self::cantEditSession($session, $checkSession)) {
4933
            api_not_allowed(true);
4934
        }
4935
    }
4936
4937
    public static function allowToManageSessions(): bool
4938
    {
4939
        if (self::allowManageAllSessions()) {
4940
            return true;
4941
        }
4942
4943
        if (api_is_teacher() && 'true' === api_get_setting('allow_teachers_to_create_sessions')) {
4944
            return true;
4945
        }
4946
4947
        return false;
4948
    }
4949
4950
    /**
4951
     * @return bool
4952
     */
4953
    public static function allowOnlyMySessions()
4954
    {
4955
        if (self::allowToManageSessions() &&
4956
            !api_is_platform_admin() &&
4957
            api_is_teacher()
4958
        ) {
4959
            return true;
4960
        }
4961
4962
        return false;
4963
    }
4964
4965
    /**
4966
     * @return bool
4967
     */
4968
    public static function allowManageAllSessions()
4969
    {
4970
        if (api_is_platform_admin() || api_is_session_admin()) {
4971
            return true;
4972
        }
4973
4974
        return false;
4975
    }
4976
4977
    /**
4978
     * @param $id
4979
     *
4980
     * @return bool
4981
     */
4982
    public static function protect_teacher_session_edit($id)
4983
    {
4984
        if (!api_is_coach($id) && !api_is_platform_admin()) {
4985
            api_not_allowed(true);
4986
        } else {
4987
            return true;
4988
        }
4989
    }
4990
4991
    /**
4992
     * @param int $courseId
4993
     *
4994
     * @return array
4995
     */
4996
    public static function get_session_by_course($courseId)
4997
    {
4998
        $table_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
4999
        $table_session = Database::get_main_table(TABLE_MAIN_SESSION);
5000
        $url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
5001
        $courseId = (int) $courseId;
5002
        $urlId = api_get_current_access_url_id();
5003
5004
        if (empty($courseId)) {
5005
            return [];
5006
        }
5007
5008
        $sql = "SELECT title, s.id
5009
                FROM $table_session_course sc
5010
                INNER JOIN $table_session s
5011
                ON (sc.session_id = s.id)
5012
                INNER JOIN $url u
5013
                ON (u.session_id = s.id)
5014
                WHERE
5015
                    u.access_url_id = $urlId AND
5016
                    sc.c_id = '$courseId' ";
5017
        $result = Database::query($sql);
5018
5019
        return Database::store_result($result);
5020
    }
5021
5022
    /**
5023
     * @param int  $userId
5024
     * @param bool $ignoreVisibilityForAdmins
5025
     * @param bool $ignoreTimeLimit
5026
     *
5027
     * @return array
5028
     */
5029
    public static function get_sessions_by_user(
5030
        $userId,
5031
        $ignoreVisibilityForAdmins = false,
5032
        $ignoreTimeLimit = false
5033
    ) {
5034
        $sessionCategories = UserManager::get_sessions_by_category(
5035
            $userId,
5036
            false,
5037
            $ignoreVisibilityForAdmins,
5038
            $ignoreTimeLimit
5039
        );
5040
5041
        $sessionArray = [];
5042
        if (!empty($sessionCategories)) {
5043
            foreach ($sessionCategories as $category) {
5044
                if (isset($category['sessions'])) {
5045
                    foreach ($category['sessions'] as $session) {
5046
                        $sessionArray[] = $session;
5047
                    }
5048
                }
5049
            }
5050
        }
5051
5052
        return $sessionArray;
5053
    }
5054
5055
    /**
5056
     * Imports sessions from a CSV file, creating or updating sessions with related users and courses.
5057
     *
5058
     * @return array Contains the import result with errors, counters, and session IDs.
5059
     */
5060
    public static function importCSV(
5061
        string $file,
5062
        bool $updateSession,
5063
        ?int $defaultUserId = null,
5064
        ?Logger $logger = null,
5065
        array $extraFields = [],
5066
        ?string $extraFieldId = null,
5067
        ?int $daysCoachAccessBeforeBeginning = null,
5068
        ?int $daysCoachAccessAfterBeginning = null,
5069
        int $sessionVisibility = 1,
5070
        array $fieldsToAvoidUpdate = [],
5071
        bool $deleteUsersNotInList = false,
5072
        bool $updateCourseCoaches = false,
5073
        bool $sessionWithCoursesModifier = false,
5074
        bool $addOriginalCourseTeachersAsCourseSessionCoaches = true,
5075
        bool $removeAllTeachersFromCourse = true,
5076
        ?int $showDescription = null,
5077
        array &$teacherBackupList = [],
5078
        array &$groupBackup = []
5079
    ): array {
5080
5081
        $sepCheck = Import::assertCommaSeparated($file, true);
5082
        if ($sepCheck !== true) {
5083
            return [
5084
                'error_message'   => $sepCheck,
5085
                'session_counter' => 0,
5086
                'session_list'    => [],
5087
            ];
5088
        }
5089
5090
        $error_message = null;
5091
        $session_counter = 0;
5092
        $defaultUserId = empty($defaultUserId) ? api_get_user_id() : (int) $defaultUserId;
5093
        $defaultUser = api_get_user_entity($defaultUserId);
5094
5095
        $eol = PHP_SAPI != 'cli' ? '<br />' : PHP_EOL;
5096
5097
        $debug = isset($logger);
5098
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
5099
        $tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
5100
        $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
5101
        $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
5102
5103
        $rows = Import::csvToArray($file);
5104
        if (empty($rows) || !is_array($rows)) {
5105
            return [
5106
                'error_message'   => get_lang('The specified file is not CSV format !'),
5107
                'session_counter' => 0,
5108
                'session_list'    => [],
5109
            ];
5110
        }
5111
5112
        $normalizeKey = static function (string $k): string {
5113
            return trim(ltrim($k, "\xEF\xBB\xBF"));
5114
        };
5115
5116
        $normalizedRows = [];
5117
        foreach ($rows as $r) {
5118
            $nr = [];
5119
            foreach ($r as $k => $v) {
5120
                $nr[$normalizeKey($k)] = $v;
5121
            }
5122
            $normalizedRows[] = $nr;
5123
        }
5124
        $rows = $normalizedRows;
5125
        $first = $rows[0] ?? [];
5126
        $required = ['SessionName', 'DateStart', 'DateEnd'];
5127
        foreach ($required as $col) {
5128
            if (!array_key_exists($col, $first)) {
5129
                return [
5130
                    'error_message'   => get_lang("The specified file doesn't contain all needed data !"),
5131
                    'session_counter' => 0,
5132
                    'session_list'    => [],
5133
                ];
5134
            }
5135
        }
5136
5137
        $sessions = $rows;
5138
        $sessionList = [];
5139
        $report = [];
5140
        foreach ($sessions as $enreg) {
5141
            $user_counter = 0;
5142
            $course_counter = 0;
5143
5144
            if (!empty($extraFields)) {
5145
                foreach ($extraFields as $original => $to) {
5146
                    $enreg[$to] = $enreg[$original] ?? null;
5147
                }
5148
            }
5149
5150
            $session_name = $enreg['SessionName'];
5151
5152
            if ($debug) {
5153
                $logger->debug('---------------------------------------');
5154
                $logger->debug("Sessions - Start process of session: $session_name");
5155
                $logger->debug('---------------------------------------');
5156
            }
5157
5158
            // Default visibility
5159
            $visibilityAfterExpirationPerSession = $sessionVisibility;
5160
            if (isset($enreg['VisibilityAfterExpiration'])) {
5161
                $visibility = $enreg['VisibilityAfterExpiration'];
5162
                switch ($visibility) {
5163
                    case 'read_only':
5164
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE_READ_ONLY;
5165
                        break;
5166
                    case 'accessible':
5167
                        $visibilityAfterExpirationPerSession = SESSION_VISIBLE;
5168
                        break;
5169
                    case 'not_accessible':
5170
                        $visibilityAfterExpirationPerSession = SESSION_INVISIBLE;
5171
                        break;
5172
                }
5173
            }
5174
5175
            if (empty($session_name)) {
5176
                continue;
5177
            }
5178
5179
            $displayAccessStartDate = $enreg['DisplayStartDate'] ?? $enreg['DateStart'];
5180
            $displayAccessEndDate = $enreg['DisplayEndDate'] ?? $enreg['DateEnd'];
5181
            $coachAccessStartDate = $enreg['CoachStartDate'] ?? $enreg['DateStart'];
5182
            $coachAccessEndDate = $enreg['CoachEndDate'] ?? $enreg['DateEnd'];
5183
            $dateStart = date('Y-m-d H:i:s', strtotime(trim($enreg['DateStart'])));
5184
            $displayAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($displayAccessStartDate)));
5185
            $coachAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($coachAccessStartDate)));
5186
            $dateEnd = self::normalizeDateEnd($enreg['DateEnd']);
5187
            $displayAccessEndDate = self::normalizeDateEnd($displayAccessEndDate);
5188
            $coachAccessEndDate = self::normalizeDateEnd($coachAccessEndDate);
5189
            $session_category_id = $enreg['SessionCategory'] ?? null;
5190
            $sessionDescription = $enreg['SessionDescription'] ?? null;
5191
            $classes = isset($enreg['Classes']) ? explode('|', $enreg['Classes']) : [];
5192
            $extraParams = [];
5193
            if (!is_null($showDescription)) {
5194
                $extraParams['show_description'] = intval($showDescription);
5195
            }
5196
5197
            $coachBefore = '';
5198
            $coachAfter = '';
5199
            if (!empty($daysCoachAccessBeforeBeginning) && !empty($daysCoachAccessAfterBeginning)) {
5200
                $date = new \DateTime($dateStart);
5201
                $interval = new DateInterval('P'.$daysCoachAccessBeforeBeginning.'D');
5202
                $date->sub($interval);
5203
                $coachBefore = $date->format('Y-m-d h:i');
5204
                $coachAccessStartDate = $coachBefore;
5205
                $coachBefore = api_get_utc_datetime($coachBefore);
5206
5207
                $date = new \DateTime($dateEnd);
5208
                $interval = new DateInterval('P'.$daysCoachAccessAfterBeginning.'D');
5209
                $date->add($interval);
5210
                $coachAfter = $date->format('Y-m-d h:i');
5211
                $coachAccessEndDate = $coachAfter;
5212
                $coachAfter = api_get_utc_datetime($coachAfter);
5213
            }
5214
5215
            $dateStart = api_get_utc_datetime($dateStart);
5216
            $dateEnd = api_get_utc_datetime($dateEnd);
5217
            $displayAccessStartDate = api_get_utc_datetime($displayAccessStartDate);
5218
            $displayAccessEndDate = api_get_utc_datetime($displayAccessEndDate);
5219
            $coachAccessStartDate = api_get_utc_datetime($coachAccessStartDate);
5220
            $coachAccessEndDate = api_get_utc_datetime($coachAccessEndDate);
5221
5222
            if (!empty($sessionDescription)) {
5223
                $extraParams['description'] = $sessionDescription;
5224
            }
5225
5226
            if (!empty($session_category_id)) {
5227
                $extraParams['session_category_id'] = $session_category_id;
5228
            }
5229
5230
            // Searching a general coach.
5231
            if (!empty($enreg['Coach'])) {
5232
                $coach_id = UserManager::get_user_id_from_username($enreg['Coach']);
5233
                if (false === $coach_id) {
5234
                    // If the coach-user does not exist - I'm the coach.
5235
                    $coach_id = $defaultUserId;
5236
                }
5237
            } else {
5238
                $coach_id = $defaultUserId;
5239
            }
5240
5241
            $coach = api_get_user_entity($coach_id);
5242
5243
            $usersRaw = (string)($enreg['Users'] ?? '');
5244
            $users = $usersRaw === ''
5245
                ? []
5246
                : array_values(array_filter(array_map('trim', explode('|', $usersRaw)), 'strlen'));
5247
            $courses = isset($enreg['Courses']) && $enreg['Courses'] !== '' ? explode('|', $enreg['Courses']) : [];
5248
5249
            $deleteOnlyCourseCoaches = false;
5250
            if (1 == count($courses)) {
5251
                if ($logger) {
5252
                    $logger->debug('Only one course delete old coach list');
5253
                }
5254
                $deleteOnlyCourseCoaches = true;
5255
            }
5256
5257
            if (!$updateSession) {
5258
                // Create a session.
5259
                $unique_name = false;
5260
                $i = 0;
5261
                // Change session name, verify that session doesn't exist.
5262
                $suffix = null;
5263
                while (!$unique_name) {
5264
                    if ($i > 1) {
5265
                        $suffix = ' - '.$i;
5266
                    }
5267
                    $sql = 'SELECT id FROM '.$tbl_session.'
5268
                                WHERE title = "'.Database::escape_string($session_name).$suffix.'"';
5269
                    $rs = Database::query($sql);
5270
                    if (Database::result($rs, 0, 0)) {
5271
                        $i++;
5272
                    } else {
5273
                        $unique_name = true;
5274
                        $session_name .= $suffix;
5275
                    }
5276
                }
5277
5278
                $sessionParams = [
5279
                    'title' => $session_name,
5280
                    'access_start_date' => $dateStart,
5281
                    'access_end_date' => $dateEnd,
5282
                    'display_start_date' => $displayAccessStartDate,
5283
                    'display_end_date' => $displayAccessEndDate,
5284
                    'coach_access_start_date' => $coachAccessStartDate,
5285
                    'coach_access_end_date' => $coachAccessEndDate,
5286
                    'visibility' => $visibilityAfterExpirationPerSession,
5287
                    'nbr_users' => 0,
5288
                    'nbr_courses' => 0,
5289
                    'nbr_classes' => 0,
5290
                    'status' => 0,
5291
                    'duration' => 0,
5292
                ];
5293
5294
                if (!empty($extraParams)) {
5295
                    $sessionParams = array_merge($sessionParams, $extraParams);
5296
                }
5297
                // Creating the session.
5298
                $session_id = Database::insert($tbl_session, $sessionParams);
5299
                $session = api_get_session_entity($session_id);
5300
                if ($session_id) {
5301
5302
                    $em = Database::getManager();
5303
                    $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5304
                    $defaultUser = $em->contains($defaultUser) ? $defaultUser : $em->merge($defaultUser);
5305
5306
                    $session->addUserInSession(Session::GENERAL_COACH, $coach);
5307
                    $session->addUserInSession(Session::GENERAL_COACH, $defaultUser);
5308
                    $em->flush();
5309
5310
                    foreach ($enreg as $key => $value) {
5311
                        if ('extra_' === substr($key, 0, 6)) { //an extra field
5312
                            self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5313
                        }
5314
                    }
5315
                    if ($debug) {
5316
                        $logger->debug("Session created: #$session_id - $session_name");
5317
                    }
5318
                } else {
5319
                    if ($debug) {
5320
                        $message = "Sessions - Session NOT created: $session_name";
5321
                        $logger->debug($message);
5322
                        $report[] = $message;
5323
                    }
5324
                }
5325
                $session_counter++;
5326
            } else {
5327
                $sessionId = null;
5328
                if (isset($extraFields) && !empty($extraFields) && !empty($enreg['extra_'.$extraFieldId])) {
5329
                    $sessionId = self::getSessionIdFromOriginalId($enreg['extra_'.$extraFieldId], $extraFieldId);
5330
                    if (empty($sessionId)) {
5331
                        $my_session_result = false;
5332
                    } else {
5333
                        $my_session_result = true;
5334
                    }
5335
                } else {
5336
                    $my_session_result = self::get_session_by_name($enreg['SessionName']);
5337
                }
5338
5339
                if (false === $my_session_result) {
5340
                    // One more check
5341
                    $sessionExistsWithName = self::get_session_by_name($session_name);
5342
                    if ($sessionExistsWithName) {
5343
                        if ($debug) {
5344
                            $message = "Skip Session - Trying to update a session, but name already exists: $session_name";
5345
                            $logger->debug($message);
5346
                            $report[] = $message;
5347
                        }
5348
                        continue;
5349
                    }
5350
5351
                    $sessionParams = [
5352
                        'title' => $session_name,
5353
                        'access_start_date' => $dateStart,
5354
                        'access_end_date' => $dateEnd,
5355
                        'display_start_date' => $displayAccessStartDate,
5356
                        'display_end_date' => $displayAccessEndDate,
5357
                        'coach_access_start_date' => $coachAccessStartDate,
5358
                        'coach_access_end_date' => $coachAccessEndDate,
5359
                        'visibility' => $visibilityAfterExpirationPerSession,
5360
                        'nbr_users' => 0,
5361
                        'nbr_courses' => 0,
5362
                        'nbr_classes' => 0,
5363
                        'status' => 0,
5364
                        'duration' => 0,
5365
                    ];
5366
5367
                    if (!empty($extraParams)) {
5368
                        $sessionParams = array_merge($sessionParams, $extraParams);
5369
                    }
5370
                    $session_id = Database::insert($tbl_session, $sessionParams);
5371
5372
                    if ($session_id) {
5373
                        $session = api_get_session_entity($session_id);
5374
5375
                        $session
5376
                            ->addUserInSession(Session::GENERAL_COACH, $coach)
5377
                            ->addUserInSession(Session::GENERAL_COACH, $defaultUser)
5378
                        ;
5379
                        Database::getManager()->flush();
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'] = $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
5505
                        $em = Database::getManager();
5506
                        $coach = $em->contains($coach) ? $coach : $em->merge($coach);
5507
                        api_get_session_entity($session_id)->addUserInSession(Session::GENERAL_COACH, $coach);
5508
                        $em->flush();
5509
5510
                        foreach ($enreg as $key => $value) {
5511
                            if ('extra_' == substr($key, 0, 6)) { //an extra field
5512
                                self::update_session_extra_field_value($session_id, substr($key, 6), $value);
5513
                            }
5514
                        }
5515
5516
                        if ($debug) {
5517
                            $logger->debug("Session updated #$session_id");
5518
                        }
5519
5520
                        // Delete session-user relation only for students
5521
                        $sql = "DELETE FROM $tbl_session_user
5522
                                    WHERE session_id = '$session_id' AND relation_type = ".Session::STUDENT;
5523
                        Database::query($sql);
5524
5525
                        $sql = "DELETE FROM $tbl_session_course WHERE session_id = '$session_id'";
5526
                        Database::query($sql);
5527
5528
                        // Delete session-course-user relationships students and coaches.
5529
                        if ($updateCourseCoaches) {
5530
                            $sql = "DELETE FROM $tbl_session_course_user
5531
                                        WHERE session_id = '$session_id' AND status in (".Session::STUDENT.", ".Session::COURSE_COACH.")";
5532
                            Database::query($sql);
5533
                        } else {
5534
                            // Delete session-course-user relation ships *only* for students.
5535
                            $sql = "DELETE FROM $tbl_session_course_user
5536
                                        WHERE session_id = '$session_id' AND status = ".Session::STUDENT;
5537
                            Database::query($sql);
5538
                        }
5539
5540
                        if ($deleteOnlyCourseCoaches) {
5541
                            $sql = "DELETE FROM $tbl_session_course_user
5542
                                        WHERE session_id = '$session_id' AND status = ".Session::COURSE_COACH;
5543
                            Database::query($sql);
5544
                        }
5545
                    } else {
5546
                        if ($debug) {
5547
                            $logger->debug(
5548
                                "Sessions - Session not found"
5549
                            );
5550
                        }
5551
                    }
5552
                }
5553
                $session_counter++;
5554
            }
5555
5556
            $sessionList[] = $session_id;
5557
5558
            // Adding the relationship "Session - User" for students
5559
            $userList = [];
5560
            if (is_array($users)) {
5561
                $extraFieldValueCareer = new ExtraFieldValue('career');
5562
                $careerList = isset($enreg['extra_careerid']) && !empty($enreg['extra_careerid']) ? $enreg['extra_careerid'] : [];
5563
                $careerList = str_replace(['[', ']'], '', $careerList);
5564
                if (!empty($careerList)) {
5565
                    $careerList = explode(',', $careerList);
5566
                    $finalCareerIdList = [];
5567
                    foreach ($careerList as $careerId) {
5568
                        $realCareerIdList = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
5569
                            'external_career_id',
5570
                            $careerId
5571
                        );
5572
                        if (isset($realCareerIdList['item_id'])) {
5573
                            $finalCareerIdList[] = $realCareerIdList['item_id'];
5574
                        }
5575
                    }
5576
                }
5577
5578
                foreach ($users as $user) {
5579
                    $user_id = UserManager::get_user_id_from_username($user);
5580
                    if (false !== $user_id) {
5581
                        if (!empty($finalCareerIdList)) {
5582
                            foreach ($finalCareerIdList as $careerId) {
5583
                                UserManager::addUserCareer($user_id, $careerId);
5584
                            }
5585
                        }
5586
5587
                        $userEntity = api_get_user_entity($user_id);
5588
                        $sessionEntity = api_get_session_entity($session_id);
5589
                        $sessionEntity->addUserInSession(Session::STUDENT, $userEntity);
5590
5591
                        if ($debug) {
5592
                            $logger->debug("Adding User #$user_id ($user) to session #$session_id");
5593
                        }
5594
                        $user_counter++;
5595
                    }
5596
                }
5597
            }
5598
5599
            if ($deleteUsersNotInList) {
5600
                // Getting user in DB in order to compare to the new list.
5601
                $usersListInDatabase = self::get_users_by_session($session_id, 0);
5602
                if (!empty($usersListInDatabase)) {
5603
                    if (empty($userList)) {
5604
                        foreach ($usersListInDatabase as $userInfo) {
5605
                            self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5606
                        }
5607
                    } else {
5608
                        foreach ($usersListInDatabase as $userInfo) {
5609
                            if (!in_array($userInfo['user_id'], $userList)) {
5610
                                self::unsubscribe_user_from_session($session_id, $userInfo['user_id']);
5611
                            }
5612
                        }
5613
                    }
5614
                }
5615
            }
5616
5617
            // See BT#6449
5618
            $onlyAddFirstCoachOrTeacher = false;
5619
            if ($sessionWithCoursesModifier) {
5620
                if (count($courses) >= 2) {
5621
                    // Only first teacher in course session;
5622
                    $onlyAddFirstCoachOrTeacher = true;
5623
                    // Remove all teachers from course.
5624
                    $removeAllTeachersFromCourse = false;
5625
                }
5626
            }
5627
5628
            foreach ($courses as $course) {
5629
                $courseArray = bracketsToArray($course);
5630
                $course_code = $courseArray[0];
5631
5632
                if (CourseManager::course_exists($course_code)) {
5633
                    $courseInfo = api_get_course_info($course_code);
5634
                    $courseId = $courseInfo['real_id'];
5635
5636
                    // Adding the course to a session.
5637
                    $sql = "INSERT IGNORE INTO $tbl_session_course
5638
                                SET c_id = '$courseId', session_id='$session_id'";
5639
                    Database::query($sql);
5640
5641
                    self::installCourse($session_id, $courseInfo['real_id']);
5642
5643
                    if ($debug) {
5644
                        $logger->debug("Adding course '$course_code' to session #$session_id");
5645
                    }
5646
5647
                    $course_counter++;
5648
                    $course_coaches = array_values(
5649
                        array_filter(
5650
                            array_map('trim', explode(',', (string)($courseArray[1] ?? ''))),
5651
                            'strlen'
5652
                        )
5653
                    );
5654
                    $course_users = array_values(
5655
                        array_filter(
5656
                            array_map('trim', explode(',', (string)($courseArray[2] ?? ''))),
5657
                            'strlen'
5658
                        )
5659
                    );
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
                                    $badCoach = trim((string)$course_coach);
5723
                                    $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
5724
                                }
5725
                            }
5726
                        }
5727
5728
                        // Custom courses/session coaches
5729
                        $teacherToAdd = null;
5730
                        // Only one coach is added.
5731
                        if (true == $onlyAddFirstCoachOrTeacher) {
5732
                            if ($debug) {
5733
                                $logger->debug("onlyAddFirstCoachOrTeacher : true");
5734
                            }
5735
5736
                            foreach ($course_coaches as $course_coach) {
5737
                                $coach_id = UserManager::get_user_id_from_username($course_coach);
5738
                                if (false !== $coach_id) {
5739
                                    $teacherToAdd = $coach_id;
5740
                                    break;
5741
                                }
5742
                            }
5743
5744
                            // Un subscribe everyone that's not in the list.
5745
                            $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5746
                            if (!empty($teacherList)) {
5747
                                foreach ($teacherList as $teacher) {
5748
                                    if ($teacherToAdd != $teacher['user_id']) {
5749
                                        $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5750
                                                    WHERE
5751
                                                        user_id = ".$teacher['user_id']." AND
5752
                                                        c_id = '".$courseId."'
5753
                                                    ";
5754
5755
                                        $result = Database::query($sql);
5756
                                        $rows = Database::num_rows($result);
5757
                                        if ($rows > 0) {
5758
                                            $userCourseData = Database::fetch_assoc($result);
5759
                                            if (!empty($userCourseData)) {
5760
                                                $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5761
                                            }
5762
                                        }
5763
5764
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5765
                                                    WHERE
5766
                                                        user_id = ".$teacher['user_id']." AND
5767
                                                        c_id = '".$courseInfo['real_id']."'
5768
                                                    ";
5769
5770
                                        $result = Database::query($sql);
5771
                                        while ($groupData = Database::fetch_assoc($result)) {
5772
                                            $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5773
                                        }
5774
5775
                                        $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5776
                                                    WHERE
5777
                                                        user_id = ".$teacher['user_id']." AND
5778
                                                        c_id = '".$courseInfo['real_id']."'
5779
                                                    ";
5780
5781
                                        $result = Database::query($sql);
5782
                                        while ($groupData = Database::fetch_assoc($result)) {
5783
                                            $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5784
                                        }
5785
5786
                                        CourseManager::unsubscribe_user(
5787
                                            $teacher['user_id'],
5788
                                            $course_code
5789
                                        );
5790
5791
                                        if ($debug) {
5792
                                            $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5793
                                        }
5794
                                    }
5795
                                }
5796
                            }
5797
5798
                            if (!empty($teacherToAdd)) {
5799
                                self::updateCoaches(
5800
                                    $session_id,
5801
                                    $courseId,
5802
                                    [$teacherToAdd],
5803
                                    true
5804
                                );
5805
5806
                                if ($debug) {
5807
                                    $logger->debug("Add coach #$teacherToAdd to course $courseId and session $session_id");
5808
                                }
5809
5810
                                $userCourseCategory = '';
5811
                                if (isset($teacherBackupList[$teacherToAdd]) &&
5812
                                    isset($teacherBackupList[$teacherToAdd][$course_code])
5813
                                ) {
5814
                                    $courseUserData = $teacherBackupList[$teacherToAdd][$course_code];
5815
                                    $userCourseCategory = $courseUserData['user_course_cat'];
5816
                                }
5817
5818
                                CourseManager::subscribeUser(
5819
                                    $teacherToAdd,
5820
                                    $courseId,
5821
                                    COURSEMANAGER,
5822
                                    0,
5823
                                    $userCourseCategory
5824
                                );
5825
5826
                                if ($debug) {
5827
                                    $logger->debug("Subscribe user #$teacherToAdd as teacher in course $course_code with user userCourseCategory $userCourseCategory");
5828
                                }
5829
5830
                                if (isset($groupBackup['user'][$teacherToAdd]) &&
5831
                                    isset($groupBackup['user'][$teacherToAdd][$course_code]) &&
5832
                                    !empty($groupBackup['user'][$teacherToAdd][$course_code])
5833
                                ) {
5834
                                    foreach ($groupBackup['user'][$teacherToAdd][$course_code] as $data) {
5835
                                        GroupManager::subscribeUsers(
5836
                                            $teacherToAdd,
5837
                                            api_get_group_entity($data['group_id']),
5838
                                            $data['c_id']
5839
                                        );
5840
                                    }
5841
                                }
5842
5843
                                if (isset($groupBackup['tutor'][$teacherToAdd]) &&
5844
                                    isset($groupBackup['tutor'][$teacherToAdd][$course_code]) &&
5845
                                    !empty($groupBackup['tutor'][$teacherToAdd][$course_code])
5846
                                ) {
5847
                                    foreach ($groupBackup['tutor'][$teacherToAdd][$course_code] as $data) {
5848
                                        GroupManager::subscribeTutors(
5849
                                            $teacherToAdd,
5850
                                            api_get_group_entity($data['group_id']),
5851
                                            $data['c_id']
5852
                                        );
5853
                                    }
5854
                                }
5855
                            }
5856
                        }
5857
5858
                        // See BT#6449#note-195
5859
                        // All coaches are added.
5860
                        if ($removeAllTeachersFromCourse) {
5861
                            if ($debug) {
5862
                                $logger->debug("removeAllTeachersFromCourse true");
5863
                            }
5864
                            $teacherToAdd = null;
5865
                            foreach ($course_coaches as $course_coach) {
5866
                                $coach_id = UserManager::get_user_id_from_username(
5867
                                    $course_coach
5868
                                );
5869
                                if (false !== $coach_id) {
5870
                                    $teacherToAdd[] = $coach_id;
5871
                                }
5872
                            }
5873
5874
                            if (!empty($teacherToAdd)) {
5875
                                // Deleting all course teachers and adding the only coach as teacher.
5876
                                $teacherList = CourseManager::get_teacher_list_from_course_code($course_code);
5877
5878
                                if (!empty($teacherList)) {
5879
                                    foreach ($teacherList as $teacher) {
5880
                                        if (!in_array($teacher['user_id'], $teacherToAdd)) {
5881
                                            $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
5882
                                                        WHERE
5883
                                                            user_id = ".$teacher['user_id']." AND
5884
                                                            c_id = '".$courseId."'
5885
                                                        ";
5886
5887
                                            $result = Database::query($sql);
5888
                                            $rows = Database::num_rows($result);
5889
                                            if ($rows > 0) {
5890
                                                $userCourseData = Database::fetch_assoc($result);
5891
                                                if (!empty($userCourseData)) {
5892
                                                    $teacherBackupList[$teacher['user_id']][$course_code] = $userCourseData;
5893
                                                }
5894
                                            }
5895
5896
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
5897
                                                        WHERE
5898
                                                            user_id = ".$teacher['user_id']." AND
5899
                                                            c_id = '".$courseInfo['real_id']."'
5900
                                                        ";
5901
5902
                                            $result = Database::query($sql);
5903
                                            while ($groupData = Database::fetch_assoc($result)) {
5904
                                                $groupBackup['user'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5905
                                            }
5906
5907
                                            $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
5908
                                                        WHERE
5909
                                                            user_id = ".$teacher['user_id']." AND
5910
                                                            c_id = '".$courseInfo['real_id']."'
5911
                                                        ";
5912
5913
                                            $result = Database::query($sql);
5914
                                            while ($groupData = Database::fetch_assoc($result)) {
5915
                                                $groupBackup['tutor'][$teacher['user_id']][$course_code][$groupData['group_id']] = $groupData;
5916
                                            }
5917
5918
                                            CourseManager::unsubscribe_user(
5919
                                                $teacher['user_id'],
5920
                                                $course_code
5921
                                            );
5922
5923
                                            if ($debug) {
5924
                                                $logger->debug("Delete user #".$teacher['user_id']." from base course: $course_code");
5925
                                            }
5926
                                        }
5927
                                    }
5928
                                }
5929
5930
                                foreach ($teacherToAdd as $teacherId) {
5931
                                    $userCourseCategory = '';
5932
                                    if (isset($teacherBackupList[$teacherId]) &&
5933
                                        isset($teacherBackupList[$teacherId][$course_code])
5934
                                    ) {
5935
                                        $courseUserData = $teacherBackupList[$teacherId][$course_code];
5936
                                        $userCourseCategory = $courseUserData['user_course_cat'];
5937
                                    }
5938
5939
                                    CourseManager::subscribeUser(
5940
                                        $teacherId,
5941
                                        $courseInfo['real_id'],
5942
                                        COURSEMANAGER,
5943
                                        0,
5944
                                        $userCourseCategory
5945
                                    );
5946
5947
                                    if ($debug) {
5948
                                        $logger->debug("Add user as teacher #".$teacherId." in base course: $course_code with userCourseCategory: $userCourseCategory");
5949
                                    }
5950
5951
                                    if (isset($groupBackup['user'][$teacherId]) &&
5952
                                        isset($groupBackup['user'][$teacherId][$course_code]) &&
5953
                                        !empty($groupBackup['user'][$teacherId][$course_code])
5954
                                    ) {
5955
                                        foreach ($groupBackup['user'][$teacherId][$course_code] as $data) {
5956
                                            GroupManager::subscribeUsers(
5957
                                                $teacherId,
5958
                                                api_get_group_entity($data['group_id']),
5959
                                                $data['c_id']
5960
                                            );
5961
                                        }
5962
                                    }
5963
5964
                                    if (isset($groupBackup['tutor'][$teacherId]) &&
5965
                                        isset($groupBackup['tutor'][$teacherId][$course_code]) &&
5966
                                        !empty($groupBackup['tutor'][$teacherId][$course_code])
5967
                                    ) {
5968
                                        foreach ($groupBackup['tutor'][$teacherId][$course_code] as $data) {
5969
                                            GroupManager::subscribeTutors(
5970
                                                $teacherId,
5971
                                                api_get_group_entity($data['group_id']),
5972
                                                $data['c_id']
5973
                                            );
5974
                                        }
5975
                                    }
5976
                                }
5977
                            }
5978
                        }
5979
5980
                        // Continue default behaviour.
5981
                        if (false == $onlyAddFirstCoachOrTeacher) {
5982
                            // Checking one more time see BT#6449#note-149
5983
                            $coaches = self::getCoachesByCourseSession($session_id, $courseId);
5984
                            // Update coaches if only there's 1 course see BT#6449#note-189
5985
                            if (empty($coaches) || 1 == count($courses)) {
5986
                                foreach ($course_coaches as $course_coach) {
5987
                                    $course_coach = trim($course_coach);
5988
                                    $coach_id = UserManager::get_user_id_from_username($course_coach);
5989
                                    if (false !== $coach_id) {
5990
                                        // Just insert new coaches
5991
                                        self::updateCoaches(
5992
                                            $session_id,
5993
                                            $courseId,
5994
                                            [$coach_id],
5995
                                            false
5996
                                        );
5997
5998
                                        if ($debug) {
5999
                                            $logger->debug("Sessions - Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
6000
                                        }
6001
                                        $savedCoaches[] = $coach_id;
6002
                                    } else {
6003
                                        $badCoach = trim((string)$course_coach);
6004
                                        $error_message .= get_lang("This user doesn't exist").': "'.$badCoach.'"'.$eol;
6005
                                    }
6006
                                }
6007
                            }
6008
                        }
6009
                    }
6010
6011
                    // Adding Students, updating relationship "Session - Course - User".
6012
                    $course_users = array_filter($course_users);
6013
                    if (!empty($course_users)) {
6014
                        foreach ($course_users as $user) {
6015
                            $user_id = UserManager::get_user_id_from_username($user);
6016
6017
                            if (false !== $user_id) {
6018
                                self::subscribe_users_to_session_course(
6019
                                    [$user_id],
6020
                                    $session_id,
6021
                                    $course_code
6022
                                );
6023
                                if ($debug) {
6024
                                    $logger->debug("Adding student: user #$user_id ($user) to course: '$course_code' and session #$session_id");
6025
                                }
6026
                            } else {
6027
                                $badUser = trim((string)$user);
6028
                                $error_message .= get_lang("This user doesn't exist").': "'.$badUser.'"'.$eol;
6029
                            }
6030
                        }
6031
                    }
6032
                    $inserted_in_course[$course_code] = $courseInfo['title'];
6033
                }
6034
            }
6035
            $access_url_id = api_get_current_access_url_id();
6036
            UrlManager::add_session_to_url($session_id, $access_url_id);
6037
            $sql = "UPDATE $tbl_session SET nbr_users = '$user_counter', nbr_courses = '$course_counter'
6038
                        WHERE id = '$session_id'";
6039
            Database::query($sql);
6040
6041
            self::addClassesByName($session_id, $classes, false);
6042
6043
            if ($debug) {
6044
                $logger->debug("End process session #$session_id -------------------- ");
6045
            }
6046
        }
6047
6048
        if (!empty($report)) {
6049
            if ($debug) {
6050
                $logger->debug("--Summary--");
6051
                foreach ($report as $line) {
6052
                    $logger->debug($line);
6053
                }
6054
            }
6055
        }
6056
6057
        return [
6058
            'error_message' => $error_message,
6059
            'session_counter' => $session_counter,
6060
            'session_list' => $sessionList,
6061
        ];
6062
    }
6063
6064
    /**
6065
     * Imports sessions from an XML file and returns the result of the operation.
6066
     */
6067
    public static function importXML(
6068
        string $file,
6069
        bool $updateSession = false,
6070
        int $defaultUserId = null,
6071
        bool $sendMail = false,
6072
        int $sessionVisibility = SESSION_VISIBLE,
6073
        array &$insertedInCourse = [],
6074
        ?string &$errorMessage = ''
6075
    ): array {
6076
        $defaultUserId = $defaultUserId ?? api_get_user_id();
6077
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
6078
        $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
6079
        $tblSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
6080
        $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6081
6082
        $sessionCounter = 0;
6083
        $sessionList = [];
6084
6085
        $content = file_get_contents($file);
6086
        $content = api_utf8_encode_xml($content);
6087
        $root = @simplexml_load_string($content);
6088
6089
        if (!is_object($root)) {
6090
            $errorMessage .= get_lang('XML document is not valid');
6091
            return [];
6092
        }
6093
6094
        // === USERS ===
6095
        if (isset($root->Users->User)) {
6096
            foreach ($root->Users->User as $nodeUser) {
6097
                $username = trim(api_utf8_decode($nodeUser->Username));
6098
                $password = api_utf8_decode($nodeUser->Password);
6099
                $firstname = api_utf8_decode($nodeUser->Firstname);
6100
                $lastname = api_utf8_decode($nodeUser->Lastname);
6101
                $email = trim(api_utf8_decode($nodeUser->Email));
6102
                $officialCode = trim(api_utf8_decode($nodeUser->OfficialCode));
6103
                $phone = trim(api_utf8_decode($nodeUser->Phone));
6104
                $statusStr = strtolower(trim(api_utf8_decode($nodeUser->Status)));
6105
                $status = $statusStr === 'teacher' ? 1 : 5;
6106
6107
                if (UserManager::is_username_available($username)) {
6108
                    if (empty($password)) {
6109
                        $password = api_generate_password();
6110
                    }
6111
                    UserManager::create_user(
6112
                        $firstname,
6113
                        $lastname,
6114
                        $status,
6115
                        $email,
6116
                        $username,
6117
                        $password,
6118
                        $officialCode,
6119
                        null,
6120
                        $phone,
6121
                        null,
6122
                        [UserAuthSource::PLATFORM],
6123
                        null,
6124
                        1,
6125
                        0,
6126
                        null,
6127
                        null,
6128
                        $sendMail
6129
                    );
6130
                } else {
6131
                    $userId = UserManager::get_user_id_from_username($username);
6132
                    if ($userId) {
6133
                        UserManager::update_user(
6134
                            $userId,
6135
                            $firstname,
6136
                            $lastname,
6137
                            $username,
6138
                            $password,
6139
                            [],
6140
                            $email,
6141
                            $status,
6142
                            $officialCode,
6143
                            $phone,
6144
                            null,
6145
                            null,
6146
                            1,
6147
                            null,
6148
                            0
6149
                        );
6150
                    }
6151
                }
6152
            }
6153
        }
6154
6155
        // === COURSES ===
6156
        if (isset($root->Courses->Course)) {
6157
            foreach ($root->Courses->Course as $nodeCourse) {
6158
                $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6159
                $courseTitle = api_utf8_decode($nodeCourse->CourseTitle ?: $courseCode);
6160
                $courseLang = api_utf8_decode($nodeCourse->CourseLanguage);
6161
                $teacherUsername = trim(api_utf8_decode($nodeCourse->CourseTeacher));
6162
6163
                $teacherId = UserManager::get_user_id_from_username($teacherUsername) ?: $defaultUserId;
6164
6165
                if (!CourseManager::course_exists($courseCode)) {
6166
                    CourseManager::create_course([
6167
                        'wanted_code' => $courseCode,
6168
                        'title' => $courseTitle,
6169
                        'course_language' => $courseLang,
6170
                        'user_id' => $defaultUserId,
6171
                        'teachers' => $teacherId,
6172
                    ]);
6173
                }
6174
            }
6175
        }
6176
6177
        // === SESSIONS ===
6178
        if (isset($root->Session)) {
6179
            foreach ($root->Session as $nodeSession) {
6180
                $sessionName = trim(api_utf8_decode($nodeSession->SessionName));
6181
                $coachUsername = trim(api_utf8_decode($nodeSession->Coach));
6182
                $coachId = UserManager::get_user_id_from_username($coachUsername) ?: $defaultUserId;
6183
                $dateStart = api_utf8_decode($nodeSession->DateStart);
6184
                $dateEnd = api_utf8_decode($nodeSession->DateEnd);
6185
                $sessionCategoryId = (int) trim(api_utf8_decode($nodeSession->SessionCategory));
6186
                $categoryExists = false;
6187
                if (!empty($sessionCategoryId)) {
6188
                    $result = Database::select(
6189
                        'id',
6190
                        Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
6191
                        ['where' => ['id = ?' => $sessionCategoryId]],
6192
                        'first'
6193
                    );
6194
6195
                    $categoryExists = !empty($result);
6196
                }
6197
                if (!$categoryExists) {
6198
                    $sessionCategoryId = null;
6199
                }
6200
                $visibilityStr = strtolower(api_utf8_decode($nodeSession->VisibilityAfterExpiration));
6201
                $visibility = match ($visibilityStr) {
6202
                    'read_only' => SESSION_VISIBLE_READ_ONLY,
6203
                    'not_accessible' => SESSION_INVISIBLE,
6204
                    default => $sessionVisibility,
6205
                };
6206
6207
                // Normalize dates
6208
                $dateStart = date('Y-m-d H:i:s', strtotime($dateStart));
6209
                $dateEnd = date('Y-m-d H:i:s', strtotime($dateEnd));
6210
6211
                $sessionId = null;
6212
                $mySession = SessionManager::get_session_by_name($sessionName);
6213
6214
                if ($updateSession && $mySession) {
6215
                    $sessionId = $mySession['id'];
6216
                    Database::update($tblSession, [
6217
                        'access_start_date' => $dateStart,
6218
                        'access_end_date' => $dateEnd,
6219
                        'visibility' => $visibility,
6220
                        'session_category_id' => $sessionCategoryId,
6221
                    ], ['id = ?' => $sessionId]);
6222
6223
                    Database::query("DELETE FROM $tblSessionUser WHERE session_id = $sessionId");
6224
                    Database::query("DELETE FROM $tblSessionCourse WHERE session_id = $sessionId");
6225
                    Database::query("DELETE FROM $tblSessionCourseUser WHERE session_id = $sessionId");
6226
                } else {
6227
                    $sessionId = Database::insert($tblSession, [
6228
                        'title' => $sessionName,
6229
                        'access_start_date' => $dateStart,
6230
                        'access_end_date' => $dateEnd,
6231
                        'visibility' => $visibility,
6232
                        'nbr_users' => 0,
6233
                        'nbr_courses' => 0,
6234
                        'nbr_classes' => 0,
6235
                        'status' => 0,
6236
                        'duration' => 0,
6237
                        'session_category_id' => $sessionCategoryId,
6238
                    ]);
6239
                }
6240
6241
                if ($sessionId) {
6242
                    Database::insert($tblSessionUser, [
6243
                        'user_id' => $coachId,
6244
                        'session_id' => $sessionId,
6245
                        'registered_at' => api_get_utc_datetime(),
6246
                        'relation_type' => Session::GENERAL_COACH,
6247
                        'duration' => 0,
6248
                    ], false, ['ignore' => true]);
6249
6250
                    Database::insert($tblSessionUser, [
6251
                        'user_id' => $defaultUserId,
6252
                        'session_id' => $sessionId,
6253
                        'registered_at' => api_get_utc_datetime(),
6254
                        'relation_type' => Session::SESSION_ADMIN,
6255
                        'duration' => 0,
6256
                    ], false, ['ignore' => true]);
6257
                    $sessionCounter++;
6258
                    $sessionList[] = $sessionId;
6259
                }
6260
6261
                // Add Users to session
6262
                foreach ($nodeSession->User as $nodeUser) {
6263
                    $username = UserManager::purify_username(api_utf8_decode($nodeUser));
6264
                    $userId = UserManager::get_user_id_from_username($username);
6265
                    if ($userId) {
6266
                        Database::insert($tblSessionUser, [
6267
                            'user_id' => $userId,
6268
                            'session_id' => $sessionId,
6269
                            'relation_type' => Session::STUDENT,
6270
                            'duration' => 0,
6271
                            'registered_at' => api_get_utc_datetime(),
6272
                        ], false, ['ignore' => true]);
6273
                    }
6274
                }
6275
6276
                // Add Courses to session
6277
                foreach ($nodeSession->Course as $nodeCourse) {
6278
                    $courseCode = api_utf8_decode($nodeCourse->CourseCode);
6279
                    $courseInfo = api_get_course_info($courseCode);
6280
                    if ($courseInfo) {
6281
                        $courseId = $courseInfo['real_id'];
6282
                        Database::insert($tblSessionCourse, [
6283
                            'c_id' => $courseId,
6284
                            'session_id' => $sessionId,
6285
                            'nbr_users' => 0,
6286
                            'position' => 0,
6287
                        ]);
6288
                        $courseCoachUsernames = explode(',', $nodeCourse->Coach);
6289
                        foreach ($courseCoachUsernames as $coachUname) {
6290
                            $coachId = UserManager::get_user_id_from_username(trim($coachUname));
6291
                            if ($coachId) {
6292
                                Database::insert($tblSessionCourseUser, [
6293
                                    'user_id' => $coachId,
6294
                                    'c_id' => $courseId,
6295
                                    'session_id' => $sessionId,
6296
                                    'status' => Session::COURSE_COACH,
6297
                                    'visibility' => 1,
6298
                                    'legal_agreement' => 0,
6299
                                    'progress' => 0,
6300
                                ]);
6301
                            }
6302
                        }
6303
6304
                        // Users in the course
6305
                        $userCounter = 0;
6306
                        foreach ($nodeCourse->User as $userNode) {
6307
                            $username = UserManager::purify_username(api_utf8_decode($userNode));
6308
                            $userId = UserManager::get_user_id_from_username($username);
6309
                            if ($userId) {
6310
                                Database::insert($tblSessionUser, [
6311
                                    'user_id' => $userId,
6312
                                    'session_id' => $sessionId,
6313
                                    'registered_at' => api_get_utc_datetime(),
6314
                                    'duration' => 0,
6315
                                    'relation_type' => Session::STUDENT
6316
                                ], false, ['ignore' => true]);
6317
                                Database::insert($tblSessionCourseUser, [
6318
                                    'user_id' => $userId,
6319
                                    'c_id' => $courseId,
6320
                                    'session_id' => $sessionId,
6321
                                    'status' => Session::STUDENT,
6322
                                    'visibility' => 1,
6323
                                    'legal_agreement' => 0,
6324
                                    'progress' => 0,
6325
                                ]);
6326
                                $userCounter++;
6327
                            }
6328
                        }
6329
6330
                        Database::update(
6331
                            $tblSessionCourse,
6332
                            ['nbr_users' => $userCounter],
6333
                            ['c_id = ? AND session_id = ?' => [$courseId, $sessionId]],
6334
                        );
6335
                    }
6336
                }
6337
6338
                Database::update($tblSession, [
6339
                    'nbr_users' => count($nodeSession->User),
6340
                    'nbr_courses' => count($nodeSession->Course),
6341
                ], ['id = ?' => $sessionId]);
6342
6343
                UrlManager::add_session_to_url($sessionId, api_get_current_access_url_id());
6344
            }
6345
        }
6346
6347
        return [
6348
            'session_counter' => $sessionCounter,
6349
            'session_list' => $sessionList,
6350
        ];
6351
    }
6352
6353
    /**
6354
     * Normalizes the end date format to include time if missing.
6355
     */
6356
    private static function normalizeDateEnd(string $date): string
6357
    {
6358
        $dt = new \DateTime(trim($date));
6359
        if ($dt->format('H:i:s') === '00:00:00') {
6360
            $dt->setTime(23, 59, 59);
6361
        }
6362
        return $dt->format('Y-m-d H:i:s');
6363
    }
6364
6365
    /**
6366
     * @param int $sessionId
6367
     * @param int $courseId
6368
     *
6369
     * @return array
6370
     */
6371
    public static function getCoachesByCourseSession($sessionId, $courseId)
6372
    {
6373
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6374
        $sessionId = (int) $sessionId;
6375
        $courseId = (int) $courseId;
6376
6377
        $sql = "SELECT user_id FROM $table
6378
                WHERE
6379
                    session_id = '$sessionId' AND
6380
                    c_id = '$courseId' AND
6381
                    status = ".Session::COURSE_COACH;
6382
        $result = Database::query($sql);
6383
6384
        $coaches = [];
6385
        if (Database::num_rows($result) > 0) {
6386
            while ($row = Database::fetch_array($result)) {
6387
                $coaches[] = $row['user_id'];
6388
            }
6389
        }
6390
6391
        return $coaches;
6392
    }
6393
6394
    /**
6395
     * @param int    $sessionId
6396
     * @param int    $courseId
6397
     * @param string $separator
6398
     *
6399
     * @return string
6400
     */
6401
    public static function getCoachesByCourseSessionToString(
6402
        $sessionId,
6403
        $courseId,
6404
        $separator = ''
6405
    ) {
6406
        $coaches = self::getCoachesByCourseSession($sessionId, $courseId);
6407
        $list = [];
6408
        if (!empty($coaches)) {
6409
            foreach ($coaches as $coachId) {
6410
                $userInfo = api_get_user_info($coachId);
6411
                if ($userInfo) {
6412
                    $list[] = $userInfo['complete_name'];
6413
                }
6414
            }
6415
        }
6416
6417
        $separator = empty($separator) ? CourseManager::USER_SEPARATOR : $separator;
6418
6419
        return array_to_string($list, $separator);
6420
    }
6421
6422
    /**
6423
     * Get all coaches added in the session - course relationship.
6424
     *
6425
     * @param int $sessionId
6426
     *
6427
     * @return array
6428
     */
6429
    public static function getCoachesBySession($sessionId)
6430
    {
6431
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6432
        $sessionId = intval($sessionId);
6433
6434
        $sql = "SELECT DISTINCT user_id
6435
                FROM $table
6436
                WHERE session_id = '$sessionId' AND status = ".Session::COURSE_COACH;
6437
        $result = Database::query($sql);
6438
6439
        $coaches = [];
6440
        if (Database::num_rows($result) > 0) {
6441
            while ($row = Database::fetch_array($result)) {
6442
                $coaches[] = $row['user_id'];
6443
            }
6444
        }
6445
6446
        return $coaches;
6447
    }
6448
6449
    /**
6450
     * @param int $userId
6451
     *
6452
     * @return array
6453
     */
6454
    public static function getAllCoursesFromAllSessionFromDrh($userId)
6455
    {
6456
        $sessions = self::get_sessions_followed_by_drh($userId);
6457
        $coursesFromSession = [];
6458
        if (!empty($sessions)) {
6459
            foreach ($sessions as $session) {
6460
                $courseList = self::get_course_list_by_session_id($session['id']);
6461
                foreach ($courseList as $course) {
6462
                    $coursesFromSession[] = $course['code'];
6463
                }
6464
            }
6465
        }
6466
6467
        return $coursesFromSession;
6468
    }
6469
6470
    /**
6471
     * getAllCoursesFromAllSessions.
6472
     *
6473
     * @return array
6474
     */
6475
    public static function getAllCoursesFromAllSessions()
6476
    {
6477
        $sessions = self::get_sessions_list();
6478
        $coursesFromSession = [];
6479
        if (!empty($sessions)) {
6480
            foreach ($sessions as $session) {
6481
                $courseList = self::get_course_list_by_session_id($session['id']);
6482
                foreach ($courseList as $course) {
6483
                    $coursesFromSession[$course['code'].':'.$session['id']] = $course['visual_code'].' - '.$course['title'].' ('.$session['title'].')';
6484
                }
6485
            }
6486
        }
6487
6488
        return $coursesFromSession;
6489
    }
6490
6491
    /**
6492
     * Return user id list or count of users depending of the $getCount parameter.
6493
     *
6494
     * @param string $status
6495
     * @param int    $userId
6496
     * @param bool   $getCount
6497
     * @param int    $from
6498
     * @param int    $numberItems
6499
     * @param string $column
6500
     * @param string $direction
6501
     * @param string $keyword
6502
     * @param string $active
6503
     * @param string $lastConnectionDate
6504
     * @param array  $sessionIdList
6505
     * @param array  $studentIdList
6506
     * @param int    $filterByStatus
6507
     *
6508
     * @return array|int
6509
     */
6510
    public static function getAllUsersFromCoursesFromAllSessionFromStatus(
6511
        $status,
6512
        $userId,
6513
        $getCount = false,
6514
        $from = null,
6515
        $numberItems = null,
6516
        $column = '',
6517
        $direction = 'asc',
6518
        $keyword = null,
6519
        $active = null,
6520
        $lastConnectionDate = null,
6521
        $sessionIdList = [],
6522
        $studentIdList = [],
6523
        $filterByStatus = null
6524
    ) {
6525
        $filterByStatus = (int) $filterByStatus;
6526
        $userId = (int) $userId;
6527
6528
        if (empty($column)) {
6529
            $column = 'u.lastname';
6530
            if (api_is_western_name_order()) {
6531
                $column = 'u.firstname';
6532
            }
6533
        }
6534
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
6535
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
6536
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
6537
        $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
6538
        $tbl_user_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
6539
        $tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
6540
        $tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
6541
        $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
6542
6543
        $direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : 'asc';
6544
        $column = Database::escape_string($column);
6545
6546
        $urlId = api_get_current_access_url_id();
6547
6548
        $sessionConditions = '';
6549
        $courseConditions = '';
6550
        $userConditions = ' AND u.active <> '.USER_SOFT_DELETED.' ';
6551
6552
        if (isset($active)) {
6553
            $active = (int) $active;
6554
            $userConditions .= " AND active = $active";
6555
        }
6556
6557
        $courseList = CourseManager::get_courses_followed_by_drh($userId, DRH);
6558
        if (!empty($courseList)) {
6559
            $courseIdList = array_column($courseList, 'id');
6560
            $courseConditions = ' AND c.id IN ("'.implode('","', $courseIdList).'")';
6561
        }
6562
6563
        $userConditionsFromDrh = '';
6564
6565
        // Classic DRH
6566
        if (empty($studentIdList)) {
6567
            $studentListSql = UserManager::get_users_followed_by_drh(
6568
                $userId,
6569
                $filterByStatus,
6570
                true,
6571
                false
6572
            );
6573
            if (!empty($studentListSql)) {
6574
                $studentIdList = array_keys($studentListSql);
6575
                $studentListSql = "'".implode("','", $studentIdList)."'";
6576
            }
6577
        } else {
6578
            $studentIdList = array_map('intval', $studentIdList);
6579
            $studentListSql = "'".implode("','", $studentIdList)."'";
6580
        }
6581
        if (!empty($studentListSql)) {
6582
            $userConditionsFromDrh = " AND u.id IN ($studentListSql) ";
6583
        }
6584
6585
        switch ($status) {
6586
            case 'admin':
6587
            case 'drh':
6588
                break;
6589
            case 'drh_all':
6590
                // Show all by DRH
6591
                if (empty($sessionIdList)) {
6592
                    $sessionListFollowed = self::get_sessions_followed_by_drh(
6593
                        $userId,
6594
                        null,
6595
                        null,
6596
                        false,
6597
                        true
6598
                    );
6599
6600
                    if (!empty($sessionListFollowed)) {
6601
                        $sessionIdList = array_column($sessionListFollowed, 'id');
6602
                    }
6603
                }
6604
6605
                if (!empty($sessionIdList)) {
6606
                    $sessionIdList = array_map('intval', $sessionIdList);
6607
                    $sessionsListSql = "'".implode("','", $sessionIdList)."'";
6608
                    $sessionConditions = " AND s.id IN ($sessionsListSql) ";
6609
                }
6610
6611
                break;
6612
            case 'teacher':
6613
            case 'session_admin':
6614
                $generalCoachedSessions = array_map(
6615
                    fn(Session $session) => $session->getId(),
6616
                    api_get_user_entity($userId)->getSessionsAsGeneralCoach()
6617
                );
6618
6619
                $sessionConditions = " AND s.IN (".implode(',', $generalCoachedSessions).") ";
6620
                $userConditionsFromDrh = '';
6621
                break;
6622
        }
6623
6624
        $select = 'SELECT DISTINCT u.*, u.id as user_id';
6625
        $masterSelect = 'SELECT DISTINCT id, id as user_id FROM ';
6626
6627
        if ($getCount) {
6628
            $select = 'SELECT DISTINCT u.id, u.id as user_id';
6629
            $masterSelect = 'SELECT COUNT(DISTINCT(id)) as count FROM ';
6630
        }
6631
6632
        if (!empty($filterByStatus)) {
6633
            $userConditions .= " AND u.status = $filterByStatus";
6634
        }
6635
6636
        if (!empty($lastConnectionDate)) {
6637
            $lastConnectionDate = Database::escape_string($lastConnectionDate);
6638
            $userConditions .= " AND u.last_login <= '$lastConnectionDate' ";
6639
        }
6640
6641
        if (!empty($keyword)) {
6642
            $keyword = Database::escape_string($keyword);
6643
            $userConditions .= " AND (
6644
                u.username LIKE '%$keyword%' OR
6645
                u.firstname LIKE '%$keyword%' OR
6646
                u.lastname LIKE '%$keyword%' OR
6647
                u.official_code LIKE '%$keyword%' OR
6648
                u.email LIKE '%$keyword%'
6649
            )";
6650
        }
6651
6652
        $where = " WHERE
6653
                   access_url_id = $urlId
6654
                   $userConditions
6655
        ";
6656
6657
        $userUnion = '';
6658
        if (!empty($userConditionsFromDrh)) {
6659
            $userUnion = "
6660
            UNION (
6661
                $select
6662
                FROM $tbl_user u
6663
                INNER JOIN $tbl_user_rel_access_url url
6664
                ON (url.user_id = u.id)
6665
                $where
6666
                $userConditionsFromDrh
6667
            )";
6668
        }
6669
6670
        $sql = "$masterSelect (
6671
                ($select
6672
                FROM $tbl_session s
6673
                    INNER JOIN $tbl_session_rel_access_url url
6674
                    ON (url.session_id = s.id)
6675
                    INNER JOIN $tbl_session_rel_course_rel_user su
6676
                    ON (s.id = su.session_id)
6677
                    INNER JOIN $tbl_user u
6678
                    ON (u.id = su.user_id)
6679
                    $where
6680
                    $sessionConditions
6681
                    $userConditionsFromDrh
6682
                ) UNION (
6683
                    $select
6684
                    FROM $tbl_course c
6685
                    INNER JOIN $tbl_course_rel_access_url url
6686
                    ON (url.c_id = c.id)
6687
                    INNER JOIN $tbl_course_user cu
6688
                    ON (cu.c_id = c.id)
6689
                    INNER JOIN $tbl_user u
6690
                    ON (u.id = cu.user_id)
6691
                    $where
6692
                    $courseConditions
6693
                    $userConditionsFromDrh
6694
                ) $userUnion
6695
                ) as t1
6696
                ";
6697
6698
        if ($getCount) {
6699
            $result = Database::query($sql);
6700
6701
            $count = 0;
6702
            if (Database::num_rows($result)) {
6703
                $rows = Database::fetch_array($result);
6704
                $count = $rows['count'];
6705
            }
6706
6707
            return $count;
6708
        }
6709
6710
        if (!empty($column) && !empty($direction)) {
6711
            $column = str_replace('u.', '', $column);
6712
            $sql .= " ORDER BY `$column` $direction ";
6713
        }
6714
6715
        $limitCondition = '';
6716
        if (isset($from) && isset($numberItems)) {
6717
            $from = (int) $from;
6718
            $numberItems = (int) $numberItems;
6719
            $limitCondition = "LIMIT $from, $numberItems";
6720
        }
6721
6722
        $sql .= $limitCondition;
6723
        $result = Database::query($sql);
6724
6725
        return Database::store_result($result);
6726
    }
6727
6728
    /**
6729
     * @param int   $sessionId
6730
     * @param int   $courseId
6731
     * @param array $coachList
6732
     * @param bool  $deleteCoachesNotInList
6733
     */
6734
    public static function updateCoaches(
6735
        $sessionId,
6736
        $courseId,
6737
        $coachList,
6738
        $deleteCoachesNotInList = false
6739
    ) {
6740
        $currentCoaches = self::getCoachesByCourseSession($sessionId, $courseId);
6741
6742
        if (!empty($coachList)) {
6743
            foreach ($coachList as $userId) {
6744
                self::set_coach_to_course_session($userId, $sessionId, $courseId);
6745
            }
6746
        }
6747
6748
        if ($deleteCoachesNotInList) {
6749
            if (!empty($coachList)) {
6750
                $coachesToDelete = array_diff($currentCoaches, $coachList);
6751
            } else {
6752
                $coachesToDelete = $currentCoaches;
6753
            }
6754
6755
            if (!empty($coachesToDelete)) {
6756
                foreach ($coachesToDelete as $userId) {
6757
                    self::set_coach_to_course_session(
6758
                        $userId,
6759
                        $sessionId,
6760
                        $courseId,
6761
                        true
6762
                    );
6763
                }
6764
            }
6765
        }
6766
    }
6767
6768
    /**
6769
     * @param array $sessions
6770
     * @param array $sessionsDestination
6771
     *
6772
     * @return array
6773
     */
6774
    public static function copyStudentsFromSession($sessions, $sessionsDestination)
6775
    {
6776
        $messages = [];
6777
        if (!empty($sessions)) {
6778
            foreach ($sessions as $sessionId) {
6779
                $sessionInfo = self::fetch($sessionId);
6780
                $userList = self::get_users_by_session($sessionId, 0);
6781
                if (!empty($userList)) {
6782
                    $newUserList = [];
6783
                    $userToString = null;
6784
                    foreach ($userList as $userInfo) {
6785
                        $newUserList[] = $userInfo['user_id'];
6786
                        $userToString .= $userInfo['firstname'].' '.$userInfo['lastname'].'<br />';
6787
                    }
6788
6789
                    if (!empty($sessionsDestination)) {
6790
                        foreach ($sessionsDestination as $sessionDestinationId) {
6791
                            $sessionDestinationInfo = self::fetch($sessionDestinationId);
6792
                            $messages[] = Display::return_message(
6793
                                sprintf(
6794
                                    get_lang(
6795
                                        'AddingStudentsFromSessionXToSessionY'
6796
                                    ),
6797
                                    $sessionInfo['title'],
6798
                                    $sessionDestinationInfo['title']
6799
                                ),
6800
                                'info',
6801
                                false
6802
                            );
6803
                            if ($sessionId == $sessionDestinationId) {
6804
                                $messages[] = Display::return_message(
6805
                                    sprintf(
6806
                                        get_lang('Session %s skipped'),
6807
                                        $sessionDestinationId
6808
                                    ),
6809
                                    'warning',
6810
                                    false
6811
                                );
6812
                                continue;
6813
                            }
6814
                            $messages[] = Display::return_message(get_lang('Learner list').'<br />'.$userToString, 'info', false);
6815
                            self::subscribeUsersToSession(
6816
                                $sessionDestinationId,
6817
                                $newUserList,
6818
                                SESSION_VISIBLE_READ_ONLY,
6819
                                false
6820
                            );
6821
                        }
6822
                    } else {
6823
                        $messages[] = Display::return_message(get_lang('No destination session provided'), 'warning');
6824
                    }
6825
                } else {
6826
                    $messages[] = Display::return_message(
6827
                        get_lang('No student found for the session').' #'.$sessionInfo['title'],
6828
                        'warning'
6829
                    );
6830
                }
6831
            }
6832
        } else {
6833
            $messages[] = Display::return_message(get_lang('No data available'), 'warning');
6834
        }
6835
6836
        return $messages;
6837
    }
6838
6839
    /**
6840
     * Assign coaches of a session(s) as teachers to a given course (or courses).
6841
     *
6842
     * @param array A list of session IDs
6843
     * @param array A list of course IDs
6844
     *
6845
     * @return string
6846
     */
6847
    public static function copyCoachesFromSessionToCourse($sessions, $courses)
6848
    {
6849
        $coachesPerSession = [];
6850
        foreach ($sessions as $sessionId) {
6851
            $coaches = self::getCoachesBySession($sessionId);
6852
            $coachesPerSession[$sessionId] = $coaches;
6853
        }
6854
6855
        $result = [];
6856
6857
        if (!empty($courses)) {
6858
            foreach ($courses as $courseId) {
6859
                $courseInfo = api_get_course_info_by_id($courseId);
6860
                foreach ($coachesPerSession as $sessionId => $coachList) {
6861
                    CourseManager::updateTeachers(
6862
                        $courseInfo,
6863
                        $coachList,
6864
                        false,
6865
                        false,
6866
                        false
6867
                    );
6868
                    $result[$courseInfo['code']][$sessionId] = $coachList;
6869
                }
6870
            }
6871
        }
6872
        $sessionUrl = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session=';
6873
        $htmlResult = null;
6874
6875
        if (!empty($result)) {
6876
            foreach ($result as $courseCode => $data) {
6877
                $url = api_get_course_url($courseCode);
6878
                $htmlResult .= sprintf(
6879
                    get_lang('Coaches subscribed as teachers in course %s'),
6880
                    Display::url($courseCode, $url, ['target' => '_blank'])
6881
                );
6882
                foreach ($data as $sessionId => $coachList) {
6883
                    $sessionInfo = self::fetch($sessionId);
6884
                    $htmlResult .= '<br />';
6885
                    $htmlResult .= Display::url(
6886
                        get_lang('Session').': '.$sessionInfo['title'].' <br />',
6887
                        $sessionUrl.$sessionId,
6888
                        ['target' => '_blank']
6889
                    );
6890
                    $teacherList = [];
6891
                    foreach ($coachList as $coachId) {
6892
                        $userInfo = api_get_user_info($coachId);
6893
                        $teacherList[] = $userInfo['complete_name'];
6894
                    }
6895
                    if (!empty($teacherList)) {
6896
                        $htmlResult .= implode(', ', $teacherList);
6897
                    } else {
6898
                        $htmlResult .= get_lang('Nothing to add');
6899
                    }
6900
                }
6901
                $htmlResult .= '<br />';
6902
            }
6903
            $htmlResult = Display::return_message($htmlResult, 'normal', false);
6904
        }
6905
6906
        return $htmlResult;
6907
    }
6908
6909
    /**
6910
     * @param string $keyword
6911
     * @param string $active
6912
     * @param string $lastConnectionDate
6913
     * @param array  $sessionIdList
6914
     * @param array  $studentIdList
6915
     * @param int    $filterUserStatus   STUDENT|COURSEMANAGER constants
6916
     *
6917
     * @return array|int
6918
     */
6919
    public static function getCountUserTracking(
6920
        $keyword = null,
6921
        $active = null,
6922
        $lastConnectionDate = null,
6923
        $sessionIdList = [],
6924
        $studentIdList = [],
6925
        $filterUserStatus = null
6926
    ) {
6927
        $userId = api_get_user_id();
6928
        $drhLoaded = false;
6929
6930
        if (api_is_drh()) {
6931
            if (api_drh_can_access_all_session_content()) {
6932
                $count = self::getAllUsersFromCoursesFromAllSessionFromStatus(
6933
                    'drh_all',
6934
                    $userId,
6935
                    true,
6936
                    null,
6937
                    null,
6938
                    null,
6939
                    null,
6940
                    $keyword,
6941
                    $active,
6942
                    $lastConnectionDate,
6943
                    $sessionIdList,
6944
                    $studentIdList,
6945
                    $filterUserStatus
6946
                );
6947
                $drhLoaded = true;
6948
            }
6949
        }
6950
6951
        if (false == $drhLoaded) {
6952
            $count = UserManager::getUsersFollowedByUser(
6953
                $userId,
6954
                $filterUserStatus,
6955
                false,
6956
                false,
6957
                true,
6958
                null,
6959
                null,
6960
                null,
6961
                null,
6962
                $active,
6963
                $lastConnectionDate,
6964
                api_is_student_boss() ? STUDENT_BOSS : COURSEMANAGER,
6965
                $keyword
6966
            );
6967
        }
6968
6969
        return $count;
6970
    }
6971
6972
    /**
6973
     * Get teachers followed by a user.
6974
     *
6975
     * @param int    $userId
6976
     * @param int    $active
6977
     * @param string $lastConnectionDate
6978
     * @param bool   $getCount
6979
     * @param array  $sessionIdList
6980
     *
6981
     * @return array|int
6982
     */
6983
    public static function getTeacherTracking(
6984
        $userId,
6985
        $active = 1,
6986
        $lastConnectionDate = null,
6987
        $getCount = false,
6988
        $sessionIdList = []
6989
    ) {
6990
        $teacherListId = [];
6991
        if (api_is_drh() || api_is_platform_admin()) {
6992
            // Followed teachers by drh
6993
            if (api_drh_can_access_all_session_content()) {
6994
                if (empty($sessionIdList)) {
6995
                    $sessions = self::get_sessions_followed_by_drh($userId);
6996
                    $sessionIdList = [];
6997
                    foreach ($sessions as $session) {
6998
                        $sessionIdList[] = $session['id'];
6999
                    }
7000
                }
7001
7002
                $sessionIdList = array_map('intval', $sessionIdList);
7003
                $sessionToString = implode("', '", $sessionIdList);
7004
7005
                $course = Database::get_main_table(TABLE_MAIN_COURSE);
7006
                $sessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7007
                $courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
7008
7009
                // Select the teachers.
7010
                $sql = "SELECT DISTINCT(cu.user_id)
7011
                        FROM $course c
7012
                        INNER JOIN $sessionCourse src
7013
                        ON c.id = src.c_id
7014
                        INNER JOIN $courseUser cu
7015
                        ON (cu.c_id = c.id)
7016
		                WHERE src.session_id IN ('$sessionToString') AND cu.status = 1";
7017
                $result = Database::query($sql);
7018
                while ($row = Database::fetch_assoc($result)) {
7019
                    $teacherListId[$row['user_id']] = $row['user_id'];
7020
                }
7021
            } else {
7022
                $teacherResult = UserManager::get_users_followed_by_drh($userId, COURSEMANAGER);
7023
                foreach ($teacherResult as $userInfo) {
7024
                    $teacherListId[] = $userInfo['user_id'];
7025
                }
7026
            }
7027
        }
7028
7029
        if (!empty($teacherListId)) {
7030
            $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7031
7032
            $select = "SELECT DISTINCT u.* ";
7033
            if ($getCount) {
7034
                $select = "SELECT count(DISTINCT(u.id)) as count";
7035
            }
7036
7037
            $sql = "$select FROM $tableUser u";
7038
7039
            if (!empty($lastConnectionDate)) {
7040
                $tableLogin = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7041
                //$sql .= " INNER JOIN $tableLogin l ON (l.login_user_id = u.user_id) ";
7042
            }
7043
            $active = intval($active);
7044
            $teacherListId = implode("','", $teacherListId);
7045
            $where = " WHERE u.active = $active AND u.id IN ('$teacherListId') ";
7046
7047
            if (!empty($lastConnectionDate)) {
7048
                $lastConnectionDate = Database::escape_string($lastConnectionDate);
7049
                //$where .= " AND l.login_date <= '$lastConnectionDate' ";
7050
            }
7051
7052
            $sql .= $where;
7053
            $result = Database::query($sql);
7054
            if (Database::num_rows($result)) {
7055
                if ($getCount) {
7056
                    $row = Database::fetch_array($result);
7057
7058
                    return $row['count'];
7059
                } else {
7060
                    return Database::store_result($result, 'ASSOC');
7061
                }
7062
            }
7063
        }
7064
7065
        return 0;
7066
    }
7067
7068
    /**
7069
     * Get the list of course tools that have to be dealt with in case of
7070
     * registering any course to a session.
7071
     *
7072
     * @return array The list of tools to be dealt with (literal names)
7073
     */
7074
    public static function getCourseToolToBeManaged()
7075
    {
7076
        return [
7077
            'courseDescription',
7078
            'courseIntroduction',
7079
        ];
7080
    }
7081
7082
    /**
7083
     * Calls the methods bound to each tool when a course is registered into a session.
7084
     *
7085
     * @param int $sessionId
7086
     * @param int $courseId
7087
     *
7088
     * @return bool
7089
     */
7090
    public static function installCourse($sessionId, $courseId)
7091
    {
7092
        return true;
7093
        $toolList = self::getCourseToolToBeManaged();
0 ignored issues
show
Unused Code introduced by
$toolList = self::getCourseToolToBeManaged() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
7094
7095
        foreach ($toolList as $tool) {
7096
            $method = 'add'.$tool;
7097
            if (method_exists(get_class(), $method)) {
7098
                self::$method($sessionId, $courseId);
7099
            }
7100
        }
7101
    }
7102
7103
    /**
7104
     * Calls the methods bound to each tool when a course is unregistered from
7105
     * a session.
7106
     *
7107
     * @param int $sessionId
7108
     * @param int $courseId
7109
     */
7110
    public static function unInstallCourse($sessionId, $courseId)
7111
    {
7112
        return true;
7113
        $toolList = self::getCourseToolToBeManaged();
0 ignored issues
show
Unused Code introduced by
$toolList = self::getCourseToolToBeManaged() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
7114
7115
        foreach ($toolList as $tool) {
7116
            $method = 'remove'.$tool;
7117
            if (method_exists(get_class(), $method)) {
7118
                self::$method($sessionId, $courseId);
7119
            }
7120
        }
7121
    }
7122
7123
    /**
7124
     * @param array $userSessionList        format see self::importSessionDrhCSV()
7125
     * @param bool  $sendEmail
7126
     * @param bool  $removeOldRelationShips
7127
     */
7128
    public static function subscribeDrhToSessionList(
7129
        $userSessionList,
7130
        $sendEmail,
7131
        $removeOldRelationShips
7132
    ) {
7133
        if (!empty($userSessionList)) {
7134
            foreach ($userSessionList as $userId => $data) {
7135
                $sessionList = [];
7136
                foreach ($data['session_list'] as $sessionInfo) {
7137
                    $sessionList[] = $sessionInfo['session_id'];
7138
                }
7139
                $userInfo = $data['user_info'];
7140
                self::subscribeSessionsToDrh(
7141
                    $userInfo,
7142
                    $sessionList,
7143
                    $sendEmail,
7144
                    $removeOldRelationShips
7145
                );
7146
            }
7147
        }
7148
    }
7149
7150
    /**
7151
     * @param array $userSessionList format see self::importSessionDrhCSV()
7152
     *
7153
     * @return string
7154
     */
7155
    public static function checkSubscribeDrhToSessionList($userSessionList)
7156
    {
7157
        $message = null;
7158
        if (!empty($userSessionList)) {
7159
            if (!empty($userSessionList)) {
7160
                foreach ($userSessionList as $userId => $data) {
7161
                    $userInfo = $data['user_info'];
7162
7163
                    $sessionListSubscribed = self::get_sessions_followed_by_drh($userId);
7164
                    if (!empty($sessionListSubscribed)) {
7165
                        $sessionListSubscribed = array_keys($sessionListSubscribed);
7166
                    }
7167
7168
                    $sessionList = [];
7169
                    if (!empty($data['session_list'])) {
7170
                        foreach ($data['session_list'] as $sessionInfo) {
7171
                            if (in_array($sessionInfo['session_id'], $sessionListSubscribed)) {
7172
                                $sessionList[] = $sessionInfo['session_info']['title'];
7173
                            }
7174
                        }
7175
                    }
7176
7177
                    $message .= '<strong>'.get_lang('User').'</strong>: ';
7178
                    $message .= $userInfo['complete_name_with_username'].' <br />';
7179
7180
                    if (!in_array($userInfo['status'], [DRH]) && !api_is_platform_admin_by_id($userInfo['user_id'])) {
7181
                        $message .= get_lang('Users must have the HR director role').'<br />';
7182
                        continue;
7183
                    }
7184
7185
                    if (!empty($sessionList)) {
7186
                        $message .= '<strong>'.get_lang('Course sessions').':</strong> <br />';
7187
                        $message .= implode(', ', $sessionList).'<br /><br />';
7188
                    } else {
7189
                        $message .= get_lang('No session provided').' <br /><br />';
7190
                    }
7191
                }
7192
            }
7193
        }
7194
7195
        return $message;
7196
    }
7197
7198
    /**
7199
     * @param string $file
7200
     * @param bool   $sendEmail
7201
     * @param bool   $removeOldRelationShips
7202
     *
7203
     * @return string
7204
     */
7205
    public static function importSessionDrhCSV($file, $sendEmail, $removeOldRelationShips)
7206
    {
7207
        $list = Import::csv_reader($file);
7208
7209
        if (!empty($list)) {
7210
            $userSessionList = [];
7211
            foreach ($list as $data) {
7212
                $sessionInfo = [];
7213
                if (isset($data['SessionId'])) {
7214
                    $sessionInfo = api_get_session_info($data['SessionId']);
7215
                }
7216
7217
                if (isset($data['SessionName']) && empty($sessionInfo)) {
7218
                $sessionInfo = self::get_session_by_name($data['SessionName']);
7219
                }
7220
7221
                if (empty($sessionInfo)) {
7222
                    $sessionData = isset($data['SessionName']) ? $data['SessionName'] : $data['SessionId'];
7223
                    Display::addFlash(
7224
                        Display::return_message(get_lang('Session not found.').' - '.$sessionData, 'warning')
7225
                    );
7226
                    continue;
7227
                }
7228
                $userList = explode(',', $data['Username']);
7229
7230
                foreach ($userList as $username) {
7231
                    $userInfo = api_get_user_info_from_username($username);
7232
7233
                if (empty($userInfo)) {
7234
                        Display::addFlash(
7235
                            Display::return_message(get_lang("This user doesn't exist").' - '.$username, 'warning')
7236
                        );
7237
                        continue;
7238
                }
7239
7240
                if (!empty($userInfo) && !empty($sessionInfo)) {
7241
                    $userSessionList[$userInfo['user_id']]['session_list'][] = [
7242
                        'session_id' => $sessionInfo['id'],
7243
                        'session_info' => $sessionInfo,
7244
                    ];
7245
                    $userSessionList[$userInfo['user_id']]['user_info'] = $userInfo;
7246
                    }
7247
                }
7248
            }
7249
7250
            self::subscribeDrhToSessionList($userSessionList, $sendEmail, $removeOldRelationShips);
7251
7252
            return self::checkSubscribeDrhToSessionList($userSessionList);
7253
        }
7254
    }
7255
7256
    /**
7257
     * Courses re-ordering in resume_session.php flag see BT#8316.
7258
     */
7259
    public static function orderCourseIsEnabled()
7260
    {
7261
        $sessionCourseOrder = api_get_setting('session_course_ordering');
7262
        if ('true' === $sessionCourseOrder) {
7263
            return true;
7264
        }
7265
7266
        return false;
7267
    }
7268
7269
    /**
7270
     * @param string $direction (up/down)
7271
     * @param int    $sessionId
7272
     * @param int    $courseId
7273
     *
7274
     * @return bool
7275
     */
7276
    public static function move($direction, $sessionId, $courseId)
7277
    {
7278
        if (!self::orderCourseIsEnabled()) {
7279
            return false;
7280
        }
7281
7282
        $sessionId = intval($sessionId);
7283
        $courseId = intval($courseId);
7284
7285
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7286
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7287
7288
        $position = [];
7289
        $count = 0;
7290
        foreach ($courseList as $course) {
7291
            if ('' == $course['position']) {
7292
                $course['position'] = $count;
7293
            }
7294
            $position[$course['code']] = $course['position'];
7295
            // Saving current order.
7296
            $sql = "UPDATE $table SET position = $count
7297
                    WHERE session_id = $sessionId AND c_id = '".$course['real_id']."'";
7298
            Database::query($sql);
7299
            $count++;
7300
        }
7301
7302
        // Loading new positions.
7303
        $courseList = self::get_course_list_by_session_id($sessionId, null, 'position');
7304
7305
        $found = false;
7306
7307
        switch ($direction) {
7308
            case 'up':
7309
                $courseList = array_reverse($courseList);
7310
                break;
7311
            case 'down':
7312
                break;
7313
        }
7314
7315
        foreach ($courseList as $course) {
7316
            if ($found) {
7317
                $nextId = $course['real_id'];
7318
                $nextOrder = $course['position'];
7319
                break;
7320
            }
7321
7322
            if ($courseId == $course['real_id']) {
7323
                $thisCourseCode = $course['real_id'];
7324
                $thisOrder = $course['position'];
7325
                $found = true;
7326
            }
7327
        }
7328
7329
        $sql1 = "UPDATE $table SET position = '".intval($nextOrder)."'
7330
                 WHERE session_id = $sessionId AND c_id =  $thisCourseCode";
7331
        Database::query($sql1);
7332
7333
        $sql2 = "UPDATE $table SET position = '".intval($thisOrder)."'
7334
                 WHERE session_id = $sessionId AND c_id = $nextId";
7335
        Database::query($sql2);
7336
7337
        return true;
7338
    }
7339
7340
    /**
7341
     * @param int $sessionId
7342
     * @param int $courseId
7343
     *
7344
     * @return bool
7345
     */
7346
    public static function moveUp($sessionId, $courseId)
7347
    {
7348
        return self::move('up', $sessionId, $courseId);
7349
    }
7350
7351
    /**
7352
     * @param int    $sessionId
7353
     * @param string $courseCode
7354
     *
7355
     * @return bool
7356
     */
7357
    public static function moveDown($sessionId, $courseCode)
7358
    {
7359
        return self::move('down', $sessionId, $courseCode);
7360
    }
7361
7362
    /**
7363
     * Use the session duration to allow/block user access see BT#8317
7364
     * Needs these DB changes
7365
     * ALTER TABLE session ADD COLUMN duration int;
7366
     * ALTER TABLE session_rel_user ADD COLUMN duration int;.
7367
     */
7368
    public static function durationPerUserIsEnabled()
7369
    {
7370
        return api_get_configuration_value('session_duration_feature');
7371
    }
7372
7373
    /**
7374
     * Returns the number of days the student has left in a session when using
7375
     * sessions durations.
7376
     *
7377
     * @param int $userId
7378
     *
7379
     * @return int
7380
     */
7381
    public static function getDayLeftInSession(array $sessionInfo, $userId)
7382
    {
7383
        $sessionId = $sessionInfo['id'];
7384
        $subscription = self::getUserSession($userId, $sessionId);
7385
        $duration = empty($subscription['duration'])
7386
            ? $sessionInfo['duration']
7387
            : $sessionInfo['duration'] + $subscription['duration'];
7388
7389
        // Get an array with the details of the first access of the student to
7390
        // this session
7391
        $courseAccess = CourseManager::getFirstCourseAccessPerSessionAndUser(
7392
            $sessionId,
7393
            $userId
7394
        );
7395
7396
        $currentTime = time();
7397
7398
        // If no previous access, return false
7399
        if (0 == count($courseAccess)) {
7400
            return $duration;
7401
        }
7402
7403
        $firstAccess = api_strtotime($courseAccess['login_course_date'], 'UTC');
7404
        $endDateInSeconds = $firstAccess + $duration * 24 * 60 * 60;
7405
        $leftDays = round(($endDateInSeconds - $currentTime) / 60 / 60 / 24);
7406
7407
        return $leftDays;
7408
    }
7409
7410
    /**
7411
     * @param int $duration
7412
     * @param int $userId
7413
     * @param int $sessionId
7414
     *
7415
     * @return bool
7416
     */
7417
    public static function editUserSessionDuration($duration, $userId, $sessionId)
7418
    {
7419
        $duration = (int) $duration;
7420
        $userId = (int) $userId;
7421
        $sessionId = (int) $sessionId;
7422
7423
        if (empty($userId) || empty($sessionId)) {
7424
            return false;
7425
        }
7426
7427
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7428
        $parameters = ['duration' => $duration];
7429
        $where = ['session_id = ? AND user_id = ? ' => [$sessionId, $userId]];
7430
        Database::update($table, $parameters, $where);
7431
7432
        return true;
7433
    }
7434
7435
    /**
7436
     * Gets one row from the session_rel_user table.
7437
     *
7438
     * @param int $userId
7439
     * @param int $sessionId
7440
     *
7441
     * @return array
7442
     */
7443
    public static function getUserSession($userId, $sessionId)
7444
    {
7445
        $userId = (int) $userId;
7446
        $sessionId = (int) $sessionId;
7447
7448
        if (empty($userId) || empty($sessionId)) {
7449
            return false;
7450
        }
7451
7452
        $table = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7453
        $sql = "SELECT * FROM $table
7454
                WHERE session_id = $sessionId AND user_id = $userId";
7455
        $result = Database::query($sql);
7456
        $values = [];
7457
        if (Database::num_rows($result)) {
7458
            $values = Database::fetch_assoc($result);
7459
        }
7460
7461
        return $values;
7462
    }
7463
7464
    /**
7465
     * Check if user is subscribed inside a session as student.
7466
     *
7467
     * @param int $sessionId The session id
7468
     * @param int $userId    The user id
7469
     *
7470
     * @return bool Whether is subscribed
7471
     */
7472
    public static function isUserSubscribedAsStudent($sessionId, $userId)
7473
    {
7474
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7475
        $sessionId = (int) $sessionId;
7476
        $userId = (int) $userId;
7477
7478
        // COUNT(1) actually returns the number of rows from the table (as if
7479
        // counting the results from the first column)
7480
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7481
                WHERE
7482
                    session_id = $sessionId AND
7483
                    user_id = $userId AND
7484
                    relation_type = ".Session::STUDENT;
7485
7486
        $result = Database::fetch_assoc(Database::query($sql));
7487
7488
        if (!empty($result) && $result['qty'] > 0) {
7489
            return true;
7490
        }
7491
7492
        return false;
7493
    }
7494
7495
    /**
7496
     * Check if user is subscribed inside a session as a HRM.
7497
     *
7498
     * @param int $sessionId The session id
7499
     * @param int $userId    The user id
7500
     *
7501
     * @return bool Whether is subscribed
7502
     */
7503
    public static function isUserSubscribedAsHRM($sessionId, $userId)
7504
    {
7505
        $sessionRelUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
7506
7507
        $sessionId = (int) $sessionId;
7508
        $userId = (int) $userId;
7509
7510
        // COUNT(1) actually returns the number of rows from the table (as if
7511
        // counting the results from the first column)
7512
        $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable
7513
                WHERE
7514
                    session_id = $sessionId AND
7515
                    user_id = $userId AND
7516
                    relation_type = ".Session::DRH;
7517
7518
        $result = Database::fetch_assoc(Database::query($sql));
7519
7520
        if (!empty($result) && $result['qty'] > 0) {
7521
            return true;
7522
        }
7523
7524
        return false;
7525
    }
7526
7527
    /**
7528
     * Get the session coached by a user (general coach and course-session coach).
7529
     *
7530
     * @param int  $coachId                       The coach id
7531
     * @param bool $checkSessionRelUserVisibility Check the session visibility
7532
     * @param bool $asPlatformAdmin               The user is a platform admin and we want all sessions
7533
     *
7534
     * @return array The session list
7535
     */
7536
    public static function getSessionsCoachedByUser(
7537
        $coachId,
7538
        $checkSessionRelUserVisibility = false,
7539
        $asPlatformAdmin = false
7540
    ) {
7541
        // Get all sessions where $coachId is the general coach
7542
        $sessions = self::get_sessions_by_general_coach($coachId, $asPlatformAdmin);
7543
        // Get all sessions where $coachId is the course - session coach
7544
        $courseSessionList = self::getCoursesListByCourseCoach($coachId);
7545
        $sessionsByCoach = [];
7546
        if (!empty($courseSessionList)) {
7547
            foreach ($courseSessionList as $userCourseSubscription) {
7548
                $session = $userCourseSubscription->getSession();
7549
                $sessionsByCoach[$session->getId()] = api_get_session_info(
7550
                    $session->getId()
7551
                );
7552
            }
7553
        }
7554
7555
        if (!empty($sessionsByCoach)) {
7556
            $sessions = array_merge($sessions, $sessionsByCoach);
7557
        }
7558
7559
        // Remove repeated sessions
7560
        if (!empty($sessions)) {
7561
            $cleanSessions = [];
7562
            foreach ($sessions as $session) {
7563
                $cleanSessions[$session['id']] = $session;
7564
            }
7565
            $sessions = $cleanSessions;
7566
        }
7567
7568
        if ($checkSessionRelUserVisibility) {
7569
            if (!empty($sessions)) {
7570
                $newSessions = [];
7571
                foreach ($sessions as $session) {
7572
                    $visibility = api_get_session_visibility($session['id']);
7573
                    if (SESSION_INVISIBLE == $visibility) {
7574
                        continue;
7575
                    }
7576
                    $newSessions[] = $session;
7577
                }
7578
                $sessions = $newSessions;
7579
            }
7580
        }
7581
7582
        return $sessions;
7583
    }
7584
7585
    /**
7586
     * Check if the course belongs to the session.
7587
     *
7588
     * @param int    $sessionId  The session id
7589
     * @param string $courseCode The course code
7590
     *
7591
     * @return bool
7592
     */
7593
    public static function sessionHasCourse($sessionId, $courseCode)
7594
    {
7595
        $sessionId = (int) $sessionId;
7596
        $courseCode = Database::escape_string($courseCode);
7597
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7598
        $sessionRelCourseTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
7599
7600
        $sql = "SELECT COUNT(1) AS qty
7601
                FROM $courseTable c
7602
                INNER JOIN $sessionRelCourseTable src
7603
                ON c.id = src.c_id
7604
                WHERE src.session_id = $sessionId
7605
                AND c.code = '$courseCode'  ";
7606
7607
        $result = Database::query($sql);
7608
7609
        if (false !== $result) {
7610
            $data = Database::fetch_assoc($result);
7611
7612
            if ($data['qty'] > 0) {
7613
                return true;
7614
            }
7615
        }
7616
7617
        return false;
7618
    }
7619
7620
    /**
7621
     * Calculate the total user time in the platform.
7622
     *
7623
     * @param int    $userId The user id
7624
     * @param string $from   Optional. From date
7625
     * @param string $until  Optional. Until date
7626
     *
7627
     * @return string The time (hh:mm:ss)
7628
     */
7629
    public static function getTotalUserTimeInPlatform($userId, $from = '', $until = '')
7630
    {
7631
        $userId = (int) $userId;
7632
        $trackLoginTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
7633
        $whereConditions = [
7634
            'login_user_id = ? ' => $userId,
7635
        ];
7636
7637
        if (!empty($from) && !empty($until)) {
7638
            $whereConditions["AND (login_date >= '?' "] = $from;
7639
            $whereConditions["AND logout_date <= DATE_ADD('?', INTERVAL 1 DAY)) "] = $until;
7640
        }
7641
7642
        $trackResult = Database::select(
7643
            'SEC_TO_TIME(SUM(UNIX_TIMESTAMP(logout_date) - UNIX_TIMESTAMP(login_date))) as total_time',
7644
            $trackLoginTable,
7645
            [
7646
                'where' => $whereConditions,
7647
            ],
7648
            'first'
7649
        );
7650
7651
        if (false != $trackResult) {
7652
            return $trackResult['total_time'] ? $trackResult['total_time'] : '00:00:00';
7653
        }
7654
7655
        return '00:00:00';
7656
    }
7657
7658
    /**
7659
     * Get the courses list by a course coach.
7660
     *
7661
     * @param int $coachId The coach id
7662
     *
7663
     * @return array (id, user_id, session_id, c_id, visibility, status, legal_agreement)
7664
     */
7665
    public static function getCoursesListByCourseCoach($coachId)
7666
    {
7667
        $entityManager = Database::getManager();
7668
        $repo = $entityManager->getRepository(SessionRelCourseRelUser::class);
7669
7670
        return $repo->findBy([
7671
            'user' => $coachId,
7672
            'status' => Session::COURSE_COACH,
7673
        ]);
7674
    }
7675
7676
    /**
7677
     * Get the count of user courses in session.
7678
     *
7679
     * @param int $sessionId
7680
     * @param int $courseId
7681
     *
7682
     * @return array
7683
     */
7684
    public static function getTotalUserCoursesInSession($sessionId, $courseId = 0)
7685
    {
7686
        $tableUser = Database::get_main_table(TABLE_MAIN_USER);
7687
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7688
7689
        $sessionId = (int) $sessionId;
7690
7691
        if (empty($sessionId)) {
7692
            return [];
7693
        }
7694
7695
        $courseCondition = '';
7696
        if (!empty($courseId)) {
7697
            $courseId = (int) $courseId;
7698
            $courseCondition = "  c_id = $courseId AND ";
7699
        }
7700
7701
        $sql = "SELECT
7702
                    COUNT(u.id) as count,
7703
                    u.id,
7704
                    scu.status status_in_session,
7705
                    u.status user_status
7706
                FROM $table scu
7707
                INNER JOIN $tableUser u
7708
                ON scu.user_id = u.id
7709
                WHERE
7710
                  $courseCondition
7711
                  scu.session_id = ".$sessionId."
7712
                GROUP BY u.id";
7713
7714
        $result = Database::query($sql);
7715
7716
        $list = [];
7717
        while ($data = Database::fetch_assoc($result)) {
7718
            $list[] = $data;
7719
        }
7720
7721
        return $list;
7722
    }
7723
7724
    /**
7725
     * Returns list of a few data from session (name, short description, start
7726
     * date, end date) and the given extra fields if defined based on a
7727
     * session category Id.
7728
     *
7729
     * @param int    $categoryId  The internal ID of the session category
7730
     * @param string $target      Value to search for in the session field values
7731
     * @param array  $extraFields A list of fields to be scanned and returned
7732
     *
7733
     * @return mixed
7734
     */
7735
    public static function getShortSessionListAndExtraByCategory(
7736
        $categoryId,
7737
        $target,
7738
        $extraFields = null,
7739
        $publicationDate = null
7740
    ) {
7741
        $categoryId = (int) $categoryId;
7742
        $sessionList = [];
7743
        // Check if categoryId is valid
7744
        if ($categoryId > 0) {
7745
            $target = Database::escape_string($target);
7746
            $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
7747
            $sfTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7748
            $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7749
            // Join session field and session field values tables
7750
            $joinTable = $sfTable.' sf INNER JOIN '.$sfvTable.' sfv ON sf.id = sfv.field_id';
7751
            $fieldsArray = [];
7752
            foreach ($extraFields as $field) {
7753
                $fieldsArray[] = Database::escape_string($field);
7754
            }
7755
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7756
            if (isset($publicationDate)) {
7757
                $publicationDateString = $publicationDate->format('Y-m-d H:i:s');
7758
                $wherePublication = " AND id NOT IN (
7759
                    SELECT sfv.item_id FROM $joinTable
7760
                    WHERE
7761
                        sf.item_type = $extraFieldType AND
7762
                        ((sf.variable = 'publication_start_date' AND sfv.field_value > '$publicationDateString' and sfv.field_value != '') OR
7763
                        (sf.variable = 'publication_end_date' AND sfv.field_value < '$publicationDateString' and sfv.field_value != ''))
7764
                )";
7765
            }
7766
            // Get the session list from session category and target
7767
            $sessionList = Database::select(
7768
                'id, title, access_start_date, access_end_date',
7769
                $sTable,
7770
                [
7771
                    'where' => [
7772
                        "session_category_id = ? AND id IN (
7773
                            SELECT sfv.item_id FROM $joinTable
7774
                            WHERE
7775
                                sf.item_type = $extraFieldType AND
7776
                                sfv.item_id = session.id AND
7777
                                sf.variable = 'target' AND
7778
                                sfv.field_value = ?
7779
                        ) $wherePublication" => [$categoryId, $target],
7780
                    ],
7781
                ]
7782
            );
7783
            $whereFieldVariables = [];
7784
            $whereFieldIds = [];
7785
            if (
7786
                is_array($fieldsArray) &&
7787
                count($fieldsArray) > 0
7788
            ) {
7789
                $whereParams = '?';
7790
                for ($i = 1; $i < count($fieldsArray); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
7791
                    $whereParams .= ', ?';
7792
                }
7793
                $whereFieldVariables = ' variable IN ( '.$whereParams.' )';
7794
                $whereFieldIds = 'field_id IN ( '.$whereParams.' )';
7795
            }
7796
            // Get session fields
7797
            $extraField = new ExtraFieldModel('session');
7798
            $questionMarks = substr(str_repeat('?, ', count($fieldsArray)), 0, -2);
7799
            $fieldsList = $extraField->get_all([
7800
                ' variable IN ( '.$questionMarks.' )' => $fieldsArray,
7801
            ]);
7802
            // Index session fields
7803
            foreach ($fieldsList as $field) {
7804
                $fields[$field['id']] = $field['variable'];
7805
            }
7806
            // Get session field values
7807
            $extra = new ExtraFieldValue('session');
7808
            $questionMarksFields = substr(str_repeat('?, ', count($fields)), 0, -2);
7809
            $sessionFieldValueList = $extra->get_all(['where' => ['field_id IN ( '.$questionMarksFields.' )' => array_keys($fields)]]);
7810
            // Add session fields values to session list
7811
            foreach ($sessionList as $id => &$session) {
7812
                foreach ($sessionFieldValueList as $sessionFieldValue) {
7813
                    // Match session field values to session
7814
                    if ($sessionFieldValue['item_id'] == $id) {
7815
                        // Check if session field value is set in session field list
7816
                        if (isset($fields[$sessionFieldValue['field_id']])) {
7817
                            // Avoid overwriting the session's ID field
7818
                            if ('id' != $fields[$sessionFieldValue['field_id']]) {
7819
                                $var = $fields[$sessionFieldValue['field_id']];
7820
                                $val = $sessionFieldValue['value'];
7821
                                // Assign session field value to session
7822
                                $session[$var] = $val;
7823
                            }
7824
                        }
7825
                    }
7826
                }
7827
            }
7828
        }
7829
7830
        return $sessionList;
7831
    }
7832
7833
    /**
7834
     * Return the Session Category id searched by name.
7835
     *
7836
     * @param string $categoryName Name attribute of session category used for search query
7837
     * @param bool   $force        boolean used to get even if something is wrong (e.g not unique name)
7838
     *
7839
     * @return int|array If success, return category id (int), else it will return an array
7840
     *                   with the next structure:
7841
     *                   array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7842
     */
7843
    public static function getSessionCategoryIdByName($categoryName, $force = false)
7844
    {
7845
        // Start error result
7846
        $errorResult = ['error' => true, 'errorMessage' => get_lang('There was an error.')];
7847
        $categoryName = Database::escape_string($categoryName);
7848
        // Check if is not empty category name
7849
        if (!empty($categoryName)) {
7850
            $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
7851
            // Get all session category with same name
7852
            $result = Database::select(
7853
                'id',
7854
                $sessionCategoryTable,
7855
                [
7856
                    'where' => [
7857
                        'title = ?' => $categoryName,
7858
                    ],
7859
                ]
7860
            );
7861
            // Check the result
7862
            if ($result < 1) {
7863
                // If not found any result, update error message
7864
                $errorResult['errorMessage'] = 'Not found any session category name '.$categoryName;
7865
            } elseif (count($result) > 1 && !$force) {
7866
                // If found more than one result and force is disabled, update error message
7867
                $errorResult['errorMessage'] = 'Found many session categories';
7868
            } elseif (1 == count($result) || $force) {
7869
                // If found just one session category or force option is enabled
7870
7871
                return key($result);
7872
            }
7873
        } else {
7874
            // category name is empty, update error message
7875
            $errorResult['errorMessage'] = 'Not valid category name';
7876
        }
7877
7878
        return $errorResult;
7879
    }
7880
7881
    /**
7882
     * Return all data from sessions (plus extra field, course and coach data) by category id.
7883
     *
7884
     * @param int $sessionCategoryId session category id used to search sessions
7885
     *
7886
     * @return array If success, return session list and more session related data, else it will return an array
7887
     *               with the next structure:
7888
     *               array('error' => true, 'errorMessage' => ERROR_MESSAGE)
7889
     */
7890
    public static function getSessionListAndExtraByCategoryId($sessionCategoryId)
7891
    {
7892
        // Start error result
7893
        $errorResult = [
7894
            'error' => true,
7895
            'errorMessage' => get_lang('There was an error.'),
7896
        ];
7897
7898
        $sessionCategoryId = intval($sessionCategoryId);
7899
        // Check if session category id is valid
7900
        if ($sessionCategoryId > 0) {
7901
            // Get table names
7902
            $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
7903
            $sessionFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
7904
            $sessionFieldValueTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
7905
            $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
7906
            $userTable = Database::get_main_table(TABLE_MAIN_USER);
7907
            $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
7908
7909
            // Get all data from all sessions whit the session category specified
7910
            $sessionList = Database::select(
7911
                '*',
7912
                $sessionTable,
7913
                [
7914
                    'where' => [
7915
                        'session_category_id = ?' => $sessionCategoryId,
7916
                    ],
7917
                ]
7918
            );
7919
7920
            $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
7921
7922
            // Check if session list query had result
7923
            if (!empty($sessionList)) {
7924
                // implode all session id
7925
                $sessionIdsString = '('.implode(', ', array_keys($sessionList)).')';
7926
                // Get all field variables
7927
                $sessionFieldList = Database::select(
7928
                    'id, variable',
7929
                    $sessionFieldTable,
7930
                    ['item_type = ? ' => [$extraFieldType]]
7931
                );
7932
7933
                // Get all field values
7934
                $sql = "SELECT item_id, field_id, value FROM
7935
                        $sessionFieldValueTable v INNER JOIN $sessionFieldTable f
7936
                        ON (f.id = v.field_id)
7937
                        WHERE
7938
                            item_id IN $sessionIdsString AND
7939
                            item_type = $extraFieldType
7940
                ";
7941
                $result = Database::query($sql);
7942
                $sessionFieldValueList = Database::store_result($result, 'ASSOC');
7943
7944
                // Check if session field values had result
7945
                if (!empty($sessionFieldValueList)) {
7946
                    $sessionFieldValueListBySession = [];
7947
                    foreach ($sessionFieldValueList as $key => $sessionFieldValue) {
7948
                        // Create an array to index ids to session id
7949
                        $sessionFieldValueListBySession[$sessionFieldValue['item_id']][] = $key;
7950
                    }
7951
                }
7952
                // Query used to find course-coaches from sessions
7953
                $sql = "SELECT
7954
                            scu.session_id,
7955
                            c.id AS course_id,
7956
                            c.code AS course_code,
7957
                            c.title AS course_title,
7958
                            u.username AS coach_username,
7959
                            u.firstname AS coach_firstname,
7960
                            u.lastname AS coach_lastname
7961
                        FROM $courseTable c
7962
                        INNER JOIN $sessionCourseUserTable scu ON c.id = scu.c_id
7963
                        INNER JOIN $userTable u ON scu.user_id = u.id
7964
                        WHERE scu.status = ".Session::COURSE_COACH." AND scu.session_id IN $sessionIdsString
7965
                        ORDER BY scu.session_id ASC ";
7966
                $res = Database::query($sql);
7967
                $sessionCourseList = Database::store_result($res, 'ASSOC');
7968
                // Check if course list had result
7969
                if (!empty($sessionCourseList)) {
7970
                    foreach ($sessionCourseList as $key => $sessionCourse) {
7971
                        // Create an array to index ids to session_id
7972
                        $sessionCourseListBySession[$sessionCourse['session_id']][] = $key;
7973
                    }
7974
                }
7975
                // Join lists
7976
                if (is_array($sessionList)) {
7977
                    foreach ($sessionList as $id => &$row) {
7978
                        if (
7979
                            !empty($sessionFieldValueListBySession) &&
7980
                            is_array($sessionFieldValueListBySession[$id])
7981
                        ) {
7982
                            // If have an index array for session extra fields, use it to join arrays
7983
                            foreach ($sessionFieldValueListBySession[$id] as $key) {
7984
                                $row['extra'][$key] = [
7985
                                    'field_name' => $sessionFieldList[$sessionFieldValueList[$key]['field_id']]['variable'],
7986
                                    'value' => $sessionFieldValueList[$key]['value'],
7987
                                ];
7988
                            }
7989
                        }
7990
                        if (
7991
                            !empty($sessionCourseListBySession) &&
7992
                            is_array($sessionCourseListBySession[$id])
7993
                        ) {
7994
                            // If have an index array for session course coach, use it to join arrays
7995
                            foreach ($sessionCourseListBySession[$id] as $key) {
7996
                                $row['course'][$key] = [
7997
                                    'course_id' => $sessionCourseList[$key]['course_id'],
7998
                                    'course_code' => $sessionCourseList[$key]['course_code'],
7999
                                    'course_title' => $sessionCourseList[$key]['course_title'],
8000
                                    'coach_username' => $sessionCourseList[$key]['coach_username'],
8001
                                    'coach_firstname' => $sessionCourseList[$key]['coach_firstname'],
8002
                                    'coach_lastname' => $sessionCourseList[$key]['coach_lastname'],
8003
                                ];
8004
                            }
8005
                        }
8006
                    }
8007
                }
8008
8009
                return $sessionList;
8010
            } else {
8011
                // Not found result, update error message
8012
                $errorResult['errorMessage'] = 'Not found any session for session category id '.$sessionCategoryId;
8013
            }
8014
        }
8015
8016
        return $errorResult;
8017
    }
8018
8019
    /**
8020
     * Return session description from session id.
8021
     *
8022
     * @param int $sessionId
8023
     *
8024
     * @return string
8025
     */
8026
    public static function getDescriptionFromSessionId($sessionId)
8027
    {
8028
        // Init variables
8029
        $sessionId = (int) $sessionId;
8030
        $description = '';
8031
        // Check if session id is valid
8032
        if ($sessionId > 0) {
8033
            // Select query from session id
8034
            $rows = Database::select(
8035
                'description',
8036
                Database::get_main_table(TABLE_MAIN_SESSION),
8037
                [
8038
                    'where' => [
8039
                        'id = ?' => $sessionId,
8040
                    ],
8041
                ]
8042
            );
8043
8044
            // Check if select query result is not empty
8045
            if (!empty($rows)) {
8046
                // Get session description
8047
                $description = $rows[0]['description'];
8048
            }
8049
        }
8050
8051
        return $description;
8052
    }
8053
8054
    /**
8055
     * Get a session list filtered by name, description or any of the given extra fields.
8056
     *
8057
     * @param string $term                 The term to search
8058
     * @param array  $extraFieldsToInclude Extra fields to include in the session data
8059
     *
8060
     * @return array The list
8061
     */
8062
    public static function searchSession($term, $extraFieldsToInclude = [])
8063
    {
8064
        $sTable = Database::get_main_table(TABLE_MAIN_SESSION);
8065
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
8066
        $sfvTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8067
        $term = Database::escape_string($term);
8068
        $extraFieldType = ExtraField::SESSION_FIELD_TYPE;
8069
        if (is_array($extraFieldsToInclude) && count($extraFieldsToInclude) > 0) {
8070
            $resultData = Database::select('*', $sTable, [
8071
                'where' => [
8072
                    "title LIKE %?% " => $term,
8073
                    " OR description LIKE %?% " => $term,
8074
                    " OR id IN (
8075
                    SELECT item_id
8076
                    FROM $sfvTable v INNER JOIN $extraFieldTable e
8077
                    ON (v.field_id = e.id)
8078
                    WHERE field_value LIKE %?% AND item_type = $extraFieldType
8079
                ) " => $term,
8080
                ],
8081
            ]);
8082
        } else {
8083
            $resultData = Database::select('*', $sTable, [
8084
                'where' => [
8085
                    "title LIKE %?% " => $term,
8086
                    "OR description LIKE %?% " => $term,
8087
                ],
8088
            ]);
8089
8090
            return $resultData;
8091
        }
8092
8093
        foreach ($resultData as $id => &$session) {
8094
            $session['extra'] = self::getFilteredExtraFields($id, $extraFieldsToInclude);
8095
        }
8096
8097
        return $resultData;
8098
    }
8099
8100
    /**
8101
     * @param int   $sessionId
8102
     * @param array $extraFieldsToInclude (empty means all)
8103
     *
8104
     * @return array
8105
     */
8106
    public static function getFilteredExtraFields($sessionId, $extraFieldsToInclude = [])
8107
    {
8108
        $extraData = [];
8109
        $variables = [];
8110
        $variablePlaceHolders = [];
8111
8112
        foreach ($extraFieldsToInclude as $sessionExtraField) {
8113
            $variablePlaceHolders[] = "?";
8114
            $variables[] = Database::escape_string($sessionExtraField);
8115
        }
8116
8117
        $sessionExtraField = new ExtraFieldModel('session');
8118
        $fieldList = $sessionExtraField->get_all(empty($extraFieldsToInclude) ? [] : [
8119
            "variable IN ( ".implode(", ", $variablePlaceHolders)." ) " => $variables,
8120
        ]);
8121
8122
        if (empty($fieldList)) {
8123
            return [];
8124
        }
8125
8126
        $fields = [];
8127
8128
        // Index session fields
8129
        foreach ($fieldList as $field) {
8130
            $fields[$field['id']] = $field['variable'];
8131
        }
8132
8133
        // Get session field values
8134
        $extra = new ExtraFieldValue('session');
8135
        $sessionFieldValueList = [];
8136
        foreach (array_keys($fields) as $fieldId) {
8137
            $sessionFieldValue = $extra->get_values_by_handler_and_field_id($sessionId, $fieldId);
8138
            if (false != $sessionFieldValue) {
8139
                $sessionFieldValueList[$fieldId] = $sessionFieldValue;
8140
            }
8141
        }
8142
8143
        foreach ($sessionFieldValueList as $sessionFieldValue) {
8144
            // Match session field values to session
8145
            if ($sessionFieldValue['item_id'] != $sessionId) {
8146
                continue;
8147
            }
8148
8149
            // Check if session field value is set in session field list
8150
            if (!isset($fields[$sessionFieldValue['field_id']])) {
8151
                continue;
8152
            }
8153
8154
            $extrafieldVariable = $fields[$sessionFieldValue['field_id']];
8155
            $extrafieldValue = $sessionFieldValue['value'];
8156
8157
            $extraData[] = [
8158
                'variable' => $extrafieldVariable,
8159
                'value' => $extrafieldValue,
8160
            ];
8161
        }
8162
8163
        return $extraData;
8164
    }
8165
8166
    /**
8167
     * @param int $sessionId
8168
     *
8169
     * @return bool
8170
     */
8171
    public static function isValidId($sessionId)
8172
    {
8173
        $sessionId = (int) $sessionId;
8174
        if ($sessionId > 0) {
8175
            $rows = Database::select(
8176
                'id',
8177
                Database::get_main_table(TABLE_MAIN_SESSION),
8178
                ['where' => ['id = ?' => $sessionId]]
8179
            );
8180
            if (!empty($rows)) {
8181
                return true;
8182
            }
8183
        }
8184
8185
        return false;
8186
    }
8187
8188
    /**
8189
     * Get list of sessions based on users of a group for a group admin.
8190
     *
8191
     * @param int $userId The user id
8192
     *
8193
     * @return array
8194
     */
8195
    public static function getSessionsFollowedForGroupAdmin($userId)
8196
    {
8197
        $sessionList = [];
8198
        $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
8199
        $sessionUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8200
        $userGroup = new UserGroupModel();
8201
        $userIdList = $userGroup->getGroupUsersByUser($userId);
8202
8203
        if (empty($userIdList)) {
8204
            return [];
8205
        }
8206
8207
        $sql = "SELECT DISTINCT s.*
8208
                FROM $sessionTable s
8209
                INNER JOIN $sessionUserTable sru
8210
                ON s.id = sru.id_session
8211
                WHERE
8212
                    (sru.id_user IN (".implode(', ', $userIdList).")
8213
                    AND sru.relation_type = ".Session::STUDENT."
8214
                )";
8215
8216
        if (api_is_multiple_url_enabled()) {
8217
            $sessionAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8218
            $accessUrlId = api_get_current_access_url_id();
8219
8220
            if (-1 != $accessUrlId) {
8221
                $sql = "SELECT DISTINCT s.*
8222
                        FROM $sessionTable s
8223
                        INNER JOIN $sessionUserTable sru ON s.id = sru.id_session
8224
                        INNER JOIN $sessionAccessUrlTable srau ON s.id = srau.session_id
8225
                        WHERE
8226
                            srau.access_url_id = $accessUrlId
8227
                            AND (
8228
                                sru.id_user IN (".implode(', ', $userIdList).")
8229
                                AND sru.relation_type = ".Session::STUDENT."
8230
                            )";
8231
            }
8232
        }
8233
8234
        $result = Database::query($sql);
8235
        while ($row = Database::fetch_assoc($result)) {
8236
            $sessionList[] = $row;
8237
        }
8238
8239
        return $sessionList;
8240
    }
8241
8242
    public static function getSessionVisibility(Session $session) : string
8243
    {
8244
        switch ($session->getVisibility()) {
8245
            case 1:
8246
                return get_lang('Read only');
8247
            case 2:
8248
                return get_lang('Visible');
8249
            case 3:
8250
                return api_ucfirst(get_lang('invisible'));
8251
        }
8252
8253
        return '';
8254
    }
8255
8256
    /**
8257
     * Returns a human readable string.
8258
     *
8259
     * @return array
8260
     */
8261
    public static function parseSessionDates(Session $session, bool $showTime = false)
8262
    {
8263
        $displayDates = self::convertSessionDateToString(
8264
            $session->getDisplayStartDate(),
8265
            $session->getDisplayEndDate(),
8266
            $showTime,
8267
            true
8268
        );
8269
        $accessDates = self::convertSessionDateToString(
8270
            $session->getAccessStartDate(),
8271
            $session->getAccessEndDate(),
8272
            $showTime,
8273
            true
8274
        );
8275
8276
        $coachDates = self::convertSessionDateToString(
8277
            $session->getCoachAccessStartDate(),
8278
            $session->getCoachAccessEndDate(),
8279
            $showTime,
8280
            true
8281
        );
8282
8283
        return [
8284
            'access' => $accessDates,
8285
            'display' => $displayDates,
8286
            'coach' => $coachDates,
8287
        ];
8288
    }
8289
8290
    /**
8291
     * @throws Exception
8292
     */
8293
    public static function setForm(FormValidator $form, Session $session = null, $fromSessionId = null): array
8294
    {
8295
        $categoriesList = self::get_all_session_category();
8296
8297
        $categoriesOptions = [
8298
            '0' => get_lang('none'),
8299
        ];
8300
8301
        if (false != $categoriesList) {
8302
            foreach ($categoriesList as $categoryItem) {
8303
                $categoriesOptions[$categoryItem['id']] = $categoryItem['title'];
8304
            }
8305
        }
8306
8307
        // Database Table Definitions
8308
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8309
8310
        $form->addText(
8311
            'title',
8312
            get_lang('Session name'),
8313
            true,
8314
            ['maxlength' => 150, 'aria-label' => get_lang('Session name')]
8315
        );
8316
        $form->addRule('title', get_lang('Session title already exists'), 'callback', 'check_session_name');
8317
8318
        if (!api_is_platform_admin() && api_is_teacher()) {
8319
            $form->addSelectFromCollection(
8320
                'coach_username',
8321
                [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8322
                [api_get_user_entity()],
8323
                [
8324
                    'id' => 'coach_username',
8325
                    'style' => 'width:370px;',
8326
                    'multiple' => true,
8327
                ],
8328
                false,
8329
                'getFullname'
8330
            );
8331
        } else {
8332
            $sql = "SELECT COUNT(1) FROM $tbl_user WHERE active <> ".USER_SOFT_DELETED." AND status = 1";
8333
            $rs = Database::query($sql);
8334
            $countUsers = (int) Database::result($rs, 0, '0');
8335
8336
            if ($countUsers < 1) {
8337
                $orderClause = 'ORDER BY ';
8338
                $orderClause .= api_sort_by_first_name() ? 'firstname, lastname, username' : 'lastname, firstname, username';
8339
8340
                $sql = "SELECT id as user_id, lastname, firstname, username
8341
                        FROM $tbl_user
8342
                        WHERE active <> -1 AND status = '1' ".
8343
                        $orderClause;
8344
8345
                if (api_is_multiple_url_enabled()) {
8346
                    $userRelAccessUrlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
8347
                    $accessUrlId = api_get_current_access_url_id();
8348
                    if (-1 != $accessUrlId) {
8349
                        $sql = "SELECT user.id as user_id, username, lastname, firstname
8350
                        FROM $tbl_user user
8351
                        INNER JOIN $userRelAccessUrlTable url_user
8352
                        ON (url_user.user_id = user.id)
8353
                        WHERE
8354
                            user.active <> -1 AND
8355
                            access_url_id = $accessUrlId AND
8356
                            status = 1 "
8357
                            .$orderClause;
8358
                    }
8359
                }
8360
8361
                $result = Database::query($sql);
8362
                $coachesList = Database::store_result($result);
8363
                $coachesOptions = [];
8364
                foreach ($coachesList as $coachItem) {
8365
                    $coachesOptions[$coachItem['user_id']] =
8366
                        api_get_person_name($coachItem['firstname'], $coachItem['lastname']).' ('.$coachItem['username'].')';
8367
                }
8368
8369
                $form->addSelect(
8370
                    'coach_username',
8371
                    [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8372
                    $coachesOptions,
8373
                    [
8374
                        'id' => 'coach_username',
8375
                        'style' => 'width:370px;',
8376
                        'multiple' => true,
8377
                    ]
8378
                );
8379
            } else {
8380
                $coaches = [];
8381
8382
                if ($session) {
8383
                    foreach ($session->getGeneralCoaches() as $coach) {
8384
                        $coaches[$coach->getId()] = $coach->getFullName();
8385
                    }
8386
                }
8387
8388
                $form->addSelectAjax(
8389
                    'coach_username',
8390
                    [get_lang('Coach name'), get_lang('Session coaches are coordinators for the session and can act as tutor for each of the course in the session. Only users with the teacher role can be selected as session coach.')],
8391
                    $coaches,
8392
                    [
8393
                        'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_general_coach',
8394
                        'width' => '100%',
8395
                        'id' => 'coach_username',
8396
                        'multiple' => true,
8397
                    ]
8398
                );
8399
            }
8400
        }
8401
8402
        $form->addRule('coach_username', get_lang('Required field'), 'required');
8403
        $form->addHtml('<div id="ajax_list_coachs"></div>');
8404
8405
        $form->addButtonAdvancedSettings('advanced_params');
8406
        $form->addElement('html', '<div id="advanced_params_options" style="'.(isset($fromSessionId) ? 'display:block' : 'display:none').'">');
8407
8408
        if (null === $session) {
8409
            $form->addSelectAjax(
8410
                'session_template',
8411
                get_lang('Session template'),
8412
                [],
8413
                [
8414
                    'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_template_session',
8415
                    'id' => 'system_template',
8416
                ]
8417
            );
8418
        }
8419
8420
        if (isset($fromSessionId)) {
8421
            $session = api_get_session_entity($fromSessionId);
8422
        }
8423
        $form->addSelect(
8424
            'session_category',
8425
            get_lang('Sessions categories'),
8426
            $categoriesOptions,
8427
            [
8428
                'id' => 'session_category',
8429
            ]
8430
        );
8431
8432
        $statusList = self::getStatusList();
8433
        $form->addSelect(
8434
            'status',
8435
            get_lang('Session status'),
8436
            $statusList,
8437
            [
8438
                'id' => 'status',
8439
            ]
8440
        );
8441
8442
        $form->addHtmlEditor(
8443
            'description',
8444
            get_lang('Description'),
8445
            false,
8446
            false,
8447
            [
8448
                'ToolbarSet' => 'Minimal',
8449
            ]
8450
        );
8451
8452
        $form->addElement('checkbox', 'show_description', null, get_lang('Show description'));
8453
8454
        $visibilityGroup = [];
8455
        $visibilityGroup[] = $form->createElement(
8456
            'select',
8457
            'session_visibility',
8458
            null,
8459
            [
8460
                SESSION_VISIBLE_READ_ONLY => get_lang('Read only'),
8461
                SESSION_VISIBLE => get_lang('Accessible'),
8462
                SESSION_INVISIBLE => api_ucfirst(get_lang('Not accessible')),
8463
            ],
8464
            []
8465
        );
8466
        $form->addGroup(
8467
            $visibilityGroup,
8468
            'visibility_group',
8469
            get_lang('Visibility after end date'),
8470
            null,
8471
            false
8472
        );
8473
8474
        $options = [
8475
            0 => get_lang('By duration'),
8476
            1 => get_lang('By dates'),
8477
        ];
8478
8479
        $form->addSelect('access', get_lang('Access'), $options, [
8480
            'onchange' => 'accessSwitcher(this.value)',
8481
            'id' => 'access',
8482
        ]);
8483
8484
        $form->addHtml('<div id="duration_div" style="display:none">');
8485
        $form->addElement(
8486
            'number',
8487
            'duration',
8488
            [
8489
                get_lang('Session duration'),
8490
                get_lang("The session duration allows you to set a number of days of access starting from the first access date of the user to the session. This way, you can set a session to 'last for 15 days' instead of starting at a fixed date for all students."),
8491
            ],
8492
            [
8493
                'maxlength' => 50,
8494
            ]
8495
        );
8496
8497
        $form->addHtml('</div>');
8498
        $form->addHtml('<div id="date_fields" style="display:none">');
8499
8500
        // Dates
8501
        $form->addDateTimePicker(
8502
            'access_start_date',
8503
            [get_lang('Access start date'), get_lang('Date on which the session is made available to all')],
8504
            ['id' => 'access_start_date']
8505
        );
8506
8507
        $form->addDateTimePicker(
8508
            'access_end_date',
8509
            [get_lang('Access end date'), get_lang('Date on which the session is closed')],
8510
            ['id' => 'access_end_date']
8511
        );
8512
8513
        $form->addRule(
8514
            ['access_start_date', 'access_end_date'],
8515
            get_lang('Start date must be before the end date'),
8516
            'compare_datetime_text',
8517
            '< allow_empty'
8518
        );
8519
8520
        $form->addDateTimePicker(
8521
            'display_start_date',
8522
            [
8523
                get_lang('Start date to display'),
8524
                get_lang('Date that will be shown in the session information as the date on which the session starts'),
8525
            ],
8526
            ['id' => 'display_start_date']
8527
        );
8528
8529
        $form->addDateTimePicker(
8530
            'display_end_date',
8531
            [
8532
                get_lang('End date to display'),
8533
                get_lang('Date that will be shown in the session information as the date on which the session ends'),
8534
            ],
8535
            ['id' => 'display_end_date']
8536
        );
8537
8538
        $form->addRule(
8539
            ['display_start_date', 'display_end_date'],
8540
            get_lang('Start date must be before the end date'),
8541
            'compare_datetime_text',
8542
            '< allow_empty'
8543
        );
8544
8545
        $form->addDateTimePicker(
8546
            'coach_access_start_date',
8547
            [
8548
                get_lang('Access start date for coaches'),
8549
                get_lang('Date on which the session is made available to coaches, so they can prepare it before the students get connected'),
8550
            ],
8551
            ['id' => 'coach_access_start_date']
8552
        );
8553
8554
        $form->addDateTimePicker(
8555
            'coach_access_end_date',
8556
            [
8557
                get_lang('Access end date for coaches'),
8558
                get_lang('Date on which the session is closed to coaches. The additional delay will allow them to export all relevant tracking information'),
8559
            ],
8560
            ['id' => 'coach_access_end_date']
8561
        );
8562
8563
        $form->addRule(
8564
            ['coach_access_start_date', 'coach_access_end_date'],
8565
            get_lang('Start date must be before the end date'),
8566
            'compare_datetime_text',
8567
            '< allow_empty'
8568
        );
8569
8570
        $form->addElement('html', '</div>');
8571
8572
        $form->addCheckBox(
8573
            'send_subscription_notification',
8574
            get_lang('Send an email when a user being subscribed to session'),
8575
        );
8576
8577
        $form->addCheckBox(
8578
            'notify_boss',
8579
            get_lang('Notify subscription of user to student boss')
8580
        );
8581
8582
        // Picture
8583
        $form->addFile(
8584
            'picture',
8585
            get_lang('Add image'),
8586
            ['id' => 'picture', 'class' => 'picture-form', 'crop_image' => true]
8587
        );
8588
        $allowedPictureTypes = api_get_supported_image_extensions(false);
8589
        $form->addRule('picture', get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowedPictureTypes).')', 'filetype', $allowedPictureTypes);
8590
8591
        if ($session && $session->getImage()) {
8592
            if (isset($fromSessionId)) {
8593
                $imageUrl = self::getSessionPictureUrl($session);
8594
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8595
                $form->addHidden('image_session_template', $imageUrl);
8596
8597
            } else {
8598
                $form->addElement('checkbox', 'delete_picture', null, get_lang('Delete picture'));
8599
                $imageUrl = self::getSessionPictureUrl($session);
8600
                $form->addLabel(get_lang('Image'), "<img src = '$imageUrl' />");
8601
            }
8602
        }
8603
8604
        // Extra fields
8605
        $extra_field = new ExtraFieldModel('session');
8606
        $extra = $extra_field->addElements($form, $session ? $session->getId() : 0, ['image']);
8607
8608
        if ('true' === api_get_setting('session.enable_auto_reinscription')) {
8609
            $form->addElement(
8610
                'text',
8611
                'days_before_finishing_for_reinscription',
8612
                get_lang('Days before finishing for re-enrollment'),
8613
                ['maxlength' => 5]
8614
            );
8615
            $form->addRule(
8616
                'days_before_finishing_for_reinscription',
8617
                get_lang('The field must be empty or a positive integer'),
8618
                'regex',
8619
                '/^\d*$/'
8620
            );
8621
        }
8622
8623
        if ('true' === api_get_setting('session.enable_session_replication')) {
8624
            $form->addElement(
8625
                'text',
8626
                'days_before_finishing_to_create_new_repetition',
8627
                get_lang('Days before finishing automated creation of new repetitions'),
8628
                ['maxlength' => 5]
8629
            );
8630
            $form->addRule(
8631
                'days_before_finishing_to_create_new_repetition',
8632
                get_lang('The field must be empty or a positive integer'),
8633
                'regex',
8634
                '/^\d*$/'
8635
            );
8636
        }
8637
8638
        if ('true' === api_get_setting('session.enable_auto_reinscription') || 'true' === api_get_setting('session.enable_session_replication')) {
8639
            $form->addElement(
8640
                'checkbox',
8641
                'last_repetition',
8642
                get_lang('Last repetition')
8643
            );
8644
8645
            $form->addElement(
8646
                'number',
8647
                'validity_in_days',
8648
                get_lang('Validity (days)'),
8649
                [
8650
                    'min' => 0,
8651
                    'max' => 365,
8652
                    'step' => 1,
8653
                    'placeholder' => get_lang('Number of days'),
8654
                ]
8655
            );
8656
8657
            $form->addRule(
8658
                'validity_in_days',
8659
                get_lang('The field must be a positive integer'),
8660
                'numeric',
8661
                null,
8662
                'client'
8663
            );
8664
        }
8665
8666
        /** @var HTML_QuickForm_select $element */
8667
        $element = $form->createElement(
8668
            'select',
8669
            'parent_id',
8670
            get_lang('Parent session'),
8671
            [],
8672
            ['class' => 'form-control']
8673
        );
8674
8675
        $element->addOption(get_lang('None'), 0, []);
8676
        $sessions = SessionManager::getListOfParentSessions();
8677
        $currentSessionId = $session?->getId();
8678
        foreach ($sessions as $id => $title) {
8679
            if ($id !== $currentSessionId) {
8680
                $attributes = [];
8681
                $element->addOption($title, $id, $attributes);
8682
            }
8683
        }
8684
        $element->setSelected($session?->getParentId() ?? 0);
8685
        $form->addElement($element);
8686
8687
        $form->addElement('html', '</div>');
8688
8689
        $js = $extra['jquery_ready_content'];
8690
8691
        return ['js' => $js];
8692
    }
8693
8694
    /**
8695
     * Saves the session picture.
8696
     *
8697
     * @param int    $sessionId
8698
     * @param array  $file
8699
     * @param string $crop
8700
     *
8701
     * @return false
8702
     */
8703
    public static function updateSessionPicture(
8704
        $sessionId,
8705
        $file,
8706
        string $crop = ''
8707
    ) {
8708
        if (empty($file)) {
8709
            return false;
8710
        }
8711
8712
        $sessionRepo = Container::getSessionRepository();
8713
        $assetRepo = Container::getAssetRepository();
8714
8715
        $asset = (new Asset())
8716
            ->setCategory(Asset::SESSION)
8717
            ->setTitle($file['name'])
8718
        ;
8719
        if (!empty($crop)) {
8720
            $asset->setCrop($crop);
8721
        }
8722
        $asset = $assetRepo->createFromRequest($asset, $file);
8723
8724
        /** @var Session $session */
8725
        $session = $sessionRepo->find($sessionId);
8726
        $session->setImage($asset);
8727
        $sessionRepo->update($session);
8728
    }
8729
8730
    /**
8731
     * Deletes de session picture as asset.
8732
     *
8733
     * @param int $sessionId
8734
     */
8735
    public static function deleteAsset(int $sessionId): void
8736
    {
8737
        $sessionRepo = Container::getSessionRepository();
8738
8739
        /** @var Session $session */
8740
        $session = $sessionRepo->find($sessionId);
8741
        $em = Database::getManager();
8742
        if ($session->hasImage()) {
8743
            $asset = $session->getImage();
8744
            $em->remove($asset);
8745
            $em->flush();
8746
        }
8747
    }
8748
8749
    /**
8750
     * Get the session picture url.
8751
     *
8752
     * @param Session $session
8753
     * @return string
8754
     */
8755
    public static function getSessionPictureUrl(Session $session): string
8756
    {
8757
        $assetRepo = Container::getAssetRepository();
8758
        $imageUrl = $assetRepo->getAssetUrl($session->getImage());
8759
8760
        return $imageUrl;
8761
    }
8762
8763
    /**
8764
     * Gets the number of rows in the session table filtered through the given
8765
     * array of parameters.
8766
     *
8767
     * @param array Array of options/filters/keys
8768
     *
8769
     * @return int The number of rows, or false on wrong param
8770
     * @assert ('a') === false
8771
     */
8772
    public static function get_count_admin_complete($options = [])
8773
    {
8774
        if (!is_array($options)) {
8775
            return false;
8776
        }
8777
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
8778
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
8779
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
8780
        $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
8781
        $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
8782
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
8783
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
8784
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
8785
8786
        $where = 'WHERE 1 = 1 AND u.active <> -1 ';
8787
8788
        if (api_is_session_admin() &&
8789
            'false' == api_get_setting('allow_session_admins_to_see_all_sessions')
8790
        ) {
8791
            $user_id = api_get_user_id();
8792
            $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
8793
        } else {
8794
            $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
8795
        }
8796
8797
        $extraFieldTables = '';
8798
        if (!empty($options['where'])) {
8799
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
8800
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
8801
8802
            $options['where'] = str_replace(
8803
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
8804
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
8805
                $options['where']
8806
            );
8807
8808
            $options['where'] = str_replace(
8809
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
8810
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
8811
                $options['where']
8812
            );
8813
8814
            if (!empty($options['extra'])) {
8815
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
8816
                $options['where'] = str_replace('AND', 'OR', $options['where']);
8817
8818
                foreach ($options['extra'] as $extra) {
8819
                    $options['where'] = str_replace(
8820
                        $extra['field'],
8821
                        'fv.field_id = '.$extra['id'].' AND fvo.option_value',
8822
                        $options['where']
8823
                    );
8824
                    $extraFieldTables = "$tbl_session_field_values fv, $tbl_session_field_options fvo, ";
8825
                }
8826
            }
8827
            $where .= ' AND '.$options['where'];
8828
        }
8829
8830
        $today = api_get_utc_datetime();
8831
        $query_rows = "SELECT count(*) as total_rows, c.title as course_title, s.title,
8832
                        IF (
8833
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
8834
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
8835
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
8836
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
8837
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
8838
                        , 1, 0) as session_active
8839
                       FROM $extraFieldTables $tbl_session s
8840
                       LEFT JOIN  $tbl_session_category sc
8841
                       ON s.session_category_id = sc.id
8842
                       INNER JOIN $tblSessionRelUser sru
8843
                       ON s.id = sru.session_id
8844
                       INNER JOIN $tbl_user u
8845
                       ON sru.user_id = u.id
8846
                       INNER JOIN $sessionCourseUserTable scu
8847
                       ON s.id = scu.session_id
8848
                       INNER JOIN $courseTable c
8849
                       ON c.id = scu.c_id
8850
                       $where ";
8851
8852
        if (api_is_multiple_url_enabled()) {
8853
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
8854
            $access_url_id = api_get_current_access_url_id();
8855
            if (-1 != $access_url_id) {
8856
                $where .= " AND ar.access_url_id = $access_url_id ";
8857
                $query_rows = "SELECT count(*) as total_rows
8858
                               FROM $tbl_session s
8859
                               LEFT JOIN  $tbl_session_category sc
8860
                               ON s.session_category_id = sc.id
8861
                               INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
8862
                               INNER JOIN $tbl_user u
8863
                               ON sru.user_id = u.id
8864
                               INNER JOIN $table_access_url_rel_session ar
8865
                               ON ar.session_id = s.id $where ";
8866
            }
8867
        }
8868
8869
        $result = Database::query($query_rows);
8870
        $num = 0;
8871
        if (Database::num_rows($result)) {
8872
            $rows = Database::fetch_array($result);
8873
            $num = $rows['total_rows'];
8874
        }
8875
8876
        return $num;
8877
    }
8878
8879
    /**
8880
     * @param string $listType
8881
     * @param array  $extraFields
8882
     *
8883
     * @return array
8884
     */
8885
    public static function getGridColumns(
8886
        $listType = 'all',
8887
        $extraFields = [],
8888
        $addExtraFields = true
8889
    ) {
8890
        $showCount = ('true' === api_get_setting('session.session_list_show_count_users'));
8891
        // Column config
8892
        $operators = ['cn', 'nc'];
8893
        $date_operators = ['gt', 'ge', 'lt', 'le'];
8894
8895
        switch ($listType) {
8896
            case 'my_space':
8897
                $columns = [
8898
                    get_lang('Title'),
8899
                    get_lang('Date'),
8900
                    get_lang('Number of courses per session'),
8901
                    get_lang('Number of learners by session'),
8902
                    get_lang('Details'),
8903
                ];
8904
8905
                $columnModel = [
8906
                    ['name' => 'title', 'index' => 'title', 'align' => 'left'],
8907
                    ['name' => 'date', 'index' => 'access_start_date', 'align' => 'left'],
8908
                    [
8909
                        'name' => 'course_per_session',
8910
                        'index' => 'course_per_session',
8911
                        'sortable' => 'false',
8912
                        'search' => 'false',
8913
                    ],
8914
                    [
8915
                        'name' => 'student_per_session',
8916
                        'index' => 'student_per_session',
8917
                        'sortable' => 'false',
8918
                        'search' => 'false',
8919
                    ],
8920
                    [
8921
                        'name' => 'actions',
8922
                        'index' => 'actions',
8923
                        'sortable' => 'false',
8924
                        'search' => 'false',
8925
                    ],
8926
                ];
8927
                break;
8928
            case 'all':
8929
            case 'active':
8930
            case 'close':
8931
                $columns = [
8932
                    '#',
8933
                    get_lang('Title'),
8934
                    get_lang('Category'),
8935
                    get_lang('Start date to display'),
8936
                    get_lang('End date to display'),
8937
                    get_lang('Visibility'),
8938
                ];
8939
8940
                $columnModel = [
8941
                    [
8942
                        'name' => 'id',
8943
                        'index' => 's.id',
8944
                        'hidden' => 'true',
8945
                    ],
8946
                    [
8947
                        'name' => 'title',
8948
                        'index' => 's.title',
8949
                        'width' => '300',
8950
                        'align' => 'left',
8951
                        'search' => 'true',
8952
                        'searchoptions' => ['sopt' => $operators],
8953
                    ],
8954
                    [
8955
                        'name' => 'category_name',
8956
                        'index' => 'category_name',
8957
                        'align' => 'left',
8958
                        'search' => 'true',
8959
                        'searchoptions' => ['sopt' => $operators],
8960
                    ],
8961
                    [
8962
                        'name' => 'display_start_date',
8963
                        'index' => 'display_start_date',
8964
                        'align' => 'left',
8965
                        'width' => '200',
8966
                        'search' => 'true',
8967
                        'searchoptions' => [
8968
                            'dataInit' => 'date_pick_today',
8969
                            'sopt' => $date_operators,
8970
                        ],
8971
                    ],
8972
                    [
8973
                        'name' => 'display_end_date',
8974
                        'index' => 'display_end_date',
8975
                        'align' => 'left',
8976
                        'width' => '200',
8977
                        'search' => 'true',
8978
                        'searchoptions' => [
8979
                            'dataInit' => 'date_pick_one_month',
8980
                            'sopt' => $date_operators,
8981
                        ],
8982
                    ],
8983
                    [
8984
                        'name' => 'visibility',
8985
                        'index' => 'visibility',
8986
                        'align' => 'left',
8987
                        'search' => 'false',
8988
                    ],
8989
                ];
8990
8991
                if ($showCount) {
8992
                    $columns[] = get_lang('Users');
8993
                    $columnModel[] = [
8994
                        'name' => 'users',
8995
                        'index' => 'users',
8996
                        'align' => 'left',
8997
                        'width' => '100',
8998
                        'search' => 'false',
8999
                    ];
9000
9001
                    // ofaj
9002
                    $columns[] = get_lang('Teachers');
9003
                    $columnModel[] = [
9004
                        'name' => 'teachers',
9005
                        'index' => 'teachers',
9006
                        'align' => 'left',
9007
                        'search' => 'false',
9008
                    ];
9009
                }
9010
9011
                $columns[] = get_lang('Session status');
9012
                $list = self::getStatusList();
9013
                $listToString = '';
9014
                foreach ($list as $statusId => $status) {
9015
                    $listToString .= $statusId.':'.$status.';';
9016
                }
9017
9018
                $columnModel[] = [
9019
                    'name' => 'status',
9020
                    'index' => 'status',
9021
                    'align' => 'left',
9022
                    'width' => '120',
9023
                    'search' => 'true',
9024
                    'stype' => 'select',
9025
                    // for the bottom bar
9026
                    'searchoptions' => [
9027
                        'defaultValue' => '1',
9028
                        'value' => $listToString,
9029
                    ],
9030
                ];
9031
9032
                break;
9033
9034
            case 'simple':
9035
                $columns = [
9036
                    '#',
9037
                    get_lang('Title'),
9038
                    get_lang('Category'),
9039
                    get_lang('Start date to display'),
9040
                    get_lang('End date to display'),
9041
                    get_lang('Visibility'),
9042
                ];
9043
9044
                $columnModel = [
9045
                    [
9046
                        'name' => 'id',
9047
                        'index' => 's.id',
9048
                        'hidden' => 'true',
9049
                    ],
9050
                    [
9051
                        'name' => 'title',
9052
                        'index' => 's.title',
9053
                        'width' => '300',
9054
                        'align' => 'left',
9055
                        'search' => 'true',
9056
                        'searchoptions' => ['sopt' => $operators],
9057
                    ],
9058
                    [
9059
                        'name' => 'category_name',
9060
                        'index' => 'category_name',
9061
                        'align' => 'left',
9062
                        'search' => 'true',
9063
                        'searchoptions' => ['sopt' => $operators],
9064
                    ],
9065
                    [
9066
                        'name' => 'display_start_date',
9067
                        'index' => 'display_start_date',
9068
                        'align' => 'left',
9069
                        'width' => '200',
9070
                        'search' => 'true',
9071
                        'searchoptions' => [
9072
                            'dataInit' => 'date_pick_today',
9073
                            'sopt' => $date_operators,
9074
                        ],
9075
                    ],
9076
                    [
9077
                        'name' => 'display_end_date',
9078
                        'index' => 'display_end_date',
9079
                        'align' => 'left',
9080
                        'width' => '200',
9081
                        'search' => 'true',
9082
                        'searchoptions' => [
9083
                            'dataInit' => 'date_pick_one_month',
9084
                            'sopt' => $date_operators,
9085
                        ],
9086
                    ],
9087
                    [
9088
                        'name' => 'visibility',
9089
                        'index' => 'visibility',
9090
                        'align' => 'left',
9091
                        'search' => 'false',
9092
                    ],
9093
                ];
9094
9095
                if ($showCount) {
9096
                    $columns[] = get_lang('Users');
9097
                    $columnModel[] = [
9098
                        'name' => 'users',
9099
                        'index' => 'users',
9100
                        'align' => 'left',
9101
                        'width' => '100',
9102
                        'search' => 'false',
9103
                    ];
9104
9105
                    // ofaj
9106
                    $columns[] = get_lang('Teachers');
9107
                    $columnModel[] = [
9108
                        'name' => 'teachers',
9109
                        'index' => 'teachers',
9110
                        'align' => 'left',
9111
                        'search' => 'false',
9112
                    ];
9113
                }
9114
9115
                $columns[] = get_lang('Session status');
9116
                $list = self::getStatusList();
9117
                $listToString = '';
9118
                foreach ($list as $statusId => $status) {
9119
                    $listToString .= $statusId.':'.$status.';';
9120
                }
9121
9122
                $columnModel[] = ['name' => 'status', 'index' => 'status', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
9123
                    // for the bottom bar
9124
                    'searchoptions' => [
9125
                        'defaultValue' => '1',
9126
                        'value' => $listToString,
9127
                    ],
9128
                ];
9129
9130
                break;
9131
            case 'complete':
9132
                $columns = [
9133
                    get_lang('Title'),
9134
                    get_lang('Start date to display'),
9135
                    get_lang('End date to display'),
9136
                    get_lang('Coach'),
9137
                    get_lang('Status'),
9138
                    get_lang('Visibility'),
9139
                    get_lang('Course title'),
9140
                ];
9141
                $columnModel = [
9142
                    [
9143
                        'name' => 'title',
9144
                        'index' => 's.title',
9145
                        'width' => '300',
9146
                        'align' => 'left',
9147
                        'search' => 'true',
9148
                        'searchoptions' => ['sopt' => $operators],
9149
                    ],
9150
                    [
9151
                        'name' => 'display_start_date',
9152
                        'index' => 'display_start_date',
9153
                        'align' => 'left',
9154
                        'width' => '200',
9155
                        'search' => 'true',
9156
                        'searchoptions' => ['dataInit' => 'date_pick_today', 'sopt' => $date_operators],
9157
                    ],
9158
                    [
9159
                        'name' => 'display_end_date',
9160
                        'index' => 'display_end_date',
9161
                        'width' => '200',
9162
                        'align' => 'left',
9163
                        'search' => 'true',
9164
                        'searchoptions' => ['dataInit' => 'date_pick_one_month', 'sopt' => $date_operators],
9165
                    ],
9166
                    [
9167
                        'name' => 'coach_name',
9168
                        'index' => 'coach_name',
9169
                        'align' => 'left',
9170
                        'search' => 'false',
9171
                        'searchoptions' => ['sopt' => $operators],
9172
                    ],
9173
                    [
9174
                        'name' => 'session_active',
9175
                        'index' => 'session_active',
9176
                        'align' => 'left',
9177
                        'search' => 'true',
9178
                        'stype' => 'select',
9179
                        // for the bottom bar
9180
                        'searchoptions' => [
9181
                            'defaultValue' => '1',
9182
                            'value' => '1:'.get_lang('Active').';0:'.get_lang('Inactive'),
9183
                        ],
9184
                        // for the top bar
9185
                        'editoptions' => [
9186
                            'value' => '" ":'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang(
9187
                                    'Inactive'
9188
                                ),
9189
                        ],
9190
                    ],
9191
                    [
9192
                        'name' => 'visibility',
9193
                        'index' => 'visibility',
9194
                        'align' => 'left',
9195
                        'search' => 'false',
9196
                    ],
9197
                    [
9198
                        'name' => 'course_title',
9199
                        'index' => 'course_title',
9200
                        'hidden' => 'true',
9201
                        'search' => 'true',
9202
                        'searchoptions' => ['searchhidden' => 'true', 'sopt' => $operators],
9203
                    ],
9204
                ];
9205
9206
                break;
9207
            case 'replication':
9208
            case 'custom':
9209
                $columns = [
9210
                    '#',
9211
                    get_lang('Title'),
9212
                    get_lang('Category'),
9213
                    get_lang('Start date to display'),
9214
                    get_lang('End date to display'),
9215
                    get_lang('Visibility'),
9216
                ];
9217
                $columnModel = [
9218
                    [
9219
                        'name' => 'id',
9220
                        'index' => 's.id',
9221
                        'hidden' => 'true',
9222
                    ],
9223
                    [
9224
                        'name' => 'title',
9225
                        'index' => 's.title',
9226
                        'width' => '260px',
9227
                        'width' => '300',
9228
                        'align' => 'left',
9229
                        'search' => 'true',
9230
                        'searchoptions' => ['sopt' => $operators],
9231
                    ],
9232
                    [
9233
                        'name' => 'category_name',
9234
                        'index' => 'category_name',
9235
                        'align' => 'left',
9236
                        'search' => 'true',
9237
                        'searchoptions' => ['sopt' => $operators],
9238
                    ],
9239
                    [
9240
                        'name' => 'display_start_date',
9241
                        'index' => 'display_start_date',
9242
                        'align' => 'left',
9243
                        'width' => '200',
9244
                        'search' => 'true',
9245
                        'searchoptions' => [
9246
                            'dataInit' => 'date_pick_today',
9247
                            'sopt' => $date_operators,
9248
                        ],
9249
                    ],
9250
                    [
9251
                        'name' => 'display_end_date',
9252
                        'index' => 'display_end_date',
9253
                        'align' => 'left',
9254
                        'width' => '200',
9255
                        'search' => 'true',
9256
                        'searchoptions' => [
9257
                            'dataInit' => 'date_pick_one_month',
9258
                            'sopt' => $date_operators,
9259
                        ],
9260
                    ],
9261
                    [
9262
                        'name' => 'visibility',
9263
                        'index' => 'visibility',
9264
                        'align' => 'left',
9265
                        'search' => 'false',
9266
                    ],
9267
                ];
9268
9269
                if ($showCount) {
9270
                    $columns[] = get_lang('Users');
9271
                    $columnModel[] = [
9272
                        'name' => 'users',
9273
                        'index' => 'users',
9274
                        'align' => 'left',
9275
                        'width' => '100',
9276
                        'search' => 'false',
9277
                    ];
9278
9279
                    // ofaj
9280
                    $columns[] = get_lang('Teachers');
9281
                    $columnModel[] = [
9282
                        'name' => 'teachers',
9283
                        'index' => 'teachers',
9284
                        'align' => 'left',
9285
                        'search' => 'false',
9286
                    ];
9287
                }
9288
9289
                $columns[] = get_lang('Session status');
9290
                $list = self::getStatusList();
9291
                $listToString = '';
9292
                foreach ($list as $statusId => $status) {
9293
                    $listToString .= $statusId.':'.$status.';';
9294
                }
9295
9296
                $columnModel[] = [
9297
                    'name' => 'status',
9298
                    'index' => 'status',
9299
                    'align' => 'left',
9300
                    'width' => '120',
9301
                    'search' => 'true',
9302
                    'stype' => 'select',
9303
                    // for the bottom bar
9304
                    'searchoptions' => [
9305
                        'defaultValue' => '1',
9306
                        'value' => $listToString,
9307
                    ],
9308
                ];
9309
9310
                break;
9311
        }
9312
9313
        if (!empty($extraFields)) {
9314
            foreach ($extraFields as $field) {
9315
                $columns[] = $field['display_text'];
9316
                $columnModel[] = [
9317
                    'name' => $field['variable'],
9318
                    'index' => $field['variable'],
9319
                    'align' => 'center',
9320
                    'search' => 'false',
9321
                ];
9322
            }
9323
        }
9324
9325
        // Inject extra session fields
9326
        $rules = [];
9327
        if ($addExtraFields) {
9328
            $sessionField = new ExtraFieldModel('session');
9329
            $rules = $sessionField->getRules($columns, $columnModel);
9330
        }
9331
9332
        if (!in_array('actions', array_column($columnModel, 'name'))) {
9333
            $columnModel[] = [
9334
                'name' => 'actions',
9335
                'index' => 'actions',
9336
                'align' => 'left',
9337
                'formatter' => 'action_formatter',
9338
                'sortable' => 'false',
9339
                'search' => 'false',
9340
            ];
9341
            $columns[] = get_lang('Actions');
9342
        }
9343
9344
        $columnName = [];
9345
        foreach ($columnModel as $col) {
9346
            $columnName[] = $col['name'];
9347
        }
9348
9349
        $return = [
9350
            'columns' => $columns,
9351
            'column_model' => $columnModel,
9352
            'rules' => $rules,
9353
            'simple_column_name' => $columnName,
9354
        ];
9355
9356
        return $return;
9357
    }
9358
9359
    /**
9360
     * Converts all dates sent through the param array (given form) to correct dates with timezones.
9361
     *
9362
     * @param array The dates The same array, with times converted
9363
     * @param bool $applyFormat Whether apply the DATE_TIME_FORMAT_SHORT format for sessions
9364
     *
9365
     * @return array The same array, with times converted
9366
     */
9367
    public static function convert_dates_to_local($params, $applyFormat = false)
9368
    {
9369
        if (!is_array($params)) {
9370
            return false;
9371
        }
9372
        $params['display_start_date'] = api_get_local_time($params['display_start_date'], null, null, true);
9373
        $params['display_end_date'] = api_get_local_time($params['display_end_date'], null, null, true);
9374
9375
        $params['access_start_date'] = api_get_local_time($params['access_start_date'], null, null, true);
9376
        $params['access_end_date'] = api_get_local_time($params['access_end_date'], null, null, true);
9377
9378
        $params['coach_access_start_date'] = isset($params['coach_access_start_date']) ? api_get_local_time($params['coach_access_start_date'], null, null, true) : null;
9379
        $params['coach_access_end_date'] = isset($params['coach_access_end_date']) ? api_get_local_time($params['coach_access_end_date'], null, null, true) : null;
9380
9381
        if ($applyFormat) {
9382
            if (isset($params['display_start_date'])) {
9383
                $params['display_start_date'] = api_format_date($params['display_start_date'], DATE_TIME_FORMAT_SHORT);
9384
            }
9385
9386
            if (isset($params['display_end_date'])) {
9387
                $params['display_end_date'] = api_format_date($params['display_end_date'], DATE_TIME_FORMAT_SHORT);
9388
            }
9389
9390
            if (isset($params['access_start_date'])) {
9391
                $params['access_start_date'] = api_format_date($params['access_start_date'], DATE_TIME_FORMAT_SHORT);
9392
            }
9393
9394
            if (isset($params['access_end_date'])) {
9395
                $params['access_end_date'] = api_format_date($params['access_end_date'], DATE_TIME_FORMAT_SHORT);
9396
            }
9397
9398
            if (isset($params['coach_access_start_date'])) {
9399
                $params['coach_access_start_date'] = api_format_date($params['coach_access_start_date'], DATE_TIME_FORMAT_SHORT);
9400
            }
9401
9402
            if (isset($params['coach_access_end_date'])) {
9403
                $params['coach_access_end_date'] = api_format_date($params['coach_access_end_date'], DATE_TIME_FORMAT_SHORT);
9404
            }
9405
        }
9406
9407
        return $params;
9408
    }
9409
9410
    /**
9411
     * Gets the admin session list callback of the session/session_list.php
9412
     * page with all user/details in the right fomat.
9413
     *
9414
     * @param array $options
9415
     *
9416
     * @return array Array of rows results
9417
     * @asset ('a') === false
9418
     */
9419
    public static function get_sessions_admin_complete($options = [])
9420
    {
9421
        if (!is_array($options)) {
9422
            return false;
9423
        }
9424
9425
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
9426
        $tbl_session_category = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
9427
        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
9428
        $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9429
        $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
9430
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
9431
9432
        $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
9433
        $tbl_session_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
9434
        $tbl_session_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
9435
9436
        $where = 'WHERE 1 = 1 ';
9437
9438
        if (!api_is_platform_admin()) {
9439
            if (api_is_session_admin() &&
9440
                'false' == api_get_setting('allow_session_admins_to_manage_all_sessions')
9441
            ) {
9442
                $user_id = api_get_user_id();
9443
                $where .= ' AND (sru.relation_type = '.Session::SESSION_ADMIN." AND sru.user_id = $user_id) ";
9444
            } else {
9445
                $where .= ' AND sru.relation_type = '.Session::GENERAL_COACH.' ';
9446
            }
9447
        }
9448
9449
        $coach_name = " CONCAT(u.lastname , ' ', u.firstname) as coach_name ";
9450
        if (api_is_western_name_order()) {
9451
            $coach_name = " CONCAT(u.firstname, ' ', u.lastname) as coach_name ";
9452
        }
9453
9454
        $today = api_get_utc_datetime();
9455
        $injectExtraFields = null;
9456
        $extra_fields_info = [];
9457
9458
        //for now only sessions
9459
        $extra_field = new ExtraFieldModel('session');
9460
        $double_fields = [];
9461
        $extra_field_option = new ExtraFieldOption('session');
9462
9463
        if (isset($options['extra'])) {
9464
            $extra_fields = $options['extra'];
9465
            if (!empty($extra_fields)) {
9466
                foreach ($extra_fields as $extra) {
9467
                    $injectExtraFields .= " IF (fv.field_id = {$extra['id']}, fvo.option_display_text, NULL ) as {$extra['field']} , ";
9468
                    if (isset($extra_fields_info[$extra['id']])) {
9469
                        $info = $extra_fields_info[$extra['id']];
9470
                    } else {
9471
                        $info = $extra_field->get($extra['id']);
9472
                        $extra_fields_info[$extra['id']] = $info;
9473
                    }
9474
9475
                    if (ExtraFieldModel::FIELD_TYPE_DOUBLE_SELECT == $info['value_type']) {
9476
                        $double_fields[$info['id']] = $info;
9477
                    }
9478
                }
9479
            }
9480
        }
9481
9482
        $options_by_double = [];
9483
        foreach ($double_fields as $double) {
9484
            $my_options = $extra_field_option->get_field_options_by_field(
9485
                $double['id'],
9486
                true
9487
            );
9488
            $options_by_double['extra_'.$double['field_variable']] = $my_options;
9489
        }
9490
9491
        //sc.title as category_name,
9492
        $select = "
9493
                SELECT * FROM (
9494
                    SELECT DISTINCT
9495
                        IF (
9496
                            (s.access_start_date <= '$today' AND '$today' < s.access_end_date) OR
9497
                            (s.access_start_date = '0000-00-00 00:00:00' AND s.access_end_date = '0000-00-00 00:00:00' ) OR
9498
                            (s.access_start_date IS NULL AND s.access_end_date IS NULL) OR
9499
                            (s.access_start_date <= '$today' AND ('0000-00-00 00:00:00' = s.access_end_date OR s.access_end_date IS NULL )) OR
9500
                            ('$today' < s.access_end_date AND ('0000-00-00 00:00:00' = s.access_start_date OR s.access_start_date IS NULL) )
9501
                        , 1, 0) as session_active,
9502
                s.title,
9503
                s.nbr_courses,
9504
                s.nbr_users,
9505
                s.display_start_date,
9506
                s.display_end_date,
9507
                $coach_name,
9508
                access_start_date,
9509
                access_end_date,
9510
                s.visibility,
9511
                u.id as user_id,
9512
                $injectExtraFields
9513
                c.title as course_title,
9514
                s.id ";
9515
9516
        if (!empty($options['where'])) {
9517
            if (!empty($options['extra'])) {
9518
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
9519
                $options['where'] = str_replace('AND', 'OR', $options['where']);
9520
                foreach ($options['extra'] as $extra) {
9521
                    $options['where'] = str_replace($extra['field'], 'fv.field_id = '.$extra['id'].' AND fvo.option_value', $options['where']);
9522
                }
9523
            }
9524
            $options['where'] = str_replace('course_title', 'c.title', $options['where']);
9525
            $options['where'] = str_replace("( session_active = '0' )", '1=1', $options['where']);
9526
            $options['where'] = str_replace(
9527
                ["AND session_active = '1'  )", " AND (  session_active = '1'  )"],
9528
                [') GROUP BY s.title HAVING session_active = 1 ', " GROUP BY s.title HAVING session_active = 1 "],
9529
                $options['where']
9530
            );
9531
9532
            $options['where'] = str_replace(
9533
                ["AND session_active = '0'  )", " AND (  session_active = '0'  )"],
9534
                [') GROUP BY s.title HAVING session_active = 0 ', " GROUP BY s.title HAVING session_active = '0' "],
9535
                $options['where']
9536
            );
9537
9538
            $where .= ' AND '.$options['where'];
9539
        }
9540
9541
        $limit = '';
9542
        if (!empty($options['limit'])) {
9543
            $limit = ' LIMIT '.$options['limit'];
9544
        }
9545
9546
        $query = "$select FROM $tbl_session s
9547
                    LEFT JOIN $tbl_session_field_values fv
9548
                    ON (fv.item_id = s.id)
9549
                    LEFT JOIN $extraFieldTable f
9550
                    ON f.id = fv.field_id
9551
                    LEFT JOIN $tbl_session_field_options fvo
9552
                    ON (fv.field_id = fvo.field_id)
9553
                    LEFT JOIN $tbl_session_rel_course src
9554
                    ON (src.session_id = s.id)
9555
                    LEFT JOIN $tbl_course c
9556
                    ON (src.c_id = c.id)
9557
                    LEFT JOIN $tbl_session_category sc
9558
                    ON (s.session_category_id = sc.id)
9559
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9560
                    INNER JOIN $tbl_user u
9561
                    ON sru.user_id = u.id
9562
                    $where
9563
                    $limit
9564
        ";
9565
9566
        if (api_is_multiple_url_enabled()) {
9567
            $table_access_url_rel_session = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
9568
            $access_url_id = api_get_current_access_url_id();
9569
            if (-1 != $access_url_id) {
9570
                $query = "$select
9571
                    FROM $tbl_session s
9572
                    LEFT JOIN $tbl_session_field_values fv
9573
                    ON (fv.item_id = s.id)
9574
                    LEFT JOIN $tbl_session_field_options fvo
9575
                    ON (fv.field_id = fvo.field_id)
9576
                    LEFT JOIN $tbl_session_rel_course src
9577
                    ON (src.session_id = s.id)
9578
                    LEFT JOIN $tbl_course c
9579
                    ON (src.c_id = c.id)
9580
                    LEFT JOIN $tbl_session_category sc
9581
                    ON (s.session_category_id = sc.id)
9582
                    INNER JOIN $tblSessionRelUser sru ON s.id = sru.session_id
9583
                    INNER JOIN $tbl_user u
9584
                    ON sru.user_id = u.id
9585
                    INNER JOIN $table_access_url_rel_session ar
9586
                    ON (ar.session_id = s.id AND ar.access_url_id = $access_url_id)
9587
                    $where
9588
                    $limit
9589
                ";
9590
            }
9591
        }
9592
9593
        $query .= ') AS s';
9594
9595
        if (!empty($options['order'])) {
9596
            $query .= ' ORDER BY '.$options['order'];
9597
        }
9598
9599
        $result = Database::query($query);
9600
9601
        $acceptIcon = Display::getMdiIcon(StateIcon::ACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Active'));
9602
9603
        $errorIcon = Display::getMdiIcon(StateIcon::INACTIVE, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Inactive'));
9604
9605
        $formatted_sessions = [];
9606
        if (Database::num_rows($result)) {
9607
            $sessions = Database::store_result($result, 'ASSOC');
9608
            foreach ($sessions as $session) {
9609
                $session_id = $session['id'];
9610
                $session['title'] = Display::url($session['title'], "resume_session.php?id_session=".$session['id']);
9611
                $session['coach_name'] = Display::url($session['coach_name'], "user_information.php?user_id=".$session['user_id']);
9612
                if (1 == $session['session_active']) {
9613
                    $session['session_active'] = $acceptIcon;
9614
                } else {
9615
                    $session['session_active'] = $errorIcon;
9616
                }
9617
9618
                $session = self::convert_dates_to_local($session);
9619
9620
                switch ($session['visibility']) {
9621
                    case SESSION_VISIBLE_READ_ONLY: //1
9622
                        $session['visibility'] = get_lang('Read only');
9623
                        break;
9624
                    case SESSION_VISIBLE:           //2
9625
                    case SESSION_AVAILABLE:         //4
9626
                        $session['visibility'] = get_lang('Visible');
9627
                        break;
9628
                    case SESSION_INVISIBLE:         //3
9629
                        $session['visibility'] = api_ucfirst(get_lang('invisible'));
9630
                        break;
9631
                }
9632
9633
                // Cleaning double selects
9634
                foreach ($session as $key => &$value) {
9635
                    if (isset($options_by_double[$key]) || isset($options_by_double[$key.'_second'])) {
9636
                        $options = explode('::', $value);
9637
                    }
9638
                    $original_key = $key;
9639
9640
                    if (false === strpos($key, '_second')) {
9641
                    } else {
9642
                        $key = str_replace('_second', '', $key);
9643
                    }
9644
9645
                    if (isset($options_by_double[$key])) {
9646
                        if (isset($options[0])) {
9647
                            if (isset($options_by_double[$key][$options[0]])) {
9648
                                if (false === strpos($original_key, '_second')) {
9649
                                    $value = $options_by_double[$key][$options[0]]['option_display_text'];
9650
                                } else {
9651
                                    $value = $options_by_double[$key][$options[1]]['option_display_text'];
9652
                                }
9653
                            }
9654
                        }
9655
                    }
9656
                }
9657
9658
                // Magic filter
9659
                if (isset($formatted_sessions[$session_id])) {
9660
                    $formatted_sessions[$session_id] = self::compareArraysToMerge(
9661
                        $formatted_sessions[$session_id],
9662
                        $session
9663
                    );
9664
                } else {
9665
                    $formatted_sessions[$session_id] = $session;
9666
                }
9667
            }
9668
        }
9669
9670
        return $formatted_sessions;
9671
    }
9672
9673
    /**
9674
     * Compare two arrays.
9675
     *
9676
     * @param array $array1
9677
     * @param array $array2
9678
     *
9679
     * @return array
9680
     */
9681
    public static function compareArraysToMerge($array1, $array2)
9682
    {
9683
        if (empty($array2)) {
9684
            return $array1;
9685
        }
9686
        foreach ($array1 as $key => $item) {
9687
            if (!isset($array1[$key])) {
9688
                //My string is empty try the other one
9689
                if (isset($array2[$key]) && !empty($array2[$key])) {
9690
                    $array1[$key] = $array2[$key];
9691
                }
9692
            }
9693
        }
9694
9695
        return $array1;
9696
    }
9697
9698
    /**
9699
     * Get link to the admin page for this session.
9700
     *
9701
     * @param int $id Session ID
9702
     *
9703
     * @return mixed URL to the admin page to manage the session, or false on error
9704
     */
9705
    public static function getAdminPath($id)
9706
    {
9707
        $id = (int) $id;
9708
        $session = self::fetch($id);
9709
        if (empty($session)) {
9710
            return false;
9711
        }
9712
9713
        return api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$id;
9714
    }
9715
9716
    /**
9717
     * Get link to the user page for this session.
9718
     * If a course is provided, build the link to the course.
9719
     *
9720
     * @param int $id       Session ID
9721
     * @param int $courseId Course ID (optional) in case the link has to send straight to the course
9722
     *
9723
     * @return mixed URL to the page to use the session, or false on error
9724
     */
9725
    public static function getPath($id, $courseId = 0)
9726
    {
9727
        $id = (int) $id;
9728
        $session = self::fetch($id);
9729
        if (empty($session)) {
9730
            return false;
9731
        }
9732
        if (empty($courseId)) {
9733
            return api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$id;
9734
        } else {
9735
            $courseInfo = api_get_course_info_by_id($courseId);
9736
            if ($courseInfo) {
9737
                return $courseInfo['course_public_url'].'?id_session='.$id;
9738
            }
9739
        }
9740
9741
        return false;
9742
    }
9743
9744
    /**
9745
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9746
     * where course id_course is in sessions id_session1, id_session2
9747
     * for course where user is coach
9748
     * i.e. coach for the course or
9749
     * main coach for a session the course is in
9750
     * for a session category (or woth no session category if empty).
9751
     *
9752
     * @param int $userId
9753
     *
9754
     * @return array
9755
     */
9756
    public static function getSessionCourseForUser($userId)
9757
    {
9758
        // list of COURSES where user is COURSE session coach
9759
        $listCourseCourseCoachSession = self::getCoursesForCourseSessionCoach($userId);
9760
        // list of courses where user is MAIN session coach
9761
        $listCourseMainCoachSession = self::getCoursesForMainSessionCoach($userId);
9762
        // merge these 2 array
9763
        $listResCourseSession = $listCourseCourseCoachSession;
9764
        foreach ($listCourseMainCoachSession as $courseId2 => $listSessionId2) {
9765
            if (isset($listResCourseSession[$courseId2])) {
9766
                // if sessionId array exists for this course
9767
                // same courseId, merge the list of session
9768
                foreach ($listCourseMainCoachSession[$courseId2] as $i => $sessionId2) {
9769
                    if (!in_array($sessionId2, $listResCourseSession[$courseId2])) {
9770
                        $listResCourseSession[$courseId2][] = $sessionId2;
9771
                    }
9772
                }
9773
            } else {
9774
                $listResCourseSession[$courseId2] = $listSessionId2;
9775
            }
9776
        }
9777
9778
        return $listResCourseSession;
9779
    }
9780
9781
    /**
9782
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9783
     * where course id_course is in sessions id_session1, id_session2.
9784
     *
9785
     * @param int $userId
9786
     *
9787
     * @return array
9788
     */
9789
    public static function getCoursesForCourseSessionCoach($userId)
9790
    {
9791
        $userId = (int) $userId;
9792
        $listResCourseSession = [];
9793
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9794
        $tblSessionRelCourseRelUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9795
9796
        $sql = "SELECT session_id, c_id, c.id
9797
                FROM $tblSessionRelCourseRelUser srcru
9798
                LEFT JOIN $tblCourse c
9799
                ON c.id = srcru.c_id
9800
                WHERE
9801
                    srcru.user_id = $userId AND
9802
                    srcru.status = ".Session::COURSE_COACH;
9803
9804
        $res = Database::query($sql);
9805
9806
        while ($data = Database::fetch_assoc($res)) {
9807
            if (api_get_session_visibility($data['session_id'])) {
9808
                if (!isset($listResCourseSession[$data['id']])) {
9809
                    $listResCourseSession[$data['id']] = [];
9810
                }
9811
                $listResCourseSession[$data['id']][] = $data['session_id'];
9812
            }
9813
        }
9814
9815
        return $listResCourseSession;
9816
    }
9817
9818
    /**
9819
     * Return an associative array 'id_course' => [id_session1, id_session2...]
9820
     * where course id_course is in sessions id_session1, id_session2.
9821
     *
9822
     * @param $userId
9823
     *
9824
     * @return array
9825
     */
9826
    public static function getCoursesForMainSessionCoach($userId)
9827
    {
9828
        $userId = (int) $userId;
9829
        $user = api_get_user_entity($userId);
9830
        $listResCourseSession = [];
9831
9832
        $sessions = $user->getSessionsAsGeneralCoach();
9833
9834
        foreach ($sessions as $session) {
9835
            $sessionId = $session->getId();
9836
            $listCoursesInSession = self::getCoursesInSession($sessionId);
9837
            foreach ($listCoursesInSession as $i => $courseId) {
9838
                if (api_get_session_visibility($sessionId)) {
9839
                    if (!isset($listResCourseSession[$courseId])) {
9840
                        $listResCourseSession[$courseId] = [];
9841
                    }
9842
                    $listResCourseSession[$courseId][] = $sessionId;
9843
                }
9844
            }
9845
        }
9846
9847
        return $listResCourseSession;
9848
    }
9849
9850
    /**
9851
     * Return an array of course_id used in session $sessionId.
9852
     *
9853
     * @param $sessionId
9854
     *
9855
     * @return array
9856
     */
9857
    public static function getCoursesInSession($sessionId)
9858
    {
9859
        if (empty($sessionId)) {
9860
            return [];
9861
        }
9862
9863
        $tblSessionRelCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
9864
        $tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
9865
9866
        // list of course in this session
9867
        $sql = "SELECT session_id, c.id
9868
                FROM $tblSessionRelCourse src
9869
                LEFT JOIN $tblCourse c
9870
                ON c.id = src.c_id
9871
                WHERE session_id = ".intval($sessionId);
9872
        $res = Database::query($sql);
9873
9874
        $listResultsCourseId = [];
9875
        while ($data = Database::fetch_assoc($res)) {
9876
            $listResultsCourseId[] = $data['id'];
9877
        }
9878
9879
        return $listResultsCourseId;
9880
    }
9881
9882
    /**
9883
     * Return an array of courses in session for user
9884
     * and for each courses the list of session that use this course for user.
9885
     *
9886
     * [0] => array
9887
     *      userCatId
9888
     *      userCatTitle
9889
     *      courseInUserCatList
9890
     *          [0] => array
9891
     *              courseId
9892
     *              title
9893
     *              courseCode
9894
     *              sessionCatList
9895
     *                  [0] => array
9896
     *                      catSessionId
9897
     *                      catSessionName
9898
     *                      sessionList
9899
     *                          [0] => array
9900
     *                              sessionId
9901
     *                              sessionName
9902
     *
9903
     * @param int $userId
9904
     *
9905
     * @return array
9906
     */
9907
    public static function getNamedSessionCourseForCoach($userId)
9908
    {
9909
        $listResults = [];
9910
        $listCourseSession = self::getSessionCourseForUser($userId);
9911
        foreach ($listCourseSession as $courseId => $listSessionId) {
9912
            // Course info
9913
            $courseInfo = api_get_course_info_by_id($courseId);
9914
            $listOneCourse = [];
9915
            $listOneCourse['courseId'] = $courseId;
9916
            $listOneCourse['title'] = $courseInfo['title'];
9917
            //$listOneCourse['courseCode'] = $courseInfo['code'];
9918
            $listOneCourse['course'] = $courseInfo;
9919
            $listOneCourse['sessionCatList'] = [];
9920
            $listCat = [];
9921
            foreach ($listSessionId as $i => $sessionId) {
9922
                // here we got all session for this course
9923
                // lets check there session categories
9924
                $sessionInfo = self::fetch($sessionId);
9925
                $catId = $sessionInfo['session_category_id'];
9926
                if (!isset($listCat[$catId])) {
9927
                    $listCatInfo = self::get_session_category($catId);
9928
                    if ($listCatInfo) {
9929
                        $listCat[$catId] = [];
9930
                        $listCat[$catId]['catSessionId'] = $catId;
9931
                        $listCat[$catId]['catSessionName'] = $listCatInfo['title'];
9932
                        $listCat[$catId]['sessionList'] = [];
9933
                    }
9934
                }
9935
                $listSessionInfo = self::fetch($sessionId);
9936
                $listSessionIdName = [
9937
                    'sessionId' => $sessionId,
9938
                    'sessionName' => $listSessionInfo['title'],
9939
                ];
9940
                $listCat[$catId]['sessionList'][] = $listSessionIdName;
9941
            }
9942
            // sort $listCat by catSessionName
9943
            usort($listCat, 'self::compareBySessionName');
9944
            // in each catSession sort sessionList by sessionName
9945
            foreach ($listCat as $i => $listCatSessionInfo) {
9946
                $listSessionList = $listCatSessionInfo['sessionList'];
9947
                usort($listSessionList, 'self::compareCatSessionInfo');
9948
                $listCat[$i]['sessionList'] = $listSessionList;
9949
            }
9950
9951
            $listOneCourse['sessionCatList'] = $listCat;
9952
            //$listResults[$userCatId]['courseInUserCatList'][] = $listOneCourse;
9953
        }
9954
9955
        // sort by user course cat
9956
        uasort($listResults, 'self::compareByUserCourseCat');
9957
9958
        // sort by course title
9959
        foreach ($listResults as $userCourseCatId => $tabCoursesInCat) {
9960
            $courseInUserCatList = $tabCoursesInCat['courseInUserCatList'];
9961
            uasort($courseInUserCatList, 'self::compareByCourse');
9962
            $listResults[$userCourseCatId]['courseInUserCatList'] = $courseInUserCatList;
9963
        }
9964
9965
        return $listResults;
9966
    }
9967
9968
    /**
9969
     * @param int $userId
9970
     * @param int $courseId
9971
     *
9972
     * @return array
9973
     */
9974
    public static function searchCourseInSessionsFromUser($userId, $courseId)
9975
    {
9976
        $table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
9977
        $userId = (int) $userId;
9978
        $courseId = (int) $courseId;
9979
        if (empty($userId) || empty($courseId)) {
9980
            return [];
9981
        }
9982
9983
        $sql = "SELECT * FROM $table
9984
                WHERE c_id = $courseId AND user_id = $userId";
9985
        $result = Database::query($sql);
9986
9987
        return Database::store_result($result, 'ASSOC');
9988
    }
9989
9990
    /**
9991
     * Subscribe and redirect to session after inscription.
9992
     */
9993
    public static function redirectToSession()
9994
    {
9995
        $sessionId = (int) ChamiloSession::read('session_redirect');
9996
        $onlyOneCourseSessionToRedirect = ChamiloSession::read('only_one_course_session_redirect');
9997
        if ($sessionId) {
9998
            $sessionInfo = api_get_session_info($sessionId);
9999
            if (!empty($sessionInfo)) {
10000
                $userId = api_get_user_id();
10001
                $response = self::isUserSubscribedAsStudent($sessionId, $userId);
10002
                if ($response) {
10003
                    $urlToRedirect = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId;
10004
                    if (!empty($onlyOneCourseSessionToRedirect)) {
10005
                        $urlToRedirect = api_get_path(WEB_PATH).
10006
                            'courses/'.$onlyOneCourseSessionToRedirect.'/index.php?id_session='.$sessionId;
10007
                    }
10008
10009
                    header('Location: '.$urlToRedirect);
10010
                    exit;
10011
                }
10012
            }
10013
        }
10014
    }
10015
10016
    /**
10017
     * @return int
10018
     */
10019
    public static function getCountUsersInCourseSession(Course $course, Session $session)
10020
    {
10021
        $url = api_get_url_entity(api_get_current_access_url_id());
10022
10023
        return Database::getManager()
10024
            ->createQuery("
10025
                SELECT COUNT(scu)
10026
                FROM ChamiloCoreBundle:SessionRelCourseRelUser scu
10027
                INNER JOIN ChamiloCoreBundle:SessionRelUser su
10028
                    WITH scu.user = su.user
10029
                    AND scu.session = su.session
10030
                INNER JOIN ChamiloCoreBundle:AccessUrlRelUser a
10031
                    WITH a.user = su.user
10032
                WHERE
10033
                    scu.course = :course AND
10034
                    su.relationType <> :relationType AND
10035
                    scu.session = :session AND
10036
                    a.url = :url
10037
            ")
10038
            ->setParameters([
10039
                'course' => $course->getId(),
10040
                'relationType' => Session::DRH,
10041
                'session' => $session->getId(),
10042
                'url' => $url,
10043
            ])
10044
            ->getSingleScalarResult();
10045
    }
10046
10047
    /**
10048
     * Get course IDs where user in not subscribed in session.
10049
     *
10050
     * @return array
10051
     */
10052
    public static function getAvoidedCoursesInSession(User $user, Session $session)
10053
    {
10054
        $courseIds = [];
10055
10056
        /** @var SessionRelCourse $sessionCourse */
10057
        foreach ($session->getCourses() as $sessionCourse) {
10058
            /** @var Course $course */
10059
            $course = $sessionCourse->getCourse();
10060
10061
            if ($session->getUserInCourse($user, $course)->count()) {
10062
                continue;
10063
            }
10064
10065
            $courseIds[] = $course->getId();
10066
        }
10067
10068
        return $courseIds;
10069
    }
10070
10071
    /**
10072
     * @param int             $userId
10073
     * @param int             $sessionId
10074
     * @param ExtraFieldValue $extraFieldValue
10075
     * @param string          $collapsableLink
10076
     *
10077
     * @return array
10078
     */
10079
    public static function getCollapsableData($userId, $sessionId, $extraFieldValue, $collapsableLink)
10080
    {
10081
        $collapsed = 0;
10082
10083
        // Get default collapsed value in extra field
10084
        $value = $extraFieldValue->get_values_by_handler_and_field_variable($sessionId, 'collapsed');
10085
        if (!empty($value) && isset($value['value'])) {
10086
            $collapsed = $value['value'];
10087
        }
10088
10089
        $userRelSession = self::getUserSession($userId, $sessionId);
10090
10091
        if ($userRelSession) {
10092
            if (isset($userRelSession['collapsed']) && '' != $userRelSession['collapsed']) {
10093
                $collapsed = $userRelSession['collapsed'];
10094
            }
10095
        } else {
10096
            return ['collapsed' => $collapsed, 'collapsable_link' => '&nbsp;'];
10097
        }
10098
10099
        $link = $collapsableLink.'&session_id='.$sessionId.'&value=1';
10100
        $image = '<i class="fa fa-folder-open"></i>';
10101
        if (1 == $collapsed) {
10102
            $link = $collapsableLink.'&session_id='.$sessionId.'&value=0';
10103
            $image = '<i class="fa fa-folder"></i>';
10104
        }
10105
10106
        $link = Display::url(
10107
            $image,
10108
            $link
10109
        );
10110
10111
        return ['collapsed' => $collapsed, 'collapsable_link' => $link];
10112
    }
10113
10114
    /**
10115
     * Converts "start date" and "end date" to "From start date to end date" string.
10116
     *
10117
     * @param string|DateTime $startDate
10118
     * @param string|DateTime $endDate
10119
     * @param bool   $showTime
10120
     * @param bool   $dateHuman
10121
     *
10122
     * @return string
10123
     */
10124
    public static function convertSessionDateToString($startDate, $endDate, $showTime, $dateHuman)
10125
    {
10126
        // api_get_local_time returns empty if date is invalid like 0000-00-00 00:00:00
10127
        $startDateToLocal = api_get_local_time(
10128
            $startDate,
10129
            null,
10130
            null,
10131
            true,
10132
            $showTime,
10133
            $dateHuman
10134
        );
10135
        $endDateToLocal = api_get_local_time(
10136
            $endDate,
10137
            null,
10138
            null,
10139
            true,
10140
            $showTime,
10141
            $dateHuman
10142
        );
10143
10144
        $format = $showTime ? DATE_TIME_FORMAT_LONG_24H : DATE_FORMAT_LONG_NO_DAY;
10145
10146
        $result = '';
10147
        if (!empty($startDateToLocal) && !empty($endDateToLocal)) {
10148
            $result = sprintf(
10149
                get_lang('From %s to %s'),
10150
                api_format_date($startDateToLocal, $format),
10151
                api_format_date($endDateToLocal, $format)
10152
            );
10153
        } else {
10154
            if (!empty($startDateToLocal)) {
10155
                $result = get_lang('From').' '.api_format_date($startDateToLocal, $format);
10156
            }
10157
            if (!empty($endDateToLocal)) {
10158
                $result = get_lang('Until').' '.api_format_date($endDateToLocal, $format);
10159
            }
10160
        }
10161
        if (empty($result)) {
10162
            $result = get_lang('No time limits');
10163
        }
10164
10165
        return $result;
10166
    }
10167
10168
    /**
10169
     * @param int $id
10170
     */
10171
    public static function getSessionChangeUserReason($id): string
10172
    {
10173
        $reasons = self::getSessionChangeUserReasons();
10174
10175
        return $reasons[$id] ?? '';
10176
    }
10177
10178
    public static function getSessionChangeUserReasons(): array
10179
    {
10180
        return [
10181
            self::SESSION_CHANGE_USER_REASON_SCHEDULE => get_lang('Schedule changed'),
10182
            self::SESSION_CHANGE_USER_REASON_CLASSROOM => get_lang('Classroom changed'),
10183
            self::SESSION_CHANGE_USER_REASON_LOCATION => get_lang('Location changed'),
10184
            //self::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION => get_lang('Enrollment cancelled'),
10185
        ];
10186
    }
10187
10188
    public static function getStatusList()
10189
    {
10190
        return [
10191
            self::STATUS_PLANNED => get_lang('Planned'),
10192
            self::STATUS_PROGRESS => get_lang('In progress'),
10193
            self::STATUS_FINISHED => get_lang('Finished'),
10194
            self::STATUS_CANCELLED => get_lang('Cancelled'),
10195
        ];
10196
    }
10197
10198
    public static function getStatusLabel($status)
10199
    {
10200
        $list = self::getStatusList();
10201
10202
        if (!isset($list[$status])) {
10203
            return get_lang('No status');
10204
        }
10205
10206
        return $list[$status];
10207
    }
10208
10209
    public static function getDefaultSessionTab()
10210
    {
10211
        $default = 'all';
10212
        $view = api_get_setting('session.default_session_list_view');
10213
10214
        if ('false' !== $view && !empty($view)) {
10215
            $default = $view;
10216
        }
10217
10218
        return $default;
10219
    }
10220
10221
    /**
10222
     * @return string
10223
     */
10224
    public static function getSessionListTabs($listType): string
10225
    {
10226
        $tabs = [
10227
            [
10228
                'content' => get_lang('All sessions'),
10229
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=all',
10230
            ],
10231
            [
10232
                'content' => get_lang('Active sessions'),
10233
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=active',
10234
            ],
10235
            [
10236
                'content' => get_lang('Closed sessions'),
10237
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=close',
10238
            ],
10239
            [
10240
                'content' => get_lang('Custom list'),
10241
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=custom',
10242
            ],
10243
            [
10244
                'content' => get_lang('Replication'),
10245
                'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=replication',
10246
            ],
10247
        ];
10248
        $default = null;
10249
        switch ($listType) {
10250
            case 'all':
10251
                $default = 1;
10252
                break;
10253
            case 'active':
10254
                $default = 2;
10255
                break;
10256
            case 'close':
10257
                $default = 3;
10258
                break;
10259
            case 'custom':
10260
                $default = 4;
10261
                break;
10262
            case 'replication':
10263
                $default = 5;
10264
                break;
10265
        }
10266
10267
        return Display::tabsOnlyLink($tabs, $default);
10268
    }
10269
10270
    /**
10271
     * Check if a session is followed by human resources manager.
10272
     *
10273
     * @param int $sessionId
10274
     * @param int $userId
10275
     *
10276
     * @return bool
10277
     */
10278
    public static function isSessionFollowedByDrh($sessionId, $userId)
10279
    {
10280
        $userId = (int) $userId;
10281
        $sessionId = (int) $sessionId;
10282
10283
        $tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
10284
        $tblSessionRelUser = Database::get_main_table(TABLE_MAIN_SESSION_USER);
10285
10286
        if (api_is_multiple_url_enabled()) {
10287
            $tblSessionRelAccessUrl = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
10288
10289
            $sql = "SELECT s.id FROM $tblSession s
10290
                INNER JOIN $tblSessionRelUser sru ON (sru.session_id = s.id)
10291
                LEFT JOIN $tblSessionRelAccessUrl a ON (s.id = a.session_id)
10292
                WHERE
10293
                    sru.user_id = '$userId' AND
10294
                    sru.session_id = '$sessionId' AND
10295
                    sru.relation_type = '".Session::DRH."' AND
10296
                    access_url_id = ".api_get_current_access_url_id();
10297
        } else {
10298
            $sql = "SELECT s.id FROM $tblSession s
10299
                INNER JOIN $tblSessionRelUser sru ON sru.session_id = s.id
10300
                WHERE
10301
                    sru.user_id = '$userId' AND
10302
                    sru.session_id = '$sessionId' AND
10303
                    sru.relation_type = '".Session::DRH."'";
10304
        }
10305
10306
        $result = Database::query($sql);
10307
10308
        return Database::num_rows($result) > 0;
10309
    }
10310
10311
    /**
10312
     * Add a warning message when session is read-only mode.
10313
     */
10314
    public static function addFlashSessionReadOnly()
10315
    {
10316
        if (api_get_session_id() && !api_is_allowed_to_session_edit()) {
10317
            Display::addFlash(
10318
                Display::return_message(get_lang('The session is read only'), 'warning')
10319
            );
10320
        }
10321
    }
10322
10323
    public static function insertUsersInCourses(array $studentIds, array $courseIds, int $sessionId)
10324
    {
10325
        $session = api_get_session_entity($sessionId);
10326
10327
        foreach ($courseIds as $courseId) {
10328
            self::insertUsersInCourse($studentIds, $courseId, $sessionId, [], false);
10329
        }
10330
10331
        foreach ($studentIds as $studentId) {
10332
            $user = api_get_user_entity($studentId);
10333
10334
            $session->addUserInSession(Session::STUDENT, $user);
10335
        }
10336
    }
10337
10338
    /**
10339
     * @throws \Doctrine\ORM\Exception\ORMException
10340
     */
10341
    public static function insertUsersInCourse(
10342
        array $studentIds,
10343
        int $courseId,
10344
        int $sessionId,
10345
        array $relationInfo = [],
10346
        bool $updateSession = true,
10347
        bool $sendNotification = false
10348
    ) {
10349
        $em = Database::getManager();
10350
        $course = api_get_course_entity($courseId);
10351
        $session = api_get_session_entity($sessionId);
10352
10353
        $relationInfo = array_merge(['visibility' => 0, 'status' => Session::STUDENT], $relationInfo);
10354
10355
        $usersToInsert = [];
10356
        foreach ($studentIds as $studentId) {
10357
            $user = api_get_user_entity($studentId);
10358
            $session->addUserInCourse($relationInfo['status'], $user, $course)
10359
                ->setVisibility($relationInfo['visibility']);
10360
10361
            Event::logUserSubscribedInCourseSession($user, $course, $session);
10362
10363
            if ($updateSession) {
10364
                if (!$session->hasUserInSession($user, Session::STUDENT)) {
10365
                    $session->addUserInSession(Session::STUDENT, $user);
10366
                }
10367
            }
10368
10369
            $usersToInsert[] = $studentId;
10370
        }
10371
10372
        $em->persist($session);
10373
        $em->flush();
10374
10375
        if ($sendNotification && !empty($usersToInsert)) {
10376
            foreach ($usersToInsert as $userId) {
10377
                $user = api_get_user_entity($userId);
10378
                $courseTitle = $course->getTitle();
10379
                $sessionTitle = $session->getTitle();
10380
10381
                $subject = sprintf(get_lang('You have been enrolled in the course %s for the session %s'), $courseTitle, $sessionTitle);
10382
                $message = sprintf(
10383
                    get_lang('Hello %s, you have been enrolled in the course %s for the session %s.'),
10384
                    UserManager::formatUserFullName($user, true),
10385
                    $courseTitle,
10386
                    $sessionTitle
10387
                );
10388
10389
                MessageManager::send_message_simple(
10390
                    $userId,
10391
                    $subject,
10392
                    $message,
10393
                    api_get_user_id(),
10394
                    false,
10395
                    true,
10396
                    false
10397
                );
10398
            }
10399
        }
10400
    }
10401
10402
    public static function getCareersFromSession(int $sessionId): array
10403
    {
10404
        $extraFieldValueSession = new ExtraFieldValue('session');
10405
        $extraFieldValueCareer = new ExtraFieldValue('career');
10406
10407
        $value = $extraFieldValueSession->get_values_by_handler_and_field_variable($sessionId, 'careerid');
10408
        $careers = [];
10409
        if (isset($value['value']) && !empty($value['value'])) {
10410
            $careerList = str_replace(['[', ']'], '', $value['value']);
10411
            $careerList = explode(',', $careerList);
10412
10413
            $careerManager = new Career();
10414
            foreach ($careerList as $career) {
10415
                $careerIdValue = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
10416
                    'external_career_id',
10417
                    $career
10418
                );
10419
                if (isset($careerIdValue['item_id']) && !empty($careerIdValue['item_id'])) {
10420
                    $finalCareerId = $careerIdValue['item_id'];
10421
                    $careerInfo = $careerManager->get($finalCareerId);
10422
                    if (!empty($careerInfo)) {
10423
                        $careers[] = $careerInfo;
10424
                    }
10425
                }
10426
            }
10427
        }
10428
10429
        return $careers;
10430
    }
10431
10432
    public static function getCareerDiagramPerSessionList($sessionList, $userId)
10433
    {
10434
        if (empty($sessionList) || empty($userId)) {
10435
            return '';
10436
        }
10437
10438
        $userId = (int) $userId;
10439
        $content = Display::page_subheader(get_lang('Ongoing training'));
10440
        $content .= '
10441
           <script>
10442
            resizeIframe = function(iFrame) {
10443
                iFrame.height = iFrame.contentWindow.document.body.scrollHeight + 20;
10444
            }
10445
            </script>
10446
        ';
10447
        $careersAdded = [];
10448
        foreach ($sessionList as $sessionId) {
10449
            $visibility = api_get_session_visibility($sessionId, null, false, $userId);
10450
            if (SESSION_AVAILABLE === $visibility) {
10451
                $careerList = self::getCareersFromSession($sessionId);
10452
                if (empty($careerList)) {
10453
                    continue;
10454
                }
10455
                foreach ($careerList as $career) {
10456
                    $careerId = $career['id'];
10457
                    if (!in_array($careerId, $careersAdded)) {
10458
                        $careersAdded[] = $careerId;
10459
                        $careerUrl = api_get_path(WEB_CODE_PATH).'user/career_diagram.php?iframe=1&career_id='.$career['id'].'&user_id='.$userId;
10460
                        $content .= '
10461
                            <iframe
10462
                                onload="resizeIframe(this)"
10463
                                style="width:100%;"
10464
                                border="0"
10465
                                frameborder="0"
10466
                                scrolling="no"
10467
                                src="'.$careerUrl.'"
10468
                            ></iframe>';
10469
                    }
10470
                }
10471
            }
10472
        }
10473
10474
        return $content;
10475
    }
10476
10477
    private static function allowed(?Session $session = null): bool
10478
    {
10479
        if (api_is_platform_admin()) {
10480
            return true;
10481
        }
10482
10483
        if (null === $session) {
10484
            return false;
10485
        }
10486
10487
        $user = api_get_user_entity();
10488
10489
        if (api_is_session_admin() &&
10490
            'true' !== api_get_setting('session.allow_session_admins_to_manage_all_sessions')
10491
        ) {
10492
10493
            if (!$session->hasUserAsSessionAdmin($user)) {
10494
                return false;
10495
            }
10496
        }
10497
10498
        if (api_is_teacher() &&
10499
            'true' === api_get_setting('session.allow_teachers_to_create_sessions')
10500
        ) {
10501
            if (!$session->hasUserAsGeneralCoach($user))  {
10502
                return false;
10503
            }
10504
        }
10505
10506
        return true;
10507
    }
10508
10509
    /**
10510
     * Add classes (by their names) to a session.
10511
     *
10512
     * @param int   $sessionId
10513
     * @param array $classesNames
10514
     * @param bool  $deleteClassSessions Optional. Empty the session list for the usergroup (class)
10515
     */
10516
    private static function addClassesByName($sessionId, $classesNames, $deleteClassSessions = true)
10517
    {
10518
        if (!$classesNames) {
10519
            return;
10520
        }
10521
10522
        $usergroup = new UserGroupModel();
10523
10524
        foreach ($classesNames as $className) {
10525
            if (empty($className)) {
10526
                continue;
10527
            }
10528
10529
            $usergroup->subscribe_sessions_to_usergroup(
10530
                $usergroup->getIdByName($className),
10531
                [$sessionId],
10532
                $deleteClassSessions
10533
            );
10534
        }
10535
    }
10536
10537
    /**
10538
     * @param array $listA
10539
     * @param array $listB
10540
     *
10541
     * @return int
10542
     */
10543
    private static function compareCatSessionInfo($listA, $listB)
10544
    {
10545
        if ($listA['sessionName'] == $listB['sessionName']) {
10546
            return 0;
10547
        } elseif ($listA['sessionName'] > $listB['sessionName']) {
10548
            return 1;
10549
        } else {
10550
            return -1;
10551
        }
10552
    }
10553
10554
    /**
10555
     * @param array $listA
10556
     * @param array $listB
10557
     *
10558
     * @return int
10559
     */
10560
    private static function compareBySessionName($listA, $listB)
10561
    {
10562
        if ('' == $listB['catSessionName']) {
10563
            return -1;
10564
        } elseif ('' == $listA['catSessionName']) {
10565
            return 1;
10566
        } elseif ($listA['catSessionName'] == $listB['catSessionName']) {
10567
            return 0;
10568
        } elseif ($listA['catSessionName'] > $listB['catSessionName']) {
10569
            return 1;
10570
        } else {
10571
            return -1;
10572
        }
10573
    }
10574
10575
    /**
10576
     * @param array $listA
10577
     * @param array $listB
10578
     *
10579
     * @return int
10580
     */
10581
    private static function compareByUserCourseCat($listA, $listB)
10582
    {
10583
        if ($listA['courseInUserCategoryTitle'] == $listB['courseInUserCategoryTitle']) {
10584
            return 0;
10585
        } elseif ($listA['courseInUserCategoryTitle'] > $listB['courseInUserCategoryTitle']) {
10586
            return 1;
10587
        } else {
10588
            return -1;
10589
        }
10590
    }
10591
10592
    /**
10593
     * @param array $listA
10594
     * @param array $listB
10595
     *
10596
     * @return int
10597
     */
10598
    private static function compareByCourse($listA, $listB)
10599
    {
10600
        if ($listA['title'] == $listB['title']) {
10601
            return 0;
10602
        } elseif ($listA['title'] > $listB['title']) {
10603
            return 1;
10604
        } else {
10605
            return -1;
10606
        }
10607
    }
10608
10609
    public static function getGeneralCoachesIdForSession(int $sessionId): array
10610
    {
10611
        return api_get_session_entity($sessionId)
10612
            ->getGeneralCoaches()
10613
            ->map(fn(User $user) => $user->getId())
10614
            ->getValues();
10615
    }
10616
10617
    public static function getGeneralCoachesNamesForSession(int $sessionId): array
10618
    {
10619
        return api_get_session_entity($sessionId)
10620
            ->getGeneralCoaches()
10621
            ->map(fn(User $user) => $user->getFullname())
10622
            ->getValues();
10623
    }
10624
10625
    public static function sessionHasSessionAdmin(int $sessionId, int $userId): bool
10626
    {
10627
        $adminIds = api_get_session_entity($sessionId)
10628
            ->getSessionAdmins()
10629
            ->map(fn(User $user) => $user->getId())
10630
            ->getValues();
10631
10632
        return in_array($userId, $adminIds);
10633
    }
10634
10635
    /**
10636
     * Retrieves all user IDs associated with a session including coaches and students.
10637
     *
10638
     * @param int $sessionId The session ID.
10639
     * @return array An array of user IDs.
10640
     */
10641
    public static function getAllUserIdsInSession(int $sessionId): array
10642
    {
10643
        $users = [];
10644
        $session = api_get_session_entity($sessionId);
10645
        if ($session) {
10646
            $courses = $session->getCourses();
10647
            if (!empty($courses)) {
10648
                foreach ($courses as $sessionRelCourse) {
10649
                    $course = $sessionRelCourse->getCourse();
10650
                    $coachSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::COURSE_COACH);
10651
                    foreach ($coachSubscriptions as $coachSubscription) {
10652
                        $users[]['user_id'] = $coachSubscription->getUser()->getId();
10653
                    }
10654
10655
                    $userCourseSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::STUDENT);
10656
                    foreach ($userCourseSubscriptions as $courseSubscription) {
10657
                        $users[]['user_id'] = $courseSubscription->getUser()->getId();
10658
                    }
10659
10660
                }
10661
            }
10662
10663
            $generalCoachesId = self::getGeneralCoachesIdForSession($sessionId);
10664
            if (!empty($generalCoachesId)) {
10665
                foreach ($generalCoachesId as $generalCoachId) {
10666
                    $users[]['user_id'] = $generalCoachId;
10667
                }
10668
            }
10669
        }
10670
10671
        return $users;
10672
    }
10673
10674
    /**
10675
     * Retrieves a list of parent sessions.
10676
     */
10677
    public static function getListOfParentSessions(): array
10678
    {
10679
        $sessions = [];
10680
        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
10681
        $sql = "SELECT id, title FROM $tbl_session ORDER BY title";
10682
        $result = Database::query($sql);
10683
10684
        while ($row = Database::fetch_array($result)) {
10685
            $sessions[$row['id']] = $row['title'];
10686
        }
10687
10688
        return $sessions;
10689
    }
10690
10691
10692
    /**
10693
     * Method to export sessions data as CSV
10694
     */
10695
    public static function exportSessionsAsCSV(array $selectedSessions): void
10696
    {
10697
        $csvData = [];
10698
        $headersGenerated = false;
10699
        $csvHeaders = [];
10700
10701
        foreach ($selectedSessions as $sessionId) {
10702
            $courses = SessionManager::get_course_list_by_session_id($sessionId);
10703
10704
            if (!empty($courses)) {
10705
                foreach ($courses as $course) {
10706
                    $courseCode = $course['course_code'];
10707
                    $courseId = $course['id'];
10708
                    $studentList = CourseManager::get_student_list_from_course_code(
10709
                        $courseCode,
10710
                        true,
10711
                        $sessionId
10712
                    );
10713
10714
                    $userIds = array_keys($studentList);
10715
10716
                    [$generatedHeaders, $csvContent] = self::generateSessionCourseReportData($sessionId, $courseId, $userIds);
10717
10718
                    if (!$headersGenerated) {
10719
                        $csvHeaders = $generatedHeaders;
10720
                        $headersGenerated = true;
10721
                    }
10722
10723
                    foreach ($csvContent as $row) {
10724
                        $csvData[] = $row;
10725
                    }
10726
                }
10727
            }
10728
        }
10729
10730
        if (!empty($csvData)) {
10731
            array_unshift($csvData, $csvHeaders);
10732
            $filename = 'export_session_courses_reports_complete_' . date('Y-m-d_H-i-s') . '.csv';
10733
            Export::arrayToCsvSimple($csvData, $filename);
10734
            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...
10735
        }
10736
    }
10737
10738
    /**
10739
     * Exports session data as a ZIP file with CSVs and sends it for download.
10740
     */
10741
    public static function exportSessionsAsZip(array $sessionList): void
10742
    {
10743
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH) . api_get_unique_id() . '.zip';
10744
        $tempDir = dirname($tempZipFile);
10745
10746
        if (!is_dir($tempDir) || !is_writable($tempDir)) {
10747
            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...
10748
        }
10749
10750
        $zip = new \ZipArchive();
10751
        if ($zip->open($tempZipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
10752
            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...
10753
        }
10754
10755
        foreach ($sessionList as $sessionItemId) {
10756
            $courses = SessionManager::get_course_list_by_session_id($sessionItemId);
10757
10758
            if (!empty($courses)) {
10759
                foreach ($courses as $course) {
10760
                    $courseCode = $course['course_code'];
10761
                    $courseId = $course['id'];
10762
                    $studentList = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionItemId);
10763
                    $userIds = array_keys($studentList);
10764
10765
                    [$csvHeaders, $csvContent] = self::generateSessionCourseReportData($sessionItemId, $courseId, $userIds);
10766
                    array_unshift($csvContent, $csvHeaders);
10767
10768
                    $sessionInfo = api_get_session_info($sessionItemId);
10769
                    $courseInfo = api_get_course_info_by_id($courseId);
10770
                    $csvFileName = $sessionInfo['name'] . '_' . $courseInfo['name'] . '.csv';
10771
10772
                    $csvFilePath = Export::arrayToCsvSimple($csvContent, $csvFileName, true);
10773
10774
                    if ($csvFilePath && file_exists($csvFilePath)) {
10775
                        $zip->addFile($csvFilePath, $csvFileName);
10776
                    }
10777
                }
10778
            }
10779
        }
10780
10781
        if (!$zip->close()) {
10782
            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...
10783
        }
10784
10785
        if (file_exists($tempZipFile)) {
10786
            DocumentManager::file_send_for_download($tempZipFile, true);
10787
            unlink($tempZipFile);
10788
        } else {
10789
            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...
10790
        }
10791
    }
10792
10793
    private static function generateSessionCourseReportData($sessionId, $courseId, $userIds): array
10794
    {
10795
        $em = Database::getManager();
10796
        $sessionRepository = $em->getRepository(Session::class);
10797
        $session = $sessionRepository->find($sessionId);
10798
10799
        if (!$session instanceof Session) {
10800
            throw new \InvalidArgumentException("Invalid session object for session ID $sessionId");
10801
        }
10802
10803
        $courseInfo = api_get_course_info_by_id($courseId);
10804
        $courseCode = $courseInfo['code'];
10805
10806
        $csvHeaders = [
10807
            get_lang('Session name'),
10808
            get_lang('Session access dates'),
10809
            get_lang('Session display dates'),
10810
            get_lang('Course name'),
10811
            get_lang('Official code'),
10812
            get_lang('First name'),
10813
            get_lang('Last name'),
10814
            get_lang('Login'),
10815
            get_lang('Time'),
10816
            get_lang('Course progress'),
10817
            get_lang('Exercise progress'),
10818
            get_lang('Exercise average'),
10819
            get_lang('Score'),
10820
            get_lang('Score') . ' - ' . get_lang('Best attempt'),
10821
            get_lang('Assignments'),
10822
            get_lang('Messages'),
10823
            get_lang('Classes'),
10824
            get_lang('Registration date'),
10825
            get_lang('First access to course'),
10826
            get_lang('Latest access in course'),
10827
        ];
10828
10829
        $csvData = TrackingCourseLog::getUserData(
10830
            null,
10831
            count($userIds),
10832
            null,
10833
            null,
10834
            [],
10835
            true,
10836
            true,
10837
            $courseCode,
10838
            $sessionId,
10839
            true,
10840
            $userIds
10841
        );
10842
10843
        $rawCsvContent = ChamiloSession::read('csv_content');
10844
10845
        if (empty($rawCsvContent)) {
10846
            throw new \RuntimeException("No CSV content found in session for course $courseCode and session $sessionId.");
10847
        }
10848
10849
        $csvContent = [];
10850
        foreach ($rawCsvContent as $row) {
10851
            $alignedRow = [
10852
                $row['session_name'] ?? '',
10853
                $row['session_startdate'] ?? '',
10854
                $row['session_enddate'] ?? '',
10855
                $row['course_name'] ?? '',
10856
                $row['official_code'] ?? '',
10857
                $row['firstname'] ?? '',
10858
                $row['lastname'] ?? '',
10859
                $row['username'] ?? '',
10860
                $row['time'] ?? '',
10861
                $row['average_progress'] ?? '',
10862
                $row['exercise_progress'] ?? '',
10863
                $row['exercise_average'] ?? '',
10864
                $row['student_score'] ?? '',
10865
                $row['student_score_best'] ?? '',
10866
                $row['count_assignments'] ?? '',
10867
                $row['count_messages'] ?? '',
10868
                $row['classes'] ?? '',
10869
                $row['registered_at'] ?? '',
10870
                $row['first_connection'] ?? '',
10871
                $row['last_connection'] ?? '',
10872
            ];
10873
            $csvContent[] = $alignedRow;
10874
        }
10875
10876
        return [$csvHeaders, $csvContent];
10877
    }
10878
}
10879