Passed
Push — master ( cf2dda...901d34 )
by
unknown
16:10 queued 07:45
created

SessionManager::set_coach_to_course_session()   C

Complexity

Conditions 11

Size

Total Lines 96
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 57
c 1
b 0
f 0
nop 4
dl 0
loc 96
rs 6.7915

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