Passed
Push — master ( 10e205...526a26 )
by
unknown
10:25 queued 14s
created

SessionManager::getTotalUserCoursesInSession()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 38
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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