Passed
Push — master ( 2a0cb4...355306 )
by
unknown
08:53
created

SessionManager::formatSessionsAdminForGrid()   D

Complexity

Conditions 26

Size

Total Lines 117
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

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

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10443
        }
10444
    }
10445
10446
    /**
10447
     * Exports session data as a ZIP file with CSVs and sends it for download.
10448
     */
10449
    public static function exportSessionsAsZip(array $sessionList): void
10450
    {
10451
        $tempZipFile = api_get_path(SYS_ARCHIVE_PATH) . api_get_unique_id() . '.zip';
10452
        $tempDir = dirname($tempZipFile);
10453
10454
        if (!is_dir($tempDir) || !is_writable($tempDir)) {
10455
            exit("The directory for creating the ZIP file does not exist or lacks write permissions: $tempDir");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10456
        }
10457
10458
        $zip = new \ZipArchive();
10459
        if ($zip->open($tempZipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
10460
            exit("Unable to open the ZIP file for writing: $tempZipFile");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10461
        }
10462
10463
        foreach ($sessionList as $sessionItemId) {
10464
            $courses = SessionManager::get_course_list_by_session_id($sessionItemId);
10465
10466
            if (!empty($courses)) {
10467
                foreach ($courses as $course) {
10468
                    $courseCode = $course['course_code'];
10469
                    $courseId = $course['id'];
10470
                    $studentList = CourseManager::get_student_list_from_course_code($courseCode, true, $sessionItemId);
10471
                    $userIds = array_keys($studentList);
10472
10473
                    [$csvHeaders, $csvContent] = self::generateSessionCourseReportData($sessionItemId, $courseId, $userIds);
10474
                    array_unshift($csvContent, $csvHeaders);
10475
10476
                    $sessionInfo = api_get_session_info($sessionItemId);
10477
                    $courseInfo = api_get_course_info_by_id($courseId);
10478
                    $csvFileName = $sessionInfo['name'] . '_' . $courseInfo['name'] . '.csv';
10479
10480
                    $csvFilePath = Export::arrayToCsvSimple($csvContent, $csvFileName, true);
10481
10482
                    if ($csvFilePath && file_exists($csvFilePath)) {
10483
                        $zip->addFile($csvFilePath, $csvFileName);
10484
                    }
10485
                }
10486
            }
10487
        }
10488
10489
        if (!$zip->close()) {
10490
            exit("Could not close the ZIP file correctly.");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10491
        }
10492
10493
        if (file_exists($tempZipFile)) {
10494
            DocumentManager::file_send_for_download($tempZipFile, true);
10495
            unlink($tempZipFile);
10496
        } else {
10497
            exit("The ZIP file was not created correctly.");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
10498
        }
10499
    }
10500
10501
    private static function generateSessionCourseReportData($sessionId, $courseId, $userIds): array
10502
    {
10503
        $em = Database::getManager();
10504
        $sessionRepository = $em->getRepository(Session::class);
10505
        $session = $sessionRepository->find($sessionId);
10506
10507
        if (!$session instanceof Session) {
10508
            throw new \InvalidArgumentException("Invalid session object for session ID $sessionId");
10509
        }
10510
10511
        $courseInfo = api_get_course_info_by_id($courseId);
10512
        $courseCode = $courseInfo['code'];
10513
10514
        $csvHeaders = [
10515
            get_lang('Session name'),
10516
            get_lang('Session access dates'),
10517
            get_lang('Session display dates'),
10518
            get_lang('Course name'),
10519
            get_lang('Official code'),
10520
            get_lang('First name'),
10521
            get_lang('Last name'),
10522
            get_lang('Login'),
10523
            get_lang('Training time'),
10524
            get_lang('Course progress'),
10525
            get_lang('Exercise progress'),
10526
            get_lang('Exercise average'),
10527
            get_lang('Score'),
10528
            get_lang('Score') . ' - ' . get_lang('Best attempt'),
10529
            get_lang('Student_publication'),
10530
            get_lang('Messages'),
10531
            get_lang('Classes'),
10532
            get_lang('Registration date'),
10533
            get_lang('First login in course'),
10534
            get_lang('Latest login in course'),
10535
        ];
10536
10537
        $csvData = TrackingCourseLog::getUserData(
10538
            null,
10539
            count($userIds),
10540
            null,
10541
            null,
10542
            [],
10543
            true,
10544
            true,
10545
            $courseCode,
10546
            $sessionId,
10547
            true,
10548
            $userIds
10549
        );
10550
10551
        $rawCsvContent = ChamiloSession::read('csv_content');
10552
10553
        if (empty($rawCsvContent)) {
10554
            throw new \RuntimeException("No CSV content found in session for course $courseCode and session $sessionId.");
10555
        }
10556
10557
        $csvContent = [];
10558
        foreach ($rawCsvContent as $row) {
10559
            $alignedRow = [
10560
                $row['session_name'] ?? '',
10561
                $row['session_startdate'] ?? '',
10562
                $row['session_enddate'] ?? '',
10563
                $row['course_name'] ?? '',
10564
                $row['official_code'] ?? '',
10565
                $row['firstname'] ?? '',
10566
                $row['lastname'] ?? '',
10567
                $row['username'] ?? '',
10568
                $row['time'] ?? '',
10569
                $row['average_progress'] ?? '',
10570
                $row['exercise_progress'] ?? '',
10571
                $row['exercise_average'] ?? '',
10572
                $row['student_score'] ?? '',
10573
                $row['student_score_best'] ?? '',
10574
                $row['count_assignments'] ?? '',
10575
                $row['count_messages'] ?? '',
10576
                $row['classes'] ?? '',
10577
                $row['registered_at'] ?? '',
10578
                $row['first_connection'] ?? '',
10579
                $row['last_connection'] ?? '',
10580
            ];
10581
            $csvContent[] = $alignedRow;
10582
        }
10583
10584
        return [$csvHeaders, $csvContent];
10585
    }
10586
}
10587