@ -6,67 +6,52 @@
* This tool allows platform admins to add users by uploading a CSV or XML file.
*/
/**
* Validate the imported data.
*/
use Symfony\Component\DomCrawler\Crawler;
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
// Set this option to true to enforce strict purification for usenames.
// Set this option to true to enforce strict purification for user names.
$purification_option_for_usernames = false;
/**
* @param array $users
*
* @return array
*/
function validate_data($users)
{
global $defined_auth_sources;
$errors = [];
$usernames = [];
// 1. Check if mandatory fields are set.
$mandatory_fields = ['LastName', 'FirstName'];
if ('true' == api_get_setting('registration', 'email')) {
$mandatory_fields[] = 'Email';
}
$classExistList = [];
$usergroup = new UserGroup();
foreach ($users as $user) {
foreach ($mandatory_fields as $field) {
if (isset($user[$field])) {
if (empty($user[$field])) {
$user['error'] = get_lang($field.'Mandatory');
$errors[] = $user;
}
}
}
// 2. Check username, first, check whether it is empty.
if (isset($user['NewUserName'])) {
if (!UserManager::is_username_empty($user['NewUserName'])) {
// 2.1. Check whether username is too long.
if (UserManager::is_username_too_long($user['NewUserName'])) {
$user['error'] = get_lang('This login is too long');
$errors[] = $user;
$errors[$user['UserName']][] = get_lang('UserNameTooLong');
}
// 2.2. Check whether the username was used twice in import file.
if (isset($usernames[$user['NewUserName']])) {
$user['error'] = get_lang('Login is used twice');
$errors[] = $user;
$errors[$user['UserName']][] = get_lang('UserNameUsedTwice');
}
$usernames[$user['UserName']] = 1;
// 2.3. Check whether username is allready occupied.
if (!UserManager::is_username_available($user['NewUserName']) & & $user['NewUserName'] != $user['UserName']) {
$user['error'] = get_lang('This login is not available');
$errors[] = $user;
if (!UserManager::is_username_available($user['NewUserName']) & &
$user['NewUserName'] != $user['UserName']
) {
$errors[$user['UserName']][] = get_lang('UserNameNotAvailable');
}
}
}
// 3. Check status.
if (isset($user['Status']) & & !api_status_exists($user['Status'])) {
$user['error'] = get_lang('This status doesn\'t exist');
$errors[] = $user;
$errors[$user['UserName']][] = get_lang('WrongStatus');
}
// 4. Check ClassId
@ -78,8 +63,7 @@ function validate_data($users)
}
$info = $usergroup->get($id);
if (empty($info)) {
$user['error'] = sprintf(get_lang('Class ID does not exist'), $id);
$errors[] = $user;
$errors[$user['UserName']][] = sprintf(get_lang('ClassIdDoesntExists'), $id);
} else {
$classExistList[] = $info['id'];
}
@ -89,8 +73,7 @@ function validate_data($users)
// 5. Check authentication source
if (!empty($user['AuthSource'])) {
if (!in_array($user['AuthSource'], $defined_auth_sources)) {
$user['error'] = get_lang('Authentication source unavailable.');
$errors[] = $user;
$errors[$user['UserName']][] = get_lang('AuthSourceNotAvailable');
}
}
}
@ -98,74 +81,53 @@ function validate_data($users)
return $errors;
}
/**
* Add missing user-information (which isn't required, like password, username etc).
*/
function complete_missing_data($user)
{
global $purification_option_for_usernames;
// 1. Create a username if necessary.
if (UserManager::is_username_empty($user['UserName'])) {
$user['UserName'] = UserManager::create_unique_username($user['FirstName'], $user['LastName']);
} else {
$user['UserName'] = UserManager::purify_username($user['UserName'], $purification_option_for_usernames);
}
// 2. Generate a password if necessary.
if (empty($user['Password'])) {
$user['Password'] = api_generate_password();
}
// 3. Set status if not allready set.
if (empty($user['Status'])) {
$user['Status'] = 'user';
}
// 4. Set authsource if not allready set.
if (empty($user['AuthSource'])) {
$user['AuthSource'] = PLATFORM_AUTH_SOURCE;
}
return $user;
}
/**
* Update users from the imported data.
*
* @param array $users List of users
*
* @return false|null
*
* @uses \global variable $inserted_in_course, which returns the list of courses the user was inserted in
* @param array $users List of users.
* @param bool $resetPassword Optional.
* @param bool $sendEmail Optional.
*/
function updateUsers($users)
function updateUsers(
$users,
$resetPassword = false,
$sendEmail = false)
{
global $insertedIn_course;
// Not all scripts declare the $inserted_in_course array (although they should).
if (!isset($inserted_in_course)) {
$inserted_in_course = [];
}
$usergroup = new UserGroup();
$send_mail = !empty($_POST['sendMail']) ? true : false;
if (is_array($users)) {
foreach ($users as $user) {
$user = complete_missing_data($user);
if (isset($user['Status'])) {
$user['Status'] = api_status_key($user['Status']);
$userName = $user['UserName'];
$userInfo = api_get_user_info_from_username($userName);
$user_id = $userInfo['user_id'];
if (0 == $user_id) {
return false;
}
$userInfo = api_get_user_info_from_username($user['UserName']);
if (empty($userInfo)) {
continue;
}
$user_id = $userInfo['user_id'];
$firstName = isset($user['FirstName']) ? $user['FirstName'] : $userInfo['firstname'];
$lastName = isset($user['LastName']) ? $user['LastName'] : $userInfo['lastname'];
$userName = isset($user['NewUserName']) ? $user['NewUserName'] : $userInfo['username'];
$changePassMethod = 0;
$password = isset($user['Password']) ? $user['Password'] : '';
if (!empty($password)) {
$password = null;
$authSource = $userInfo['auth_source'];
if ($resetPassword) {
$changePassMethod = 1;
} else {
if (isset($user['Password'])) {
$changePassMethod = 2;
$password = $user['Password'];
}
$authSource = isset($user['AuthSource']) ? $user['AuthSource'] : '';
if (2 === $changePassMethod & & !empty($authSource) & & $authSource != $userInfo['auth_source']) {
if (isset($user['AuthSource']) & & $user['AuthSource'] != $authSource) {
$authSource = $user['AuthSource'];
$changePassMethod = 3;
}
}
$email = isset($user['Email']) ? $user['Email'] : $userInfo['email'];
$status = isset($user['Status']) ? $user['Status'] : $userInfo['status'];
$officialCode = isset($user['OfficialCode']) ? $user['OfficialCode'] : $userInfo['official_code'];
@ -176,8 +138,14 @@ function updateUsers($users)
$creatorId = $userInfo['creator_id'];
$hrDeptId = $userInfo['hr_dept_id'];
$language = isset($user['Language']) ? $user['Language'] : $userInfo['language'];
$sendEmail = isset($user['SendEmail']) ? $user['SendEmail'] : $userInfo['language'];
$userUpdated = UserManager :: update_user(
//$sendEmail = isset($user['SendEmail']) ? $user['SendEmail'] : $userInfo['language'];
//$sendEmail = false;
// see BT#17893
if ($resetPassword & & $sendEmail == false) {
$sendEmail = true;
}
UserManager::update_user(
$user_id,
$firstName,
$lastName,
@ -196,9 +164,10 @@ function updateUsers($users)
null,
$language,
'',
'' ,
$sendEmail ,
$changePassMethod
);
if (!empty($user['Courses']) & & !is_array($user['Courses'])) {
$user['Courses'] = [$user['Courses']];
}
@ -206,8 +175,6 @@ function updateUsers($users)
foreach ($user['Courses'] as $course) {
if (CourseManager::course_exists($course)) {
CourseManager::subscribeUser($user_id, $course, $user['Status']);
$course_info = api_get_course_info($course);
$inserted_in_course[$course] = $course_info['title'];
}
}
}
@ -237,6 +204,11 @@ function updateUsers($users)
);
}
}
$userUpdated = api_get_user_info($user_id);
Display::addFlash(
Display::return_message(get_lang('UserUpdated').': '.$userUpdated['complete_name_with_username'])
);
}
}
}
@ -246,16 +218,25 @@ function updateUsers($users)
*
* @param string $file Path to the CSV-file
*
* @throws Exception
*
* @return array All userinformation read from the file
*/
function parse_csv_data($file)
{
$users = Import :: csvToArray($file);
foreach ($users as $index => $user) {
if (isset($user['Courses'])) {
$user['Courses'] = explode('|', trim($user['Courses']));
$data = Import::csv_reader($file);
if (empty($data)) {
throw new Exception(get_lang('NoDataAvailable'));
}
$users = [];
foreach ($data as $row) {
if (isset($row['Courses'])) {
$row['Courses'] = explode('|', trim($row['Courses']));
}
if (!isset($row['UserName'])) {
throw new Exception(get_lang('ThisFieldIsRequired').': UserName');
}
$users[$index] = $user;
$users[] = $row ;
}
return $users;
@ -263,14 +244,14 @@ function parse_csv_data($file)
function parse_xml_data($file)
{
$crawler = new \Symfony\Component\DomCrawler\ Crawler();
$crawler = new Crawler();
$crawler->addXmlContent(file_get_contents($file));
$crawler = $crawler->filter('Contacts > Contact ');
$array = [];
foreach ($crawler as $domElement) {
$row = [];
foreach ($domElement->childNodes as $node) {
if ('#text' != $node->nodeName) {
if ($node->nodeName != '#text' ) {
$row[$node->nodeName] = $node->nodeValue;
}
}
@ -286,116 +267,105 @@ $this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script(true, null);
$defined_auth_sources[] = PLATFORM_AUTH_SOURCE;
if (isset($extAuthSource) & & is_array($extAuthSource)) {
$defined_auth_sources = array_merge($defined_auth_sources, array_keys($extAuthSource));
}
$tool_name = get_lang('Import users list ');
$interbreadcrumb[] = ["url" => 'index.php', "name" => get_lang('Administratio n')];
$tool_name = get_lang('UpdateUserListXMLCSV ');
$interbreadcrumb[] = ["url" => 'index.php', "name" => get_lang('Platform Admin')];
set_time_limit(0);
$extra_fields = UserManager::get_extra_fields(0, 0, 5, 'ASC', true);
$user_id_error = [];
$error_message = '';
if (isset($_POST['formSent']) & & $_POST['formSent'] & & 0 !== $_FILES['import_file']['size']) {
$file_type = 'csv';
$form = new FormValidator('user_update_import', 'post', api_get_self());
$form->addHeader($tool_name);
$form->addFile('import_file', get_lang('ImportFileLocation'), ['accept' => 'text/csv', 'id' => 'import_file']);
$form->addCheckBox('reset_password', '', get_lang('AutoGeneratePassword'));
$group = [
$form->createElement('radio', 'sendMail', '', get_lang('Yes'), 1),
$form->createElement('radio', 'sendMail', null, get_lang('No'), 0),
];
$form->addGroup($group, '', get_lang('SendMailToUsers'));
$defaults['sendMail'] = 0;
if ($form->validate()) {
if (Security::check_token('post')) {
Security::clear_token();
$tok = Security::get_token();
$allowed_file_mimetype = ['csv', 'xml'];
$error_kind_file = false;
$formValues = $form->exportValues();
if (empty($_FILES['import_file']) || empty($_FILES['import_file']['size'])) {
header('Location: '.api_get_self());
exit;
}
$uploadInfo = pathinfo($_FILES['import_file']['name']);
$ext_import_file = $uploadInfo['extension'];
if (in_array($ext_import_file, $allowed_file_mimetype)) {
if (0 === strcmp($file_type, 'csv') & & $ext_import_file == $allowed_file_mimetype[0]) {
$users = parse_csv_data($_FILES['import_file']['tmp_name']);
$errors = validate_data($users);
$error_kind_file = false;
} elseif (0 === strcmp($file_type, 'xml') & & $ext_import_file == $allowed_file_mimetype[1]) {
$users = parse_xml_data($_FILES['import_file']['tmp_name']);
$errors = validate_data($users);
$error_kind_file = false;
} else {
$error_kind_file = true;
}
} else {
$error_kind_file = true;
if ($uploadInfo['extension'] !== 'csv') {
Display::addFlash(
Display::return_message(get_lang('YouMustImportAFileAccordingToSelectedOption'), 'error')
);
header('Location: '.api_get_self());
exit;
}
// List user id with error.
$users_to_insert = $user_id_error = [];
try {
$users = parse_csv_data($_FILES['import_file']['tmp_name']);
} catch (Exception $exception) {
Display::addFlash(
Display::return_message($exception->getMessage(), 'error')
);
if (is_array($errors)) {
foreach ($errors as $my_errors) {
$user_id_error[] = $my_errors['UserName'];
}
header('Location: '.api_get_self());
exit;
}
if (is_array($users)) {
foreach ($users as $my_user) {
if (!in_array($my_user['UserName'], $user_id_error)) {
$users_to_insert[] = $my_user;
}
$errors = validate_data($users);
$errorUsers = array_keys($errors);
$usersToUpdate = [];
foreach ($users as $user) {
if (!in_array($user['UserName'], $errorUsers)) {
$usersToUpdate[] = $user;
}
}
$inserted_in_course = [];
if (0 === strcmp($file_type, 'csv')) {
updateUsers($users_to_insert);
}
$sendEmail = $_POST['sendMail'] ? true : false;
updateUsers($usersToUpdate, isset($formValues['reset_password']), $sendEmail);
if (count($errors) > 0) {
$see_message_import = get_lang('The users that were not registered on the platform have been imported');
if (empty($errors)) {
Display::addFlash(
Display::return_message(get_lang('FileImported'), 'success')
);
} else {
$see_message_import = get_lang('File imported');
}
$warning_message = '';
if (0 != count($errors)) {
$warning_message = '< ul > ';
foreach ($errors as $index => $error_user) {
$warning_message .= '< li > < b > '.$error_user['error'].'< / b > : ';
$warning_message .=
'< strong > '.$error_user['UserName'].'< / strong > ('.
api_get_person_name($error_user['FirstName'], $error_user['LastName']).')';
$warning_message .= '< / li > ';
}
$warning_message .= '< / ul > ';
$warningMessage = '';
foreach ($errors as $errorUsername => $errorUserMessages) {
$warningMessage .= "< strong > $errorUsername< / strong > ";
$warningMessage .= '< ul > < li > '.implode('< / li > < li > ', $errorUserMessages).'< / li > < / ul > ';
}
// if the warning message is too long then we display the warning message trough a session
if (!empty($warning_message)) {
Display::addFlash(Display::return_message($warning_message, 'warning', false));
Display::addFlash(
Display::return_message(get_lang('FileImportedJustUsersThatAreNotRegistered'), 'warning')
);
Display::addFlash(Display::return_message($warningMessage, 'warning', false));
}
if ($error_kind_file) {
Display::addFlash(Display::return_message(get_lang('You must import a file corresponding to the selected format'), 'error', false)) ;
header('Location: '.api_get_self());
exit;
} else {
header('Location: '.api_get_path(WEB_CODE_PATH).'admin/user_list.php?sec_token='.$tok);
Display::addFlash(Display::return_message(get_lang('LinkExpired'), 'warning', false));
header('Location: '.api_get_self());
exit;
}
}
Display::display_header($tool_name);
if (!empty($error_message)) {
echo Display::return_message($error_message, 'error');
}
$form = new FormValidator('user_update_import', 'post', api_get_self());
$form->addElement('header', $tool_name);
$form->addElement('hidden', 'formSent');
$form->addElement('file', 'import_file', get_lang('Import marks in an assessment'));
$group = [];
Display::display_header($tool_name);
$token = Security::get_token();
$form->addButtonImport(get_lang('Import'));
$defaults['formSent'] = 1;
$defaults['sendMail'] = 0;
$defaults['file_type'] = 'csv';
$form->setDefaults($defaults);
$form->addHidden('sec_token', $token);
$form->addButtonImport(get_lang('Import'));
$form->display();
$list = [];
@ -417,15 +387,16 @@ if ($count_fields > 0) {
}
?>
< p > <?php echo get_lang ( 'The CSV file must look like this ' ) . ' (' . get_lang ( 'Fields in <strong>bold</strong> are mandatory. ' ) . ')' ; ?> :</ p >
< blockquote >
< p > <?php echo get_lang ( 'CSVMustLookLike ' ) . ' (' . get_lang ( 'MandatoryFields ' ) . ')' ; ?> :</ p >
< blockquote >
< pre >
< b > UserName< / b > ;LastName;FirstName;Email;NewUserName;Password;AuthSource;OfficialCode;PhoneNumber;Status;ExpiryDate;Active;Language;Courses;ClassId;
xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;user/teacher/drh;YYYY-MM-DD 00:00:00;0/1;xxx;< span style = "color:red;" > <?php if ( count ( $list_reponse ) > 0 ) {
xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;xxx;user/teacher/drh;YYYY-MM-DD 00:00:00;0/1;xxx;< span
style="color:red;"><?php if ( count ( $list_reponse ) > 0 ) {
echo implode(';', $list_reponse).';';
} ?>< / span > xxx1|xxx2|xxx3;1;< br / >
} ?>< / span > xxx1|xxx2|xxx3;1;< br / >
< / pre >
< / blockquote >
< p > <?php
Display :: display_footer();
< / blockquote >
< p >
<?php
Display::display_footer();