SessionManager   F
last analyzed

Complexity

Total Complexity 1351

Size/Duplication

Total Lines 10854
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 5724
c 2
b 0
f 0
dl 0
loc 10854
rs 0.8
wmc 1351

159 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
B fetch() 0 54 7
A getCountUsersLangBySession() 0 38 5
A sessionNameExists() 0 8 1
F getSessionsForAdmin() 0 352 67
B get_count_admin() 0 110 8
A generateNextSessionName() 0 23 4
D get_user_data_access_tracking_overview() 0 141 20
C get_session_lp_progress() 0 107 13
C get_survey_overview() 0 98 13
F get_session_progress() 0 347 24
F create_session() 0 145 30
D formatSessionsAdminForGrid() 0 136 29
F edit_session() 0 188 28
C delete() 0 113 11
B getSessionsCoachedByUser() 0 47 10
F add_courses_to_session() 0 282 29
A getSessionChangeUserReasons() 0 6 1
C subscribeSessionsToDrh() 0 74 12
A addFlashSessionReadOnly() 0 5 3
A unsubscribe_user_from_session() 0 39 3
A getCoachesBySession() 0 18 3
B getSessionCategoryIdByName() 0 36 7
A getDefaultSessionTab() 0 10 3
B getSessionListTabs() 0 44 6
A getUsersByCourseSession() 0 35 6
D edit_category_session() 0 58 20
A getStatusList() 0 7 1
A getGeneralCoachesIdForSession() 0 6 1
A normalizeDateEnd() 0 7 2
A create_session_extra_field() 0 15 1
A compareArraysToMerge() 0 15 6
B getUsersByCourseAndSessionList() 0 40 8
A getUserStatusInSession() 0 11 1
A searchSession() 0 36 4
A getUserSession() 0 19 4
B exportSessionsAsZip() 0 49 11
B subscribe_users_to_session_course() 0 49 7
A get_course_list_by_session_id_like() 0 33 5
A addClassesByName() 0 17 4
A getSessionChangeUserReason() 0 5 1
A getAvoidedCoursesInSession() 0 17 3
C getShortSessionListAndExtraByCategory() 0 96 13
A protectSession() 0 4 2
B convertSessionDateToString() 0 42 7
A getSessionIdFromOriginalId() 0 13 2
B getCareersFromSession() 0 28 7
D create_category_session() 0 65 19
F getGridColumns() 0 472 20
F importXML() 0 283 29
A notifyBossOfInscription() 0 44 1
A getCourseCountBySessionId() 0 29 3
B generateSessionCourseReportData() 0 84 4
A allowOnlyMySessions() 0 10 4
A unsubscribe_course_from_session() 0 43 4
A cantEditSession() 0 19 6
B removeUsersFromCourseSession() 0 63 9
A sessionNameExistBesidesMySession() 0 20 3
A get_sessions_followed_by_drh() 0 24 1
C set_coach_to_course_session() 0 96 11
A getSessionPictureUrl() 0 6 1
C get_sessions_list() 0 91 17
B getCollapsableData() 0 33 7
C getTeacherTracking() 0 83 14
A subscribe_sessions_to_promotion() 0 16 3
A get_all_session_category() 0 15 2
B exportSessionsAsCSV() 0 40 7
A getDescriptionFromSessionId() 0 26 3
A getSessionCourseForUser() 0 23 5
F getAllUsersFromCoursesFromAllSessionFromStatus() 0 216 28
A getAllCoursesFromAllSessionFromDrh() 0 14 4
B move() 0 62 9
A getDayLeftInSession() 0 27 3
B get_users_by_session() 0 60 9
A unSubscribeUserFromCourseSession() 0 30 2
A getSessionVisibility() 0 12 4
A getPath() 0 17 4
A get_all_sessions_by_promotion() 0 8 1
A getCoursesListByCourseCoach() 0 8 1
A isValidId() 0 15 3
A getTotalUserCoursesInSession() 0 38 4
A getSessionsFollowedForGroupAdmin() 0 45 5
A getCoachesByCourseSessionToString() 0 19 5
A getGeneralCoachesNamesForSession() 0 6 1
A get_session_by_name() 0 17 3
A moveDown() 0 3 1
A sessionHasCourse() 0 25 3
B copyStudentsFromSession() 0 63 8
A get_user_status_in_course_session() 0 21 2
C getSessionListAndExtraByCategoryId() 0 127 15
F getSessionsFollowedByUser() 0 182 33
A getStatusLabel() 0 9 2
A insertUsersInCourses() 0 12 3
A getCountUserTracking() 0 51 5
A parseSessionDates() 0 26 1
A getCoursesForCourseSessionCoach() 0 27 4
C importSessionDrhCSV() 0 48 12
A clear_session_ref_promotion() 0 12 2
B updateCoaches() 0 28 7
B convert_dates_to_local() 0 41 11
A getCountUsersInCourseSession() 0 26 1
A getCourseToolToBeManaged() 0 5 1
A deleteAsset() 0 11 2
A redirectToSession() 0 18 5
A compareBySessionName() 0 12 5
A allowManageAllSessions() 0 7 3
A isUserSubscribedAsStudent() 0 21 3
B get_course_list_by_session_id() 0 55 8
A get_session_category() 0 13 2
A getDrhUsersInSession() 0 3 1
A moveUp() 0 3 1
A get_session_by_course() 0 24 2
A getCoursesInSession() 0 23 3
F get_sessions_admin_complete() 0 252 35
A compareByCourse() 0 8 3
A delete_session_category() 0 38 4
A getListOfParentSessions() 0 12 2
A durationPerUserIsEnabled() 0 3 1
B checkSubscribeDrhToSessionList() 0 41 11
B getAllCoursesFollowedByUser() 0 71 9
A getTotalUserTimeInPlatform() 0 27 5
F subscribeUsersToSession() 0 238 29
A get_sessions_by_user() 0 24 5
B getHotSessions() 0 53 6
F setForm() 0 398 25
B getAllUserIdsInSession() 0 31 8
A getAdminPath() 0 9 2
B copyCoachesFromSessionToCourse() 0 60 10
A getCoursesForMainSessionCoach() 0 22 5
B allowed() 0 30 9
A compareCatSessionInfo() 0 8 3
A editUserSessionDuration() 0 16 3
A set_session_status() 0 5 1
A isSessionFollowedByDrh() 0 31 2
A getCoachesByCourseSession() 0 21 3
A installCourse() 0 9 3
A updateSessionPicture() 0 25 3
A getSessionFollowedByDrh() 0 40 3
F importCSV() 0 1001 183
B getNamedSessionCourseForCoach() 0 59 7
A update_session_extra_field_value() 0 10 1
A subscribeDrhToSessionList() 0 17 4
A count_sessions() 0 14 2
F copy() 0 225 37
C get_count_admin_complete() 0 105 10
A sessionHasSessionAdmin() 0 8 1
A searchCourseInSessionsFromUser() 0 14 3
A unInstallCourse() 0 9 3
B insertUsersInCourse() 0 56 7
B getFilteredExtraFields() 0 58 10
A protect_teacher_session_edit() 0 6 3
A compareByUserCourseCat() 0 8 3
A isUserSubscribedAsHRM() 0 22 3
A get_sessions_by_general_coach() 0 31 5
A relation_session_course_exist() 0 15 2
A getAllCoursesFromAllSessions() 0 14 4
A orderCourseIsEnabled() 0 8 2
B getCareerDiagramPerSessionList() 0 43 8
A allowToManageSessions() 0 11 4

How to fix   Complexity   

Complex Class

Complex classes like SessionManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SessionManager, and based on these observations, apply Extract Interface, too.

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