Passed
Pull Request — master (#5828)
by
unknown
07:30
created

SessionManager::create_category_session()   D

Complexity

Conditions 19
Paths 128

Size

Total Lines 65
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 40
nc 128
nop 7
dl 0
loc 65
rs 4.2833
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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