diff --git a/public/main/inc/lib/database.lib.php b/public/main/inc/lib/database.lib.php index f9517cf9749..fe63749d628 100644 --- a/public/main/inc/lib/database.lib.php +++ b/public/main/inc/lib/database.lib.php @@ -312,7 +312,7 @@ public static function store_result(\Doctrine\DBAL\Result $result, $option = 'BO * @throws \Doctrine\DBAL\Exception * @throws Exception */ - public static function insert(string $table_name, array $attributes, bool $show_query = false): bool|int + public static function insert(string $table_name, array $attributes, bool $show_query = false, array $options = []): bool|int { if (empty($attributes) || empty($table_name)) { return false; @@ -321,8 +321,9 @@ public static function insert(string $table_name, array $attributes, bool $show_ $params = array_keys($attributes); if (!empty($params)) { - $sql = 'INSERT INTO '.$table_name.' ('.implode(',', $params).') - VALUES (:'.implode(', :', $params).')'; + $prefix = (!empty($options['ignore'])) ? 'INSERT IGNORE INTO' : 'INSERT INTO'; + $sql = $prefix.' '.$table_name.' ('.implode(',', $params).') + VALUES (:'.implode(', :', $params).')'; if ($show_query) { var_dump($sql); diff --git a/public/main/inc/lib/sessionmanager.lib.php b/public/main/inc/lib/sessionmanager.lib.php index de650421889..e8498010772 100644 --- a/public/main/inc/lib/sessionmanager.lib.php +++ b/public/main/inc/lib/sessionmanager.lib.php @@ -12,6 +12,7 @@ use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser; use Chamilo\CoreBundle\Entity\SessionRelUser; use Chamilo\CoreBundle\Entity\User; +use Chamilo\CoreBundle\Entity\UserAuthSource; use Chamilo\CoreBundle\Framework\Container; use Chamilo\CourseBundle\Entity\CSurvey; use ExtraField as ExtraFieldModel; @@ -5030,49 +5031,30 @@ public static function get_sessions_by_user( } /** - * @param string $file - * @param bool $updateSession true: if the session exists it will be updated. - * false: if session exists a new session will be created adding a counter session1, session2, etc - * @param int $defaultUserId - * @param Logger $logger - * @param array $extraFields convert a file row to an extra field. Example in CSV file there's a SessionID - * then it will converted to extra_external_session_id if you set: array('SessionId' => 'extra_external_session_id') - * @param string $extraFieldId - * @param int $daysCoachAccessBeforeBeginning - * @param int $daysCoachAccessAfterBeginning - * @param int $sessionVisibility - * @param array $fieldsToAvoidUpdate - * @param bool $deleteUsersNotInList - * @param bool $updateCourseCoaches - * @param bool $sessionWithCoursesModifier - * @param bool $addOriginalCourseTeachersAsCourseSessionCoaches - * @param bool $removeAllTeachersFromCourse - * @param int $showDescription - * @param array $teacherBackupList - * @param array $groupBackup + * Imports sessions from a CSV file, creating or updating sessions with related users and courses. * - * @return array + * @return array Contains the import result with errors, counters, and session IDs. */ public static function importCSV( - $file, - $updateSession, - $defaultUserId = null, - $logger = null, - $extraFields = [], - $extraFieldId = null, - $daysCoachAccessBeforeBeginning = null, - $daysCoachAccessAfterBeginning = null, - $sessionVisibility = 1, - $fieldsToAvoidUpdate = [], - $deleteUsersNotInList = false, - $updateCourseCoaches = false, - $sessionWithCoursesModifier = false, - $addOriginalCourseTeachersAsCourseSessionCoaches = true, - $removeAllTeachersFromCourse = true, - $showDescription = null, - &$teacherBackupList = [], - &$groupBackup = [] - ) { + string $file, + bool $updateSession, + ?int $defaultUserId = null, + ?Logger $logger = null, + array $extraFields = [], + ?string $extraFieldId = null, + ?int $daysCoachAccessBeforeBeginning = null, + ?int $daysCoachAccessAfterBeginning = null, + int $sessionVisibility = 1, + array $fieldsToAvoidUpdate = [], + bool $deleteUsersNotInList = false, + bool $updateCourseCoaches = false, + bool $sessionWithCoursesModifier = false, + bool $addOriginalCourseTeachersAsCourseSessionCoaches = true, + bool $removeAllTeachersFromCourse = true, + ?int $showDescription = null, + array &$teacherBackupList = [], + array &$groupBackup = [] + ): array { $content = file($file); $error_message = null; $session_counter = 0; @@ -5127,9 +5109,9 @@ public static function importCSV( $user_counter = 0; $course_counter = 0; - if (isset($extraFields) && !empty($extraFields)) { + if (!empty($extraFields)) { foreach ($extraFields as $original => $to) { - $enreg[$to] = isset($enreg[$original]) ? $enreg[$original] : null; + $enreg[$to] = $enreg[$original] ?? null; } } @@ -5163,25 +5145,22 @@ public static function importCSV( continue; } - $displayAccessStartDate = isset($enreg['DisplayStartDate']) ? $enreg['DisplayStartDate'] : $enreg['DateStart']; - $displayAccessEndDate = isset($enreg['DisplayEndDate']) ? $enreg['DisplayEndDate'] : $enreg['DateEnd']; - $coachAccessStartDate = isset($enreg['CoachStartDate']) ? $enreg['CoachStartDate'] : $enreg['DateStart']; - $coachAccessEndDate = isset($enreg['CoachEndDate']) ? $enreg['CoachEndDate'] : $enreg['DateEnd']; + $displayAccessStartDate = $enreg['DisplayStartDate'] ?? $enreg['DateStart']; + $displayAccessEndDate = $enreg['DisplayEndDate'] ?? $enreg['DateEnd']; + $coachAccessStartDate = $enreg['CoachStartDate'] ?? $enreg['DateStart']; + $coachAccessEndDate = $enreg['CoachEndDate'] ?? $enreg['DateEnd']; // We assume the dates are already in UTC - $dateStart = explode('/', $enreg['DateStart']); - $dateEnd = explode('/', $enreg['DateEnd']); - $dateStart = $dateStart[0].'-'.$dateStart[1].'-'.$dateStart[2].' 00:00:00'; - $dateEnd = $dateEnd[0].'-'.$dateEnd[1].'-'.$dateEnd[2].' 23:59:59'; - $displayAccessStartDate = explode('/', $displayAccessStartDate); - $displayAccessStartDate = implode('-', $displayAccessStartDate).' 00:00:00'; - $displayAccessEndDate = explode('/', $displayAccessEndDate); - $displayAccessEndDate = implode('-', $displayAccessEndDate).' 23:59:59'; - $coachAccessStartDate = explode('/', $coachAccessStartDate); - $coachAccessStartDate = implode('-', $coachAccessStartDate).' 00:00:00'; - $coachAccessEndDate = explode('/', $coachAccessEndDate); - $coachAccessEndDate = implode('-', $coachAccessEndDate).' 23:59:59'; - $session_category_id = isset($enreg['SessionCategory']) ? $enreg['SessionCategory'] : null; - $sessionDescription = isset($enreg['SessionDescription']) ? $enreg['SessionDescription'] : null; + + $dateStart = date('Y-m-d H:i:s', strtotime(trim($enreg['DateStart']))); + $displayAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($displayAccessStartDate))); + $coachAccessStartDate = date('Y-m-d H:i:s', strtotime(trim($coachAccessStartDate))); + + $dateEnd = self::normalizeDateEnd($enreg['DateEnd']); + $displayAccessEndDate = self::normalizeDateEnd($displayAccessEndDate); + $coachAccessEndDate = self::normalizeDateEnd($coachAccessEndDate); + + $session_category_id = $enreg['SessionCategory'] ?? null; + $sessionDescription = $enreg['SessionDescription'] ?? null; $classes = isset($enreg['Classes']) ? explode('|', $enreg['Classes']) : []; $extraParams = []; if (!is_null($showDescription)) { @@ -6067,6 +6046,307 @@ public static function importCSV( ]; } + /** + * Imports sessions from an XML file and returns the result of the operation. + */ + public static function importXML( + string $file, + bool $updateSession = false, + int $defaultUserId = null, + bool $sendMail = false, + int $sessionVisibility = SESSION_VISIBLE, + array &$insertedInCourse = [], + ?string &$errorMessage = '' + ): array { + $defaultUserId = $defaultUserId ?? api_get_user_id(); + $tblSession = Database::get_main_table(TABLE_MAIN_SESSION); + $tblSessionUser = Database::get_main_table(TABLE_MAIN_SESSION_USER); + $tblSessionCourse = Database::get_main_table(TABLE_MAIN_SESSION_COURSE); + $tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); + + $sessionCounter = 0; + $sessionList = []; + + $content = file_get_contents($file); + $content = api_utf8_encode_xml($content); + $root = @simplexml_load_string($content); + + if (!is_object($root)) { + $errorMessage .= get_lang('XML document is not valid'); + return []; + } + + // === USERS === + if (isset($root->Users->User)) { + foreach ($root->Users->User as $nodeUser) { + $username = trim(api_utf8_decode($nodeUser->Username)); + $password = api_utf8_decode($nodeUser->Password); + $firstname = api_utf8_decode($nodeUser->Firstname); + $lastname = api_utf8_decode($nodeUser->Lastname); + $email = trim(api_utf8_decode($nodeUser->Email)); + $officialCode = trim(api_utf8_decode($nodeUser->OfficialCode)); + $phone = trim(api_utf8_decode($nodeUser->Phone)); + $statusStr = strtolower(trim(api_utf8_decode($nodeUser->Status))); + $status = $statusStr === 'teacher' ? 1 : 5; + + if (UserManager::is_username_available($username)) { + if (empty($password)) { + $password = api_generate_password(); + } + UserManager::create_user( + $firstname, + $lastname, + $status, + $email, + $username, + $password, + $officialCode, + null, + $phone, + null, + [UserAuthSource::PLATFORM], + null, + 1, + 0, + null, + null, + $sendMail + ); + } else { + $userId = UserManager::get_user_id_from_username($username); + if ($userId) { + UserManager::update_user( + $userId, + $firstname, + $lastname, + $username, + $password, + [], + $email, + $status, + $officialCode, + $phone, + null, + null, + 1, + null, + 0 + ); + } + } + } + } + + // === COURSES === + if (isset($root->Courses->Course)) { + foreach ($root->Courses->Course as $nodeCourse) { + $courseCode = api_utf8_decode($nodeCourse->CourseCode); + $courseTitle = api_utf8_decode($nodeCourse->CourseTitle ?: $courseCode); + $courseLang = api_utf8_decode($nodeCourse->CourseLanguage); + $teacherUsername = trim(api_utf8_decode($nodeCourse->CourseTeacher)); + + $teacherId = UserManager::get_user_id_from_username($teacherUsername) ?: $defaultUserId; + + if (!CourseManager::course_exists($courseCode)) { + CourseManager::create_course([ + 'wanted_code' => $courseCode, + 'title' => $courseTitle, + 'course_language' => $courseLang, + 'user_id' => $defaultUserId, + 'teachers' => $teacherId, + ]); + } + } + } + + // === SESSIONS === + if (isset($root->Session)) { + foreach ($root->Session as $nodeSession) { + $sessionName = trim(api_utf8_decode($nodeSession->SessionName)); + $coachUsername = trim(api_utf8_decode($nodeSession->Coach)); + $coachId = UserManager::get_user_id_from_username($coachUsername) ?: $defaultUserId; + $dateStart = api_utf8_decode($nodeSession->DateStart); + $dateEnd = api_utf8_decode($nodeSession->DateEnd); + $sessionCategoryId = (int) trim(api_utf8_decode($nodeSession->SessionCategory)); + $categoryExists = false; + if (!empty($sessionCategoryId)) { + $result = Database::select( + 'id', + Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY), + ['where' => ['id = ?' => $sessionCategoryId]], + 'first' + ); + + $categoryExists = !empty($result); + } + if (!$categoryExists) { + $sessionCategoryId = null; + } + $visibilityStr = strtolower(api_utf8_decode($nodeSession->VisibilityAfterExpiration)); + $visibility = match ($visibilityStr) { + 'read_only' => SESSION_VISIBLE_READ_ONLY, + 'not_accessible' => SESSION_INVISIBLE, + default => $sessionVisibility, + }; + + // Normalize dates + $dateStart = date('Y-m-d H:i:s', strtotime($dateStart)); + $dateEnd = date('Y-m-d H:i:s', strtotime($dateEnd)); + + $sessionId = null; + $mySession = SessionManager::get_session_by_name($sessionName); + + if ($updateSession && $mySession) { + $sessionId = $mySession['id']; + Database::update($tblSession, [ + 'access_start_date' => $dateStart, + 'access_end_date' => $dateEnd, + 'visibility' => $visibility, + 'session_category_id' => $sessionCategoryId, + ], ['id = ?' => $sessionId]); + + Database::query("DELETE FROM $tblSessionUser WHERE session_id = $sessionId"); + Database::query("DELETE FROM $tblSessionCourse WHERE session_id = $sessionId"); + Database::query("DELETE FROM $tblSessionCourseUser WHERE session_id = $sessionId"); + } else { + $sessionId = Database::insert($tblSession, [ + 'title' => $sessionName, + 'access_start_date' => $dateStart, + 'access_end_date' => $dateEnd, + 'visibility' => $visibility, + 'nbr_users' => 0, + 'nbr_courses' => 0, + 'nbr_classes' => 0, + 'status' => 0, + 'duration' => 0, + 'session_category_id' => $sessionCategoryId, + ]); + } + + if ($sessionId) { + Database::insert($tblSessionUser, [ + 'user_id' => $coachId, + 'session_id' => $sessionId, + 'registered_at' => api_get_utc_datetime(), + 'relation_type' => Session::GENERAL_COACH, + 'duration' => 0, + ], false, ['ignore' => true]); + + Database::insert($tblSessionUser, [ + 'user_id' => $defaultUserId, + 'session_id' => $sessionId, + 'registered_at' => api_get_utc_datetime(), + 'relation_type' => Session::SESSION_ADMIN, + 'duration' => 0, + ], false, ['ignore' => true]); + $sessionCounter++; + $sessionList[] = $sessionId; + } + + // Add Users to session + foreach ($nodeSession->User as $nodeUser) { + $username = UserManager::purify_username(api_utf8_decode($nodeUser)); + $userId = UserManager::get_user_id_from_username($username); + if ($userId) { + Database::insert($tblSessionUser, [ + 'user_id' => $userId, + 'session_id' => $sessionId, + 'relation_type' => Session::STUDENT, + 'duration' => 0, + 'registered_at' => api_get_utc_datetime(), + ], false, ['ignore' => true]); + } + } + + // Add Courses to session + foreach ($nodeSession->Course as $nodeCourse) { + $courseCode = api_utf8_decode($nodeCourse->CourseCode); + $courseInfo = api_get_course_info($courseCode); + if ($courseInfo) { + $courseId = $courseInfo['real_id']; + Database::insert($tblSessionCourse, [ + 'c_id' => $courseId, + 'session_id' => $sessionId, + 'nbr_users' => 0, + 'position' => 0, + ]); + $courseCoachUsernames = explode(',', $nodeCourse->Coach); + foreach ($courseCoachUsernames as $coachUname) { + $coachId = UserManager::get_user_id_from_username(trim($coachUname)); + if ($coachId) { + Database::insert($tblSessionCourseUser, [ + 'user_id' => $coachId, + 'c_id' => $courseId, + 'session_id' => $sessionId, + 'status' => Session::COURSE_COACH, + 'visibility' => 1, + 'legal_agreement' => 0, + 'progress' => 0, + ]); + } + } + + // Users in the course + $userCounter = 0; + foreach ($nodeCourse->User as $userNode) { + $username = UserManager::purify_username(api_utf8_decode($userNode)); + $userId = UserManager::get_user_id_from_username($username); + if ($userId) { + Database::insert($tblSessionUser, [ + 'user_id' => $userId, + 'session_id' => $sessionId, + 'registered_at' => api_get_utc_datetime(), + 'duration' => 0, + 'relation_type' => Session::STUDENT + ], false, ['ignore' => true]); + Database::insert($tblSessionCourseUser, [ + 'user_id' => $userId, + 'c_id' => $courseId, + 'session_id' => $sessionId, + 'status' => Session::STUDENT, + 'visibility' => 1, + 'legal_agreement' => 0, + 'progress' => 0, + ]); + $userCounter++; + } + } + + Database::update( + $tblSessionCourse, + ['nbr_users' => $userCounter], + ['c_id = ? AND session_id = ?' => [$courseId, $sessionId]], + ); + } + } + + Database::update($tblSession, [ + 'nbr_users' => count($nodeSession->User), + 'nbr_courses' => count($nodeSession->Course), + ], ['id = ?' => $sessionId]); + + UrlManager::add_session_to_url($sessionId, api_get_current_access_url_id()); + } + } + + return [ + 'session_counter' => $sessionCounter, + 'session_list' => $sessionList, + ]; + } + + /** + * Normalizes the end date format to include time if missing. + */ + private static function normalizeDateEnd(string $date): string + { + $dt = new \DateTime(trim($date)); + if ($dt->format('H:i:s') === '00:00:00') { + $dt->setTime(23, 59, 59); + } + return $dt->format('Y-m-d H:i:s'); + } + /** * @param int $sessionId * @param int $courseId diff --git a/public/main/session/session_import.php b/public/main/session/session_import.php index 4667a5a84ff..6dbf9515c34 100644 --- a/public/main/session/session_import.php +++ b/public/main/session/session_import.php @@ -2,9 +2,7 @@ /* For licensing terms, see /license.txt */ -use Chamilo\CoreBundle\Entity\Session; use Chamilo\CoreBundle\Component\Utils\ActionIcon; -use Chamilo\CoreBundle\Entity\UserAuthSource; $cidReset = true; @@ -23,7 +21,6 @@ $toolName = get_lang('Import sessions list'); -//$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('Administration')); $interbreadcrumb[] = ['url' => 'session_list.php', 'name' => get_lang('Session list')]; set_time_limit(0); @@ -37,500 +34,79 @@ $userInfo = api_get_user_info(); if (isset($_POST['formSent']) && $_POST['formSent']) { - if (isset($_FILES['import_file']['tmp_name']) && - !empty($_FILES['import_file']['tmp_name']) - ) { - $formSent = $_POST['formSent']; - $fileType = isset($_POST['file_type']) ? $_POST['file_type'] : null; - $sendMail = isset($_POST['sendMail']) && $_POST['sendMail'] ? 1 : 0; - $isOverwrite = isset($_POST['overwrite']) && $_POST['overwrite'] ? true : false; - $deleteUsersNotInList = isset($_POST['delete_users_not_in_list']) ? true : false; - $sessions = []; - $sessionCounter = 0; - - if ('xml' === $fileType) { - // XML - // SimpleXML for PHP5 deals with various encodings, but how many they are, what are version issues, - // do we need to waste time with configuration options? - // For avoiding complications we go some sort of "PHP4 way" - we convert the input xml-file into UTF-8 - // before passing it to the parser. - // Instead of: - // $root = @simplexml_load_file($_FILES['import_file']['tmp_name']); - // we may use the following construct: - // $root = @simplexml_load_string(api_utf8_encode_xml(file_get_contents($_FILES['import_file']['tmp_name']))); - // To ease debugging let us use: - $content = file_get_contents($_FILES['import_file']['tmp_name']); - - $content = api_utf8_encode_xml($content); - $root = @simplexml_load_string($content); - unset($content); - - if (is_object($root)) { - if (count($root->Users->User) > 0) { - // Creating/updating users from base node. - foreach ($root->Users->User as $nodeUser) { - $username = $usernameOld = trim(api_utf8_decode($nodeUser->Username)); - if (UserManager::is_username_available($username)) { - $password = api_utf8_decode($nodeUser->Password); - if (empty($password)) { - $password = api_generate_password(); - } - switch ($nodeUser->Status) { - case 'student': - $status = 5; - break; - case 'teacher': - $status = 1; - break; - default: - $status = 5; - $errorMessage .= get_lang('Learner status has been given to').' : '.$username.'
'; - } - - $result = UserManager::create_user( - api_utf8_decode($nodeUser->Firstname), - api_utf8_decode($nodeUser->Lastname), - $status, - api_utf8_decode($nodeUser->Email), - $username, - $password, - api_utf8_decode($nodeUser->OfficialCode), - null, - api_utf8_decode($nodeUser->Phone), - null, - [UserAuthSource::PLATFORM], - null, - 1, - 0, - null, - null, - $sendMail - ); - } else { - $lastname = trim(api_utf8_decode($nodeUser->Lastname)); - $firstname = trim(api_utf8_decode($nodeUser->Firstname)); - $password = api_utf8_decode($nodeUser->Password); - $email = trim(api_utf8_decode($nodeUser->Email)); - $officialCode = trim(api_utf8_decode($nodeUser->OfficialCode)); - $phone = trim(api_utf8_decode($nodeUser->Phone)); - $status = trim(api_utf8_decode($nodeUser->Status)); - switch ($status) { - case 'student': - $status = 5; - break; - case 'teacher': - $status = 1; - break; - default: - $status = 5; - $errorMessage .= get_lang('Learner status has been given to').' : '.$username.'
'; - } - - $userId = UserManager::get_user_id_from_username($username); - - if (!empty($userId)) { - UserManager::update_user( - $userId, - $firstname, - $lastname, - $username, - $password, - [], - $email, - $status, - $officialCode, - $phone, - null, //$picture_uri, - null, //$expiration_date, - null, //$active, - null, //$creator_id = null, - 0, - null, //$extra = null, - null, //$language = 'english', - null, //$encrypt_method = '', - false, - 0 //$reset_password = 0 - ); - } - } - } - } + if (!empty($_FILES['import_file']['tmp_name'])) { + $fileType = $_POST['file_type'] ?? null; - // Creating courses from base node. - if (count($root->Courses->Course) > 0) { - foreach ($root->Courses->Course as $courseNode) { - $params = []; - if (empty($courseNode->CourseTitle)) { - $params['title'] = api_utf8_decode($courseNode->CourseCode); - } else { - $params['title'] = api_utf8_decode($courseNode->CourseTitle); - } - $params['wanted_code'] = api_utf8_decode($courseNode->CourseCode); - $params['tutor_name'] = null; - $params['course_category'] = null; - $params['course_language'] = api_utf8_decode($courseNode->CourseLanguage); - $params['user_id'] = api_get_user_id(); - - // Looking up for the teacher. - $username = trim(api_utf8_decode($courseNode->CourseTeacher)); - $rs = Database::select( - ['id', 'lastname', 'firstname'], - $tblUser, - ['where' => ['username = ?' => $username]], - 'first', - 'NUM' - ); - [$userId, $lastname, $firstname] = $rs; - if ($userId > 0) { - $params['teachers'] = $userId; - } else { - $params['teachers'] = api_get_user_id(); - } - CourseManager::create_course($params); - } - } + $allowedExtensions = [ + 'csv' => ['csv'], + 'xml' => ['xml'], + ]; - // Creating sessions from base node. - if (count($root->Session) > 0) { - foreach ($root->Session as $nodeSession) { - $courseCounter = 0; - $userCounter = 0; - - $sessionName = trim(api_utf8_decode($nodeSession->SessionName)); - $coach = UserManager::purify_username( - api_utf8_decode($nodeSession->Coach), - $purificationOptionForUsernames - ); - - if (!empty($coach)) { - $coachId = UserManager::get_user_id_from_username($coach); - if (false === $coachId) { - $errorMessage .= get_lang('This user doesn\'t exist').' : '.$coach.'
'; - // Forcing the coach id if user does not exist. - $coachId = api_get_user_id(); - } - } else { - // Forcing the coach id. - $coachId = api_get_user_id(); - } - - // Just in case - encoding conversion. - $dStart = trim(api_utf8_decode($nodeSession->DateStart)); - - if (!empty($dStart)) { - [$yearStart, $monthStart, $dayStart] = explode('/', $dStart); - if (empty($yearStart) || empty($monthStart) || empty($dayStart)) { - $errorMessage .= get_lang('Wrong date format (yyyy-mm-dd)').' : '.$dStart.'
'; - break; - } else { - $timeStart = mktime(0, 0, 0, (int) $monthStart, (int) $dayStart, (int) $yearStart); - } - - $dateEnd = trim(api_utf8_decode($nodeSession->DateEnd)); - if (!empty($dStart)) { - [$yearEnd, $monthEnd, $dayEnd] = explode('/', $dateEnd); - if (empty($yearEnd) || empty($monthEnd) || empty($dayEnd)) { - $errorMessage .= get_lang('Error').' : '.$dateEnd.'
'; - break; - } else { - $timeEnd = mktime(0, 0, 0, $monthEnd, $dayEnd, $yearEnd); - } - } - if ($timeEnd - $timeStart < 0) { - $errorMessage .= get_lang('The first date should be before the end date').' : '.$dateEnd.'
'; - } - } - - // Default visibility - $visibilityAfterExpirationPerSession = 1; - if (isset($nodeSession->VisibilityAfterExpiration)) { - $visibility = trim(api_utf8_decode($nodeSession->VisibilityAfterExpiration)); - switch ($visibility) { - case 'read_only': - $visibilityAfterExpirationPerSession = SESSION_VISIBLE_READ_ONLY; - break; - case 'accessible': - $visibilityAfterExpirationPerSession = SESSION_VISIBLE; - break; - case 'not_accessible': - $visibilityAfterExpirationPerSession = SESSION_INVISIBLE; - break; - } - } - $sessionCategoryId = trim(api_utf8_decode($nodeSession->SessionCategory)); - - if (!$isOverwrite) { - // Always create a session. - $uniqueName = false; // This MUST be initializead. - $i = 0; - $suffix = ''; - // Change session name, verify that session doesn't exist. - while (!$uniqueName) { - if ($i > 1) { - $suffix = ' - '.$i; - } - $sql = 'SELECT id FROM '.$tblSession.' - WHERE title = "'.Database::escape_string($sessionName.$suffix).'"'; - $rs = Database::query($sql); - if (Database::result($rs, 0, 0)) { - $i++; - } else { - $uniqueName = true; - $sessionName .= $suffix; - } - } - - // Creating the session. - $sqlSession = "INSERT IGNORE INTO $tblSession SET - title = '".Database::escape_string($sessionName)."', - access_start_date = '$dStart', - access_end_date = '$dateEnd', - visibility = '$visibilityAfterExpirationPerSession', - nbr_users = 0, - nbr_courses = 0, - nbr_classes = 0, - status = 0, - duration = 0, - session_category_id = '$sessionCategoryId'"; - $rsSession = Database::query($sqlSession); - $sessionId = Database::insert_id(); - Database::insert( - $tblSessionUser, - [ - 'relation_type' => Session::GENERAL_COACH, - 'duration' => 0, - 'registered_at' => api_get_utc_datetime(), - 'user_id' => $coachId, - 'session_id' => $sessionId, - ] - ); - Database::insert( - $tblSessionUser, - [ - 'relation_type' => Session::SESSION_ADMIN, - 'duration' => 0, - 'registered_at' => api_get_utc_datetime(), - 'user_id' => (int) $userInfo['user_id'], - 'session_id' => $sessionId, - ] - ); - $sessionCounter++; - } else { - // Update the session if it is needed. - $mySessionResult = SessionManager::get_session_by_name($sessionName); - if (false === $mySessionResult) { - // Creating the session. - $sqlSession = "INSERT IGNORE INTO $tblSession SET - title = '".Database::escape_string($sessionName)."', - access_start_date = '$dStart', - access_end_date = '$dateEnd', - visibility = '$visibilityAfterExpirationPerSession', - nbr_users = 0, - nbr_courses = 0, - nbr_classes = 0, - status = 0, - duration = 0, - session_category_id = '$sessionCategoryId'"; - $rsSession = Database::query($sqlSession); - $sessionId = Database::insert_id(); - Database::insert( - $tblSessionUser, - [ - 'relation_type' => Session::GENERAL_COACH, - 'duration' => 0, - 'registered_at' => api_get_utc_datetime(), - 'user_id' => $coachId, - 'session_id' => $sessionId, - ] - ); - Database::insert( - $tblSessionUser, - [ - 'relation_type' => Session::SESSION_ADMIN, - 'duration' => 0, - 'registered_at' => api_get_utc_datetime(), - 'user_id' => (int) $userInfo['user_id'], - 'session_id' => $sessionId, - ] - ); - $sessionCounter++; - } else { - // if the session already exists - update it. - $sqlSession = "UPDATE $tblSession SET - access_start_date = '$dStart', - access_end_date = '$dateEnd', - visibility = '$visibilityAfterExpirationPerSession', - session_category_id = '$sessionCategoryId' - WHERE title = '$sessionName'"; - $rsSession = Database::query($sqlSession); - $sessionId = Database::query("SELECT id FROM $tblSession WHERE title='$sessionName'"); - [$sessionId] = Database::fetch_array($sessionId); - Database::query("DELETE FROM $tblSessionUser WHERE session_id ='$sessionId'"); - Database::query("DELETE FROM $tblSessionCourse WHERE session_id='$sessionId'"); - Database::query("DELETE FROM $tblSessionCourseUser WHERE session_id='$sessionId'"); - Database::insert( - $tblSessionUser, - [ - 'relation_type' => Session::GENERAL_COACH, - 'duration' => 0, - 'registered_at' => api_get_utc_datetime(), - 'user_id' => $coachId, - 'session_id' => $sessionId, - ] - ); - } - } - - // Associate the session with access_url. - if (api_is_multiple_url_enabled()) { - $accessUrlId = api_get_current_access_url_id(); - UrlManager::add_session_to_url($sessionId, $accessUrlId); - } else { - // We fill by default the access_url_rel_session table. - UrlManager::add_session_to_url($sessionId, 1); - } - - // Adding users to the new session. - foreach ($nodeSession->User as $nodeUser) { - $username = UserManager::purify_username(api_utf8_decode($nodeUser), $purificationOptionForUsernames); - $userId = UserManager::get_user_id_from_username($username); - if (false !== $userId) { - $sql = "INSERT IGNORE INTO $tblSessionUser SET - user_id ='$userId', - session_id = '$sessionId', - registered_at = '".api_get_utc_datetime()."'"; - $rsUser = Database::query($sql); - $userCounter++; - } - } - - // Adding courses to a session. - foreach ($nodeSession->Course as $nodeCourse) { - $course_code = Database::escape_string(trim(api_utf8_decode($nodeCourse->CourseCode))); - // Verify that the course pointed by the course code node exists. - if (CourseManager::course_exists($course_code)) { - // If the course exists we continue. - $course_info = api_get_course_info($course_code); - $courseId = $course_info['real_id']; - - $sessionCourseRelation = SessionManager::relation_session_course_exist( - $sessionId, - $courseId - ); - if (!$sessionCourseRelation) { - $sql_course = "INSERT INTO $tblSessionCourse SET - c_id = $courseId, - session_id = $sessionId"; - $rs_course = Database::query($sql_course); - SessionManager::installCourse($sessionId, $courseId); - } - - $courseCoaches = explode(',', $nodeCourse->Coach); - - // Adding coachs to session course user - foreach ($courseCoaches as $course_coach) { - //$coachId = UserManager::purify_username(api_utf8_decode($course_coach), $purification_option_for_usernames); - $coachId = UserManager::get_user_id_from_username($course_coach); - if (false !== $coachId) { - $sql = "INSERT IGNORE INTO $tblSessionCourseUser SET - user_id='$coachId', - c_id = '$courseId', - session_id = '$sessionId', - status = ".Session::COURSE_COACH; - $rs_coachs = Database::query($sql); - } else { - $errorMessage .= get_lang('This user doesn\'t exist').' : '.$coachId.'
'; - } - } - - // Adding users. - $courseCounter++; - $usersInCourseCounter = 0; - foreach ($nodeCourse->User as $nodeUser) { - $username = UserManager::purify_username(api_utf8_decode($nodeUser), $purificationOptionForUsernames); - $userId = UserManager::get_user_id_from_username($username); - if (false !== $userId) { - // Adding to session_rel_user table. - $sql = "INSERT IGNORE INTO $tblSessionUser SET - user_id ='$userId', - session_id = '$sessionId', - registered_at = '".api_get_utc_datetime()."'"; - $rsUser = Database::query($sql); - $userCounter++; - // Adding to session_rel_user_rel_course table. - $sql = "INSERT IGNORE INTO $tblSessionCourseUser SET - user_id = '$userId', - c_id = '$courseId', - session_id = '$sessionId'"; - $rsUsers = Database::query($sql); - $usersInCourseCounter++; - } else { - $errorMessage .= get_lang('This user doesn\'t exist').' : '.$username.'
'; - } - } - $sql = "UPDATE $tblSessionCourse SET nbr_users='$usersInCourseCounter' WHERE c_id='$courseId'"; - Database::query($sql); - $insertedInCourse[$course_code] = $course_info['title']; - } - } - Database::query("UPDATE $tblSession SET nbr_users='$userCounter', nbr_courses='$courseCounter' WHERE id='$sessionId'"); - } - } - if (empty($root->Users->User) && empty($root->Courses->Course) && empty($root->Session)) { - $errorMessage = get_lang('The specified file doesn\'t contain all needed data !'); - } + $uploadedFileName = $_FILES['import_file']['name']; + $uploadedExtension = strtolower(pathinfo($uploadedFileName, PATHINFO_EXTENSION)); + + if (!in_array($uploadedExtension, $allowedExtensions[$fileType] ?? [])) { + $errorMessage = get_lang('The uploaded file does not match the selected file type.'); + } else { + $sendMail = !empty($_POST['sendMail']); + $isOverwrite = !empty($_POST['overwrite']); + $deleteUsersNotInList = !empty($_POST['delete_users_not_in_list']); + + $insertedInCourse = []; + $errorMessage = ''; + + if ($fileType === 'xml') { + $result = SessionManager::importXML( + $_FILES['import_file']['tmp_name'], + $isOverwrite, + api_get_user_id(), + $sendMail, + SESSION_VISIBLE, + $insertedInCourse, + $errorMessage + ); } else { - $errorMessage .= get_lang('XML document is not valid'); + $result = SessionManager::importCSV( + $_FILES['import_file']['tmp_name'], + $isOverwrite, + api_get_user_id(), + null, + [], + null, + null, + null, + SESSION_VISIBLE, + [], + $deleteUsersNotInList, + !empty($_POST['update_course_coaches']), + false, + !empty($_POST['add_me_as_coach']), + false + ); } - } else { - // CSV - $updateCourseCoaches = isset($_POST['update_course_coaches']) ? true : false; - $addOriginalCourseTeachersAsCourseSessionCoaches = isset($_POST['add_me_as_coach']) ? true : false; - - $result = SessionManager::importCSV( - $_FILES['import_file']['tmp_name'], - $isOverwrite, - api_get_user_id(), - null, - [], - null, - null, - null, - 1, - [], - $deleteUsersNotInList, - $updateCourseCoaches, - false, - $addOriginalCourseTeachersAsCourseSessionCoaches, - false - ); - $sessionList = $result['session_list']; - $errorMessage = $result['error_message']; - $sessionCounter = $result['session_counter']; - } - if (!empty($errorMessage)) { - $errorMessage = get_lang('but problems occured').' :
'.$errorMessage; - } + $sessionCounter = $result['session_counter'] ?? 0; + $sessionList = $result['session_list'] ?? []; - if (!empty($insertedInCourse) && count($insertedInCourse) > 1) { - $warn = get_lang('Several courses were subscribed to the session because of a duplicate course code').': '; - foreach ($insertedInCourse as $code => $title) { - $warn .= ' '.$title.' ('.$code.'),'; + if (!empty($result['error_message'])) { + $errorMessage .= get_lang('but problems occured') . ' :
' . $result['error_message']; } - $warn = substr($warn, 0, -1); - } - if (1 == $sessionCounter) { - if ('csv' === $fileType) { - $sessionId = current($sessionList); + + if (!empty($insertedInCourse) && count($insertedInCourse) > 1) { + $warn = get_lang('Several courses were subscribed to the session because of a duplicate course code') . ': ' . + implode(', ', array_map(fn($code, $title) => "$title ($code)", array_keys($insertedInCourse), $insertedInCourse)); + } + + if (empty($errorMessage)) { + if ($sessionCounter === 1 && $fileType === 'csv') { + $sessionId = current($sessionList); + header('Location: resume_session.php?id_session=' . $sessionId); + exit; + } else { + header('Location: session_list.php'); + exit; + } } - Display::addFlash(Display::return_message($warn)); - header('Location: resume_session.php?id_session='.$sessionId); - exit; - } else { - Display::addFlash(Display::return_message(get_lang('File imported').' '.$errorMessage)); - header('Location: session_list.php'); - exit; } } else { $errorMessage = get_lang('No file was sent'); @@ -544,7 +120,7 @@ echo Display::toolbarAction('session_import', [$actions]); if (!empty($errorMessage)) { - echo Display::return_message($errorMessage, 'normal', false); + echo Display::return_message($errorMessage, 'error'); } $form = new FormValidator('import_sessions', 'post', api_get_self(), null, ['enctype' => 'multipart/form-data']); @@ -610,71 +186,89 @@ ) ); $form->display(); +echo ''; ?> -

bold are mandatory.').')'; ?> :

-
+    
+

:

+
 SessionName;Coach;DateStart;DateEnd;Users;Courses;VisibilityAfterExpiration;DisplayStartDate;DisplayEndDate;CoachStartDate;CoachEndDate;Classes
-Example 1;username;yyyy/mm/dd;yyyy/mm/dd;username1|username2;course1[coach1][username1,...]|course2[coach1][username1,...];read_only;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;class1|class2
-Example 2;username;yyyy/mm/dd;yyyy/mm/dd;username1|username2;course1[coach1][username1,...]|course2[coach1][username1,...];accessible;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;class3|class4
-Example 3;username;yyyy/mm/dd;yyyy/mm/dd;username1|username2;course1[coach1][username1,...]|course2[coach1][username1,...];not_accessible;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;yyyy/mm/dd;class5|class6
-
-

bold are mandatory.').')'; ?> :

-
-<?xml version="1.0" encoding="UTF-8"?>
+Example 1;username;2025/04/01;2025/04/30;username1|username2;course1[coach1][username1,...];read_only;2025/04/01;2025/04/30;2025/04/01;2025/04/30;class1
+Example 2;username;2025-04-01;2025-04-30;username1|username2;course1[coach1][username1,...];accessible;2025-04-01;2025-04-30;2025-04-01;2025-04-30;class2
+Example 3;username;2025/04/01 08:00:00;2025/04/30 23:59:59;username1|username2;course1[coach1][username1,...];not_accessible;2025/04/01 08:00:00;2025/04/30 23:59:59;2025/04/01 08:00:00;2025/04/30 23:59:59;class3
+    
+
+
+