pull/6062/merge
christianbeeznest 7 months ago committed by GitHub
commit 3b01a4e4d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      main/admin/index.php
  2. 330
      main/admin/user_advanced_edit.php
  3. 80
      main/inc/ajax/user_manager.ajax.php
  4. 48
      main/inc/lib/usermanager.lib.php

@ -147,6 +147,11 @@ if (api_is_platform_admin()) {
'url' => 'usergroups.php',
'label' => get_lang('Classes'),
];
$items[] = [
'class' => 'item-user-advanced_edit',
'url' => 'user_advanced_edit.php',
'label' => get_lang('UserAdvancedEdit'),
];
if (api_get_configuration_value('show_link_request_hrm_user')) {
$items[] = [
'class' => 'item-user-linking-requests',
@ -177,6 +182,11 @@ if (api_is_platform_admin()) {
'label' => get_lang('Classes'),
],
];
$items[] = [
'class' => 'item-user-advanced_edit',
'url' => 'user_advanced_edit.php',
'label' => get_lang('UserAdvancedEdit'),
];
if (api_is_session_admin()) {
if ('true' === api_get_setting('limit_session_admin_role')) {

@ -0,0 +1,330 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
api_protect_admin_script(true);
$this_section = SECTION_PLATFORM_ADMIN;
$tool_name = get_lang('AdvancedUserEdition');
$message = '';
// Secure GET parameters
$parameters = [];
if (!empty($_GET)) {
foreach ($_GET as $key => $value) {
$parameters[$key] = Security::remove_XSS($value);
}
}
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('PlatformAdmin')];
// Toolbar actions
$toolbarActions = '';
// Advanced search form
$form = new FormValidator('advancedSearch', 'get', '', '', [], FormValidator::LAYOUT_HORIZONTAL);
$form->addElement('header', '', get_lang('AdvancedSearch'));
$form->addText('keywordUsername', get_lang('LoginName'), false);
$form->addText('keywordEmail', get_lang('Email'), false);
$form->addText('keywordFirstname', get_lang('FirstName'), false);
$form->addText('keywordLastname', get_lang('LastName'), false);
$form->addText('keywordOfficialCode', get_lang('OfficialCode'), false);
$statusOptions = [
'%' => get_lang('All'),
STUDENT => get_lang('Student'),
COURSEMANAGER => get_lang('Teacher'),
DRH => get_lang('Drh'),
SESSIONADMIN => get_lang('SessionsAdmin'),
PLATFORM_ADMIN => get_lang('Administrator')
];
$form->addElement('select', 'keywordStatus', get_lang('Profile'), $statusOptions);
$activeGroup = [];
$activeGroup[] = $form->createElement('checkbox', 'keywordActive', '', get_lang('Active'));
$activeGroup[] = $form->createElement('checkbox', 'keywordInactive', '', get_lang('Inactive'));
$form->addGroup($activeGroup, '', get_lang('ActiveAccount'), null, false);
$form->addButtonSearch(get_lang('SearchUsers'), 'filter');
// Search filters
$searchFilters = [
'keywordFirstname' => $_GET['keywordFirstname'] ?? '',
'keywordLastname' => $_GET['keywordLastname'] ?? '',
'keywordUsername' => $_GET['keywordUsername'] ?? '',
'keywordEmail' => $_GET['keywordEmail'] ?? '',
'keywordOfficialCode' => $_GET['keywordOfficialCode'] ?? '',
'keywordStatus' => $_GET['keywordStatus'] ?? '',
'keywordActive' => $_GET['keywordActive'] ?? '',
'keywordInactive' => $_GET['keywordInactive'] ?? '',
];
$users = [];
if (isset($_GET['filter'])) {
$users = UserManager::searchUsers($searchFilters);
}
$fieldSelector = '';
$jqueryReadyContent = '';
$extraUserField = new ExtraField('user');
if (!empty($users)) {
$extraFields = $extraUserField->get_all(['filter = ?' => 1], 'option_order');
$editableFields = [
'firstname' => get_lang('FirstName'),
'lastname' => get_lang('LastName'),
'email' => get_lang('Email'),
'phone' => get_lang('PhoneNumber'),
'official_code' => get_lang('OfficialCode'),
'status' => get_lang('Profile'),
'active' => get_lang('ActiveAccount'),
'password' => get_lang('Password')
];
foreach ($extraFields as $field) {
$editableFields[$field['variable']] = ucfirst($field['variable']);
}
$form->addElement('select', 'editableFields', get_lang('FieldsToEdit'), $editableFields, [
'multiple' => 'multiple',
'size' => 7
]);
$form->addElement('submit', 'filter', get_lang('Filter'));
}
$tableResult = '';
if (!empty($users)) {
$selectedFields = $_GET['editableFields'] ?? [];
foreach ($users as &$user) {
$userData = api_get_user_info($user['id']);
if ($userData) {
$user = array_merge($user, $userData);
}
$extraFieldValues = new ExtraFieldValue('user');
$userExtraFields = $extraFieldValues->getAllValuesByItem($user['id']);
$formattedExtraFields = [];
foreach ($userExtraFields as $extraField) {
$formattedExtraFields[$extraField['variable']] = $extraField['value'];
}
$user['extra_fields'] = $formattedExtraFields;
}
unset($user);
$userTable = new SortableTable('users', null, null, 0, 50);
$userTable->set_header(0, get_lang('ID'));
$userTable->set_header(1, get_lang('Username'));
foreach ($selectedFields as $field) {
$userTable->set_header(count($userTable->headers), ucfirst($field));
}
$userTable->set_header(count($userTable->headers), get_lang('Actions'));
foreach ($users as $user) {
$row = [$user['id'], $user['username']];
foreach ($selectedFields as $field) {
$value = isset($user[$field]) ? htmlspecialchars($user[$field]) : '';
$extraFieldTypes = [];
foreach ($extraFields as $extraField) {
$extraFieldTypes[$extraField['variable']] = $extraField['field_type'];
}
if (isset($user['extra_fields'][$field])) {
$fieldType = $extraFieldTypes[$field] ?? ExtraField::FIELD_TYPE_TEXT;
$value = htmlspecialchars($user['extra_fields'][$field]);
switch ($fieldType) {
case ExtraField::FIELD_TYPE_TEXTAREA:
$row[] = '<textarea name="extra_'.$field.'['.$user['id'].']" class="form-control">'.$value.'</textarea>';
break;
case ExtraField::FIELD_TYPE_SELECT:
$fieldHtml = '<select name="extra_'.$field.'['.$user['id'].']" class="form-control">';
foreach ($extraField['options'] as $option) {
$selected = ($option['option_value'] == $value) ? 'selected' : '';
$fieldHtml .= '<option value="'.$option['option_value'].'" '.$selected.'>'.$option['display_text'].'</option>';
}
$fieldHtml .= '</select>';
$row[] = $fieldHtml;
break;
case ExtraField::FIELD_TYPE_CHECKBOX:
$checked = ($value == '1') ? 'checked' : '';
$row[] = '<input type="checkbox" name="extra_'.$field.'['.$user['id'].']" value="1" '.$checked.'>';
break;
case ExtraField::FIELD_TYPE_RADIO:
$fieldHtml = '';
foreach ($extraField['options'] as $option) {
$checked = ($option['option_value'] == $value) ? 'checked' : '';
$fieldHtml .= '<label><input type="radio" name="extra_'.$field.'['.$user['id'].']" value="'.$option['option_value'].'" '.$checked.'> '.$option['display_text'].'</label>';
}
$row[] = $fieldHtml;
break;
case ExtraField::FIELD_TYPE_TAG:
$extraTagField = $extraUserField->get_handler_field_info_by_field_variable($field);
$formattedValue = UserManager::get_user_tags_to_string(
$user['id'],
$extraTagField['id'],
false
);
$row[] = '<input type="text" name="extra_'.$field.'['.$user['id'].']" value="'.$formattedValue.'" class="form-control">'.
'<small>'.get_lang('KeywordTip').'</small>';
break;
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
if (is_array($value) && isset($value["extra_{$field}"]) && isset($value["extra_{$field}_second"])) {
$formattedValue = $value["extra_{$field}"] . ',' . $value["extra_{$field}_second"];
} else {
$formattedValue = '';
}
$row[] = '<input type="text" name="extra_'.$field.'['.$user['id'].']" value="'.$formattedValue.'" class="form-control">'.
'<small>'.get_lang('KeywordTip').'</small>';
break;
default:
$row[] = '<input type="text" name="extra_'.$field.'['.$user['id'].']" value="'.$value.'" class="form-control">';
break;
}
}
else {
if ($field === 'password') {
$row[] = '<input type="password" name="'.$field.'['.$user['id'].']" value="" class="form-control" placeholder="'.get_lang('Password').'">';
}
elseif ($field === 'status') {
$statusOptions = [
STUDENT => get_lang('Student'),
COURSEMANAGER => get_lang('Teacher'),
DRH => get_lang('Drh'),
SESSIONADMIN => get_lang('SessionsAdmin'),
PLATFORM_ADMIN => get_lang('Administrator')
];
$select = '<select name="status['.$user['id'].']" class="form-control">';
foreach ($statusOptions as $key => $label) {
$selected = ($key == $user['status']) ? 'selected' : '';
$select .= '<option value="'.$key.'" '.$selected.'>'.$label.'</option>';
}
$select .= '</select>';
$row[] = $select;
}
elseif ($field === 'active') {
$checkedActive = ($user['active'] == 1) ? 'checked' : '';
$checkedInactive = ($user['active'] == 0) ? 'checked' : '';
$row[] = '<label><input type="radio" name="active['.$user['id'].']" value="1" '.$checkedActive.'> '.get_lang('Active').'</label>
<label><input type="radio" name="active['.$user['id'].']" value="0" '.$checkedInactive.'> '.get_lang('Inactive').'</label>';
}
else {
$row[] = '<input type="text" name="'.$field.'['.$user['id'].']" value="'.$value.'" class="form-control">';
}
}
}
$row[] = '<button class="btn btn-primary saveUser" data-user-id="'.$user['id'].'">'.get_lang('Save').'</button>';
$userTable->addRow($row);
}
$tableResult = $userTable->return_table();
}
$htmlHeadXtra[] = '<script>
$(document).ready(function() {
function getUserData(userId) {
let userData = { user_id: userId };
$("input[name$=\'[" + userId + "]\'], select[name$=\'[" + userId + "]\'], textarea[name$=\'[" + userId + "]\']").each(function() {
let fieldName = $(this).attr("name").replace("[" + userId + "]", "");
userData[fieldName] = $(this).val();
});
$("input[type=\'radio\'][name$=\'[" + userId + "]\']:checked").each(function() {
let fieldName = $(this).attr("name").replace("[" + userId + "]", "");
userData[fieldName] = $(this).val();
});
$("input[type=\'checkbox\'][name$=\'[" + userId + "]\']:checked").each(function() {
let fieldName = $(this).attr("name").replace("[" + userId + "]", "");
userData[fieldName] = "1";
});
$("input[name^=\'extra_[" + userId + "]\'], select[name^=\'extra_[" + userId + "]\'], textarea[name^=\'extra_[" + userId + "]\']").each(function() {
let fieldName = $(this).attr("name").replace("extra_[" + userId + "]", "extra_");
if ($(this).hasClass("tags-input")) {
userData[fieldName] = $(this).val().split(",");
}
else if ($(this).hasClass("doubleselect-input")) {
let values = $(this).val().split(",");
if (values.length === 2) {
userData[fieldName] = values[0];
userData[fieldName + "_second"] = values[1];
}
}
else {
userData[fieldName] = $(this).val();
}
});
return userData;
}
$(".saveUser").click(function() {
let userId = $(this).data("user-id");
if (!userId) {
return;
}
let userData = getUserData(userId);
$.post("'.api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php", {
a: "update_users",
users: JSON.stringify([userData])
}, function(response) {
alert(response.message);
}, "json");
});
$("#saveAll").click(function() {
let usersData = [];
$(".saveUser").each(function() {
let userId = $(this).data("user-id");
let userData = getUserData(userId);
if (userData) usersData.push(userData);
});
if (usersData.length === 0) {
return;
}
$.post("'.api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php", {
a: "update_users",
users: JSON.stringify(usersData)
}, function(response) {
alert(response.message);
}, "json");
});
});
</script>';
$formContent = $form->returnForm();
// Render page
$tpl = new Template($tool_name);
$tpl->assign('actions', $toolbarActions);
$tpl->assign('message', $message);
$tpl->assign('content', $formContent . $fieldSelector . $tableResult . (!empty($users) ? '<button class="btn btn-success" id="saveAll">'.get_lang('SaveAll').'</button>' : ''));
$tpl->display_one_col_template();

@ -463,6 +463,86 @@ switch ($action) {
header('Content-Type: application/json');
echo json_encode(['items' => $items]);
break;
case 'update_users':
$usersData = json_decode($_POST['users'], true);
$updatedCount = 0;
foreach ($usersData as $userData) {
if (empty($userData['user_id'])) {
continue;
}
$userId = (int) $userData['user_id'];
$currentUserData = api_get_user_info($userId);
if (!$currentUserData) {
continue;
}
$updatedData = [
'firstname' => $userData['firstname'] ?? $currentUserData['firstname'],
'lastname' => $userData['lastname'] ?? $currentUserData['lastname'],
'email' => $userData['email'] ?? $currentUserData['email'],
'phone' => $userData['phone'] ?? $currentUserData['phone'],
'official_code' => $userData['official_code'] ?? $currentUserData['official_code'],
'status' => isset($userData['status']) ? (int) $userData['status'] : $currentUserData['status'],
'active' => isset($userData['active']) ? (int) $userData['active'] : $currentUserData['active'],
];
if (!empty($userData['password'])) {
$updatedData['password'] = $userData['password'];
}
$extraFieldHandler = new ExtraField('user');
$extraFieldValue = new ExtraFieldValue('user');
$extraFields = [];
foreach ($userData as $key => &$value) {
if (strpos($key, 'extra_') === 0) {
$fieldName = str_replace('extra_', '', $key);
$fieldInfo = $extraFieldHandler->get_handler_field_info_by_field_variable($fieldName);
if ($fieldInfo) {
if ($fieldInfo['field_type'] == 10 && is_string($value) && strpos($value, ',') !== false) {
$value = explode(',', $value);
}
}
}
}
UserManager::update_user(
$userId,
$updatedData['firstname'],
$updatedData['lastname'],
$currentUserData['username'],
$updatedData['password'] ?? null,
$currentUserData['auth_source'],
$updatedData['email'],
$updatedData['status'],
$updatedData['official_code'],
$updatedData['phone'],
$currentUserData['picture_uri'],
null,
$updatedData['active'],
null,
null,
null,
$currentUserData['language']
);
$userData['item_id'] = $userId;
$extraFieldValue->saveFieldValues(
$userData,
false,
false,
[],
[],
true
);
$updatedCount++;
}
echo json_encode(['message' => $updatedCount.' '.get_lang('UsersAdded')]);
break;
default:
echo '';
}

@ -8261,4 +8261,52 @@ SQL;
return $url;
}
/**
* Search for users based on given filters.
*/
public static function searchUsers(array $filters = [], array $editableFields = []): array
{
$where = [];
if (!empty($filters['keywordFirstname'])) {
$where[] = "u.firstname LIKE '%".Database::escape_string($filters['keywordFirstname'])."%'";
}
if (!empty($filters['keywordLastname'])) {
$where[] = "u.lastname LIKE '%".Database::escape_string($filters['keywordLastname'])."%'";
}
if (!empty($filters['keywordUsername'])) {
$where[] = "u.username LIKE '%".Database::escape_string($filters['keywordUsername'])."%'";
}
if (!empty($filters['keywordEmail'])) {
$where[] = "u.email LIKE '%".Database::escape_string($filters['keywordEmail'])."%'";
}
if (!empty($filters['keywordOfficialCode'])) {
$where[] = "u.official_code LIKE '%".Database::escape_string($filters['keywordOfficialCode'])."%'";
}
if (!empty($filters['keywordStatus']) && $filters['keywordStatus'] !== '%') {
$where[] = "u.status = '".Database::escape_string($filters['keywordStatus'])."'";
}
if (!empty($filters['keywordActive']) && empty($filters['keywordInactive'])) {
$where[] = "u.active = 1";
} elseif (empty($filters['keywordActive']) && !empty($filters['keywordInactive'])) {
$where[] = "u.active = 0";
}
$fields = ['u.id', 'u.username'];
if (!empty($editableFields)) {
foreach ($editableFields as $field) {
$fields[] = "u." . Database::escapeField($field);
}
}
$sql = "SELECT " . implode(", ", $fields) . " FROM " . Database::get_main_table(TABLE_MAIN_USER) . " u";
if (!empty($where)) {
$sql .= " WHERE " . implode(" AND ", $where);
}
$sql .= " ORDER BY u.id ASC";
return Database::store_result(Database::query($sql), 'ASSOC');
}
}

Loading…
Cancel
Save