Passed
Pull Request — master (#6220)
by
unknown
08:42
created

SessionManager::importSessionDrhCSV()   C

Complexity

Conditions 12

Size

Total Lines 48
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 28
nop 3
dl 0
loc 48
rs 6.9666
c 0
b 0
f 0

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