diff --git a/main/admin/index.php b/main/admin/index.php index 08d7c2da66..6edd06fa07 100644 --- a/main/admin/index.php +++ b/main/admin/index.php @@ -534,8 +534,30 @@ if (api_is_platform_admin()) { } } - /* Chamilo.org */ + // Data protection + $blocks['data_privacy']['icon'] = Display::return_icon( + 'platform.png', + get_lang('Platform'), + [], + ICON_SIZE_MEDIUM, + false + ); + $blocks['data_privacy']['label'] = api_ucfirst(get_lang('PersonalDataPrivacy')); + $blocks['data_privacy']['class'] = 'block-admin-platform'; + $blocks['data_privacy']['editable'] = false; + $items = []; + + $items[] = [ + 'url' => api_get_path(WEB_CODE_PATH).'admin/user_list_consent.php', + 'label' => get_lang('UserList'), + ]; + + $blocks['data_privacy']['items'] = $items; + $blocks['data_privacy']['extra'] = null; + $blocks['data_privacy']['search_form'] = null; + + /* Chamilo.org */ $blocks['chamilo']['icon'] = Display::return_icon( 'platform.png', 'Chamilo.org', diff --git a/main/admin/user_list.php b/main/admin/user_list.php index e1c0de0e9f..20a306ccec 100755 --- a/main/admin/user_list.php +++ b/main/admin/user_list.php @@ -46,12 +46,6 @@ if (isset($_GET['user_id']) && $action == 'login_as') { api_protect_admin_script(true); -// Blocks the possibility to delete a user -$deleteUserAvailable = true; -if (api_get_configuration_value('deny_delete_users')) { - $deleteUserAvailable = false; -} - trimVariables(); $url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=get_user_courses'; @@ -870,40 +864,10 @@ if (!empty($action)) { } break; case 'delete_user': - $allowDelete = api_get_configuration_value('allow_delete_user_for_session_admin'); - if (api_is_platform_admin() || - ($allowDelete && api_is_session_admin()) - ) { - $userToUpdate = $_GET['user_id']; - $userToUpdateInfo = api_get_user_info($userToUpdate); - $currentUserId = api_get_user_id(); - - if ($userToUpdateInfo && $deleteUserAvailable && - api_global_admin_can_edit_admin($_GET['user_id'], null, $allowDelete) - ) { - if ($userToUpdate != $currentUserId && - UserManager::delete_user($_GET['user_id']) - ) { - $message = Display::return_message( - get_lang('UserDeleted').': '.$userToUpdateInfo['complete_name_with_username'], - 'confirmation' - ); - } else { - $message = Display::return_message( - get_lang('CannotDeleteUserBecauseOwnsCourse'), - 'error' - ); - } - } else { - $message = Display::return_message( - get_lang('CannotDeleteUser'), - 'error' - ); - } - Display::addFlash($message); - header('Location: '.api_get_self()); - exit; - } + $message = UserManager::deleteUserWithVerification($_GET['user_id']); + Display::addFlash($message); + header('Location: '.api_get_self()); + exit; break; case 'delete': if (api_is_platform_admin()) { @@ -984,39 +948,10 @@ if (!empty($action)) { } break; case 'anonymize': - if (api_is_platform_admin() || - ($allowDelete && api_is_session_admin()) - ) { - $userToUpdate = (int) $_GET['user_id']; - $userToUpdateInfo = api_get_user_info($userToUpdate); - $currentUserId = api_get_user_id(); - - if ($userToUpdateInfo && - api_global_admin_can_edit_admin($userToUpdate, null, $allowDelete) - ) { - if ($userToUpdate != $currentUserId && - UserManager::anonymize($userToUpdate) - ) { - $message = Display::return_message( - sprintf(get_lang('UserXAnonymized'), $userToUpdateInfo['complete_name_with_username']), - 'confirmation' - ); - } else { - $message = Display::return_message( - sprintf(get_lang('CannotAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), - 'error' - ); - } - } else { - $message = Display::return_message( - sprintf(get_lang('NoPermissionToAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), - 'error' - ); - } - Display::addFlash($message); - header('Location: '.api_get_self()); - exit; - } + $message = UserManager::anonymizeUserWithVerification($_GET['user_id']); + Display::addFlash($message); + header('Location: '.api_get_self()); + exit; break; } Security::clear_token(); diff --git a/main/admin/user_list_consent.php b/main/admin/user_list_consent.php new file mode 100644 index 0000000000..c9086e4e6b --- /dev/null +++ b/main/admin/user_list_consent.php @@ -0,0 +1,697 @@ + BeezNest 2011 + * + * @package chamilo.admin + */ +$cidReset = true; +require_once __DIR__.'/../inc/global.inc.php'; + +$urlId = api_get_current_access_url_id(); +$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; + +api_protect_admin_script(); + +$this_section = SECTION_PLATFORM_ADMIN; + +/** + * Prepares the shared SQL query for the user table. + * See get_user_data() and get_number_of_users(). + * + * @param bool $getCount Whether to count, or get data + * + * @return string SQL query + */ +function prepare_user_sql_query($getCount) +{ + $sql = ''; + $user_table = Database::get_main_table(TABLE_MAIN_USER); + $admin_table = Database::get_main_table(TABLE_MAIN_ADMIN); + + if ($getCount) { + $sql .= "SELECT COUNT(u.id) AS total_number_of_items FROM $user_table u"; + } else { + $sql .= "SELECT u.id AS col0, u.official_code AS col2, "; + if (api_is_western_name_order()) { + $sql .= "u.firstname AS col3, u.lastname AS col4, "; + } else { + $sql .= "u.lastname AS col3, u.firstname AS col4, "; + } + + $sql .= " u.username AS col5, + u.email AS col6, + u.status AS col7, + u.active AS col8, + u.id AS col9, + u.registration_date AS col10, + u.expiration_date AS exp, + u.password + FROM $user_table u"; + } + + // adding the filter to see the user's only of the current access_url + if ((api_is_platform_admin() || api_is_session_admin()) && api_get_multiple_access_url()) { + $access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); + $sql .= " INNER JOIN $access_url_rel_user_table url_rel_user + ON (u.id=url_rel_user.user_id)"; + } + + $extraFieldId = UserManager::create_extra_field( + 'request_for_legal_agreement_consent_removal', + 1, //text + 'Request for legal agreement consent removal', + '' + ); + + $extraFieldValue = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); + $sql .= " INNER JOIN $extraFieldValue v + ON (u.id = v.item_id AND field_id = $extraFieldId) "; + + $keywordList = [ + 'keyword_firstname', + 'keyword_lastname', + 'keyword_username', + 'keyword_email', + 'keyword_officialcode', + 'keyword_status', + 'keyword_active', + 'keyword_inactive', + 'check_easy_passwords', + ]; + + $keywordListValues = []; + $atLeastOne = false; + foreach ($keywordList as $keyword) { + $keywordListValues[$keyword] = null; + if (isset($_GET[$keyword]) && !empty($_GET[$keyword])) { + $keywordListValues[$keyword] = $_GET[$keyword]; + $atLeastOne = true; + } + } + + if ($atLeastOne == false) { + $keywordListValues = []; + } + + if (isset($_GET['keyword']) && !empty($_GET['keyword'])) { + $keywordFiltered = Database::escape_string("%".$_GET['keyword']."%"); + $sql .= " WHERE ( + u.firstname LIKE '$keywordFiltered' OR + u.lastname LIKE '$keywordFiltered' OR + concat(u.firstname, ' ', u.lastname) LIKE '$keywordFiltered' OR + concat(u.lastname,' ',u.firstname) LIKE '$keywordFiltered' OR + u.username LIKE '$keywordFiltered' OR + u.official_code LIKE '$keywordFiltered' OR + u.email LIKE '$keywordFiltered' + ) + "; + } elseif (isset($keywordListValues) && !empty($keywordListValues)) { + $query_admin_table = ''; + $keyword_admin = ''; + + if (isset($keywordListValues['keyword_status']) && + $keywordListValues['keyword_status'] == PLATFORM_ADMIN + ) { + $query_admin_table = " , $admin_table a "; + $keyword_admin = ' AND a.user_id = u.id '; + $keywordListValues['keyword_status'] = '%'; + } + + $keyword_extra_value = ''; + + $sql .= " $query_admin_table + WHERE ( + u.firstname LIKE '".Database::escape_string("%".$keywordListValues['keyword_firstname']."%")."' AND + u.lastname LIKE '".Database::escape_string("%".$keywordListValues['keyword_lastname']."%")."' AND + u.username LIKE '".Database::escape_string("%".$keywordListValues['keyword_username']."%")."' AND + u.email LIKE '".Database::escape_string("%".$keywordListValues['keyword_email']."%")."' AND + u.status LIKE '".Database::escape_string($keywordListValues['keyword_status'])."' "; + if (!empty($keywordListValues['keyword_officialcode'])) { + $sql .= " AND u.official_code LIKE '".Database::escape_string("%".$keywordListValues['keyword_officialcode']."%")."' "; + } + + $sql .= " + $keyword_admin + $keyword_extra_value + "; + + if (isset($keywordListValues['keyword_active']) && + !isset($keywordListValues['keyword_inactive']) + ) { + $sql .= " AND u.active = 1"; + } elseif (isset($keywordListValues['keyword_inactive']) && + !isset($keywordListValues['keyword_active']) + ) { + $sql .= " AND u.active = 0"; + } + $sql .= " ) "; + } + + $preventSessionAdminsToManageAllUsers = api_get_setting('prevent_session_admins_to_manage_all_users'); + if (api_is_session_admin() && $preventSessionAdminsToManageAllUsers === 'true') { + $sql .= " AND u.creator_id = ".api_get_user_id(); + } + + $variables = Session::read('variables_to_show', []); + if (!empty($variables)) { + $extraField = new ExtraField('user'); + $extraFieldResult = []; + $extraFieldHasData = []; + foreach ($variables as $variable) { + if (isset($_GET['extra_'.$variable])) { + if (is_array($_GET['extra_'.$variable])) { + $values = $_GET['extra_'.$variable]; + } else { + $values = [$_GET['extra_'.$variable]]; + } + + if (empty($values)) { + continue; + } + + $info = $extraField->get_handler_field_info_by_field_variable( + $variable + ); + + if (empty($info)) { + continue; + } + + foreach ($values as $value) { + if (empty($value)) { + continue; + } + if ($info['field_type'] == ExtraField::FIELD_TYPE_TAG) { + $result = $extraField->getAllUserPerTag( + $info['id'], + $value + ); + $result = empty($result) ? [] : array_column( + $result, + 'user_id' + ); + } else { + $result = UserManager::get_extra_user_data_by_value( + $variable, + $value + ); + } + $extraFieldHasData[] = true; + if (!empty($result)) { + $extraFieldResult = array_merge( + $extraFieldResult, + $result + ); + } + } + } + } + + if (!empty($extraFieldHasData)) { + $sql .= " AND (u.id IN ('".implode("','", $extraFieldResult)."')) "; + } + } + + // adding the filter to see the user's only of the current access_url + if ((api_is_platform_admin() || api_is_session_admin()) && + api_get_multiple_access_url() + ) { + $sql .= " AND url_rel_user.access_url_id=".api_get_current_access_url_id(); + } + + return $sql; +} + +/** + * Get the total number of users on the platform. + * + * @see SortableTable#get_total_number_of_items() + */ +function get_number_of_users() +{ + $sql = prepare_user_sql_query(true); + $res = Database::query($sql); + $obj = Database::fetch_object($res); + + return $obj->total_number_of_items; +} + +/** + * Get the users to display on the current page (fill the sortable-table). + * + * @param int offset of first user to recover + * @param int Number of users to get + * @param int Column to sort on + * @param string Order (ASC,DESC) + * + * @return array Users list + * + * @see SortableTable#get_table_data($from) + */ +function get_user_data($from, $number_of_items, $column, $direction) +{ + $sql = prepare_user_sql_query(false); + if (!in_array($direction, ['ASC', 'DESC'])) { + $direction = 'ASC'; + } + $column = (int) $column; + $from = intval($from); + $number_of_items = intval($number_of_items); + $sql .= " ORDER BY col$column $direction "; + $sql .= " LIMIT $from,$number_of_items"; + + $res = Database::query($sql); + + $users = []; + $t = time(); + while ($user = Database::fetch_row($res)) { + $userPicture = UserManager::getUserPicture( + $user[0], + USER_IMAGE_SIZE_SMALL + ); + $photo = ''.api_get_person_name($user[2], $user[3]).''; + + if ($user[7] == 1 && !empty($user[10])) { + // check expiration date + $expiration_time = convert_sql_date($user[10]); + // if expiration date is passed, store a special value for active field + if ($expiration_time < $t) { + $user[7] = '-1'; + } + } + + // forget about the expiration date field + $users[] = [ + $user[0], + $photo, + $user[1], + $user[2], + $user[3], + $user[4], + $user[5], + $user[6], + $user[7], + api_get_local_time($user[9]), + $user[0], + ]; + } + + return $users; +} + +/** + * Returns a mailto-link. + * + * @param string $email An email-address + * + * @return string HTML-code with a mailto-link + */ +function email_filter($email) +{ + return Display::encrypted_mailto_link($email, $email); +} + +/** + * Returns a mailto-link. + * + * @param string $email An email-address + * @param array $params Deprecated + * @param array $row + * + * @return string HTML-code with a mailto-link + */ +function user_filter($name, $params, $row) +{ + return ''.$name.''; +} + +/** + * Build the modify-column of the table. + * + * @param int The user id + * @param string URL params to add to table links + * @param array Row of elements to alter + * + * @throws Exception + * + * @return string Some HTML-code with modify-buttons + */ +function modify_filter($user_id, $url_params, $row) +{ + $_admins_list = Session::read('admin_list', []); + $is_admin = in_array($user_id, $_admins_list); + $token = Security::getTokenFromSession(); + $result = ''; + $result .= ''. + Display::return_icon('synthese_view.gif', get_lang('Info')).'  '; + + $result .= Display::url( + get_lang('SendMessage'), + api_get_path(WEB_CODE_PATH).'messages/new_message.php?send_to_user='.$user_id + ); + $result .= '  '; + $result .= Display::url( + get_lang('RemoveTerms'), + api_get_self().'?user_id='.$user_id.'&action=delete_terms&sec_token='.$token + ); + $result .= '  '; + + $result .= ' '. + Display::return_icon( + 'anonymous.png', + get_lang('Anonymize'), + [], + ICON_SIZE_SMALL + ). + ''; + + if ($user_id != api_get_user_id()) { + $result .= ' '. + Display::return_icon( + 'delete.png', + get_lang('Delete'), + [], + ICON_SIZE_SMALL + ). + ''; + } + + $editProfileUrl = Display::getProfileEditionLink($user_id, true); + + $result .= ''. + Display::return_icon( + 'edit.png', + get_lang('Edit'), + [], + ICON_SIZE_SMALL + ). + ' '; + + if ($is_admin) { + $result .= Display::return_icon( + 'admin_star.png', + get_lang('IsAdministrator'), + ['width' => ICON_SIZE_SMALL, 'heigth' => ICON_SIZE_SMALL] + ); + } else { + $result .= Display::return_icon( + 'admin_star_na.png', + get_lang('IsNotAdministrator') + ); + } + + return $result; +} + +/** + * Build the active-column of the table to lock or unlock a certain user + * lock = the user can no longer use this account. + * + * @author Patrick Cool , Ghent University + * + * @param int $active the current state of the account + * @param string $params + * @param array $row + * + * @return string Some HTML-code with the lock/unlock button + */ +function active_filter($active, $params, $row) +{ + $_user = api_get_user_info(); + + if ($active == '1') { + $action = 'Lock'; + $image = 'accept'; + } elseif ($active == '-1') { + $action = 'edit'; + $image = 'warning'; + } elseif ($active == '0') { + $action = 'Unlock'; + $image = 'error'; + } + + $result = ''; + + if ($action === 'edit') { + $result = Display::return_icon( + $image.'.png', + get_lang('AccountExpired'), + [], + 16 + ); + } elseif ($row['0'] != $_user['user_id']) { + // you cannot lock yourself out otherwise you could disable all the + // accounts including your own => everybody is locked out and nobody + // can change it anymore. + $result = Display::return_icon( + $image.'.png', + get_lang(ucfirst($action)), + ['onclick' => 'active_user(this);', 'id' => 'img_'.$row['0']], + 16 + ); + } + + return $result; +} + +/** + * Instead of displaying the integer of the status, we give a translation for the status. + * + * @param int $status + * + * @return string translation + * + * @version march 2008 + * + * @author Patrick Cool , Ghent University, Belgium + */ +function status_filter($status) +{ + $statusname = api_get_status_langvars(); + + return $statusname[$status]; +} + +if (isset($_GET['keyword']) || isset($_GET['keyword_firstname'])) { + $interbreadcrumb[] = ["url" => 'index.php', "name" => get_lang('PlatformAdmin')]; + $interbreadcrumb[] = ["url" => 'user_list.php', "name" => get_lang('UserList')]; + $tool_name = get_lang('SearchUsers'); +} else { + $interbreadcrumb[] = ["url" => 'index.php', "name" => get_lang('PlatformAdmin')]; + $tool_name = get_lang('UserList'); +} + +$message = ''; + +if (!empty($action)) { + $check = Security::check_token('get'); + if ($check) { + switch ($action) { + case 'delete_terms': + $extraFieldValue = new ExtraFieldValue('user'); + $value = $extraFieldValue->get_values_by_handler_and_field_variable( + $_GET['user_id'], + 'legal_accept' + ); + $result = $extraFieldValue->delete($value['id']); + + $value = $extraFieldValue->get_values_by_handler_and_field_variable( + $_GET['user_id'], + 'request_for_legal_agreement_consent_removal' + ); + $result = $extraFieldValue->delete($value['id']); + + Display::addFlash(Display::return_message(get_lang('Deleted'))); + header('Location: '.api_get_self()); + exit; + + break; + case 'delete_user': + $message = UserManager::deleteUserWithVerification($_GET['user_id']); + Display::addFlash($message); + header('Location: '.api_get_self()); + exit; + break; + case 'delete': + if (api_is_platform_admin()) { + $number_of_selected_users = count($_POST['id']); + $number_of_affected_users = 0; + if (is_array($_POST['id'])) { + foreach ($_POST['id'] as $index => $user_id) { + if ($user_id != $_user['user_id']) { + if (UserManager::delete_user($user_id)) { + $number_of_affected_users++; + } + } + } + } + if ($number_of_selected_users == $number_of_affected_users) { + $message = Display::return_message( + get_lang('SelectedUsersDeleted'), + 'confirmation' + ); + } else { + $message = Display::return_message( + get_lang('SomeUsersNotDeleted'), + 'error' + ); + } + } + break; + case 'anonymize': + $message = UserManager::anonymizeUserWithVerification($_GET['user_id']); + Display::addFlash($message); + header('Location: '.api_get_self()); + exit; + break; + } + Security::clear_token(); + } +} + +// Create a search-box +$form = new FormValidator('search_simple', 'get', null, null, null, 'inline'); +$form->addText( + 'keyword', + get_lang('Search'), + false, + [ + 'aria-label' => get_lang("SearchUsers"), + ] +); +$form->addButtonSearch(get_lang('Search')); + +$actionsLeft = ''; +$actionsCenter = ''; +$actionsRight = ''; +$actionsLeft .= $form->returnForm(); + +if (isset($_GET['keyword'])) { + $parameters = ['keyword' => Security::remove_XSS($_GET['keyword'])]; +} elseif (isset($_GET['keyword_firstname'])) { + $parameters['keyword_firstname'] = Security::remove_XSS($_GET['keyword_firstname']); + $parameters['keyword_lastname'] = Security::remove_XSS($_GET['keyword_lastname']); + $parameters['keyword_username'] = Security::remove_XSS($_GET['keyword_username']); + $parameters['keyword_email'] = Security::remove_XSS($_GET['keyword_email']); + $parameters['keyword_officialcode'] = Security::remove_XSS($_GET['keyword_officialcode']); + $parameters['keyword_status'] = Security::remove_XSS($_GET['keyword_status']); + $parameters['keyword_active'] = Security::remove_XSS($_GET['keyword_active']); + $parameters['keyword_inactive'] = Security::remove_XSS($_GET['keyword_inactive']); +} +// Create a sortable table with user-data +$parameters['sec_token'] = Security::get_token(); + +$_admins_list = array_keys(UserManager::get_all_administrators()); +Session::write('admin_list', $_admins_list); +// Display Advanced search form. +$form = new FormValidator( + 'advanced_search', + 'get', + '', + '', + [], + FormValidator::LAYOUT_HORIZONTAL +); + +$form->addElement('html', ''); + +$form = $form->returnForm(); + +$table = new SortableTable( + 'users', + 'get_number_of_users', + 'get_user_data', + (api_is_western_name_order() xor api_sort_by_first_name()) ? 3 : 2 +); +$table->set_additional_parameters($parameters); +$table->set_header(0, '', false, 'width="18px"'); +$table->set_header(1, get_lang('Photo'), false); +$table->set_header(2, get_lang('OfficialCode')); + +if (api_is_western_name_order()) { + $table->set_header(3, get_lang('FirstName')); + $table->set_header(4, get_lang('LastName')); +} else { + $table->set_header(3, get_lang('LastName')); + $table->set_header(4, get_lang('FirstName')); +} +$table->set_header(5, get_lang('LoginName')); +$table->set_header(6, get_lang('Email')); +$table->set_header(7, get_lang('Profile')); +$table->set_header(8, get_lang('Active'), true, 'width="15px"'); +$table->set_header(9, get_lang('RegistrationDate'), true, 'width="90px"'); +$table->set_header(10, get_lang('Action'), false, 'width="220px"'); + +$table->set_column_filter(3, 'user_filter'); +$table->set_column_filter(4, 'user_filter'); +$table->set_column_filter(6, 'email_filter'); +$table->set_column_filter(7, 'status_filter'); +$table->set_column_filter(8, 'active_filter'); +$table->set_column_filter(10, 'modify_filter'); + +// Only show empty actions bar if delete users has been blocked +$actionsList = []; +if (api_is_platform_admin() && + !api_get_configuration_value('deny_delete_users') +) { + $actionsList['delete'] = get_lang('DeleteFromPlatform'); +} +$actionsList['disable'] = get_lang('Disable'); +$actionsList['enable'] = get_lang('Enable'); +$table->set_form_actions($actionsList); + +$table_result = $table->return_table(); +$extra_search_options = ''; +$toolbarActions = Display::toolbarAction( + 'toolbarUser', + [$actionsLeft, $actionsCenter, $actionsRight], + [4, 4, 4] +); + +$notice = Display::return_message(get_lang('InformationRightToBeForgottenText'), 'normal', false); + +$tpl = new Template($tool_name); +$tpl->assign('actions', $toolbarActions); +$tpl->assign('message', $message); +$tpl->assign('content', $form.$table_result.$extra_search_options.$notice); +$tpl->display_one_col_template(); diff --git a/main/auth/inscription.php b/main/auth/inscription.php index 923b95ea8f..7b0ce68d19 100755 --- a/main/auth/inscription.php +++ b/main/auth/inscription.php @@ -898,7 +898,7 @@ if ($form->validate()) { Event::addEvent( LOG_TERM_CONDITION_ACCEPTED, LOG_USER_OBJECT, - api_get_user_info(), + api_get_user_info($user_id), api_get_utc_datetime() ); diff --git a/main/badge/issued.php b/main/badge/issued.php index 3b61f6b975..df9962150e 100644 --- a/main/badge/issued.php +++ b/main/badge/issued.php @@ -3,6 +3,7 @@ use Chamilo\CoreBundle\Entity\SkillRelUser; use Chamilo\CoreBundle\Entity\SkillRelUserComment; +use SkillRelUser as SkillRelUserManager; /** * Show information about the issued badge. @@ -107,7 +108,7 @@ $skillIssueInfo = [ 'skill_short_code' => $skillIssue->getSkill()->getShortCode(), 'skill_description' => $skillIssue->getSkill()->getDescription(), 'skill_criteria' => $skillIssue->getSkill()->getCriteria(), - 'badge_assertion' => $skillIssue->getAssertionUrl(), + 'badge_assertion' => SkillRelUserManager::getAssertionUrl($skillIssue), 'comments' => [], 'feedback_average' => $skillIssue->getAverage(), ]; @@ -120,7 +121,6 @@ $skillId = $skillIssueInfo['skill_id']; /** @var SkillRelUserComment $comment */ foreach ($skillIssueComments as $comment) { $commentDate = api_get_local_time($comment->getFeedbackDateTime()); - $skillIssueInfo['comments'][] = [ 'text' => $comment->getFeedbackText(), 'value' => $comment->getFeedbackValue(), @@ -157,7 +157,6 @@ if (!$profile) { if ($profile) { $profileId = $profile->getId(); - $levels = $skillLevelRepo->findBy([ 'profile' => $profileId, ]); @@ -168,7 +167,6 @@ if ($profile) { } ksort($profileLevels); // Sort the array by Position. - foreach ($profileLevels as $profileLevel) { $profileId = key($profileLevel); $acquiredLevel[$profileId] = $profileLevel[$profileId]; @@ -193,7 +191,7 @@ if ($showLevels && $allowToEdit) { $entityManager->flush(); Display::addFlash(Display::return_message(get_lang('Saved'))); - header("Location: ".$skillIssue->getIssueUrl()); + header('Location: '.SkillRelUserManager::getIssueUrl($skillIssue)); exit; } } @@ -226,7 +224,7 @@ if ($form->validate() && $allowComment && $allowToEdit) { $entityManager->flush(); Display::addFlash(Display::return_message(get_lang('Added'))); - header("Location: ".$skillIssue->getIssueUrl()); + header('Location: '.SkillRelUserManager::getIssueUrl($skillIssue)); exit; } diff --git a/main/badge/issued_all.php b/main/badge/issued_all.php index 477a1cd51a..a1e17f0bde 100644 --- a/main/badge/issued_all.php +++ b/main/badge/issued_all.php @@ -4,6 +4,7 @@ use Chamilo\CoreBundle\Entity\SkillRelUser; use Chamilo\CoreBundle\Entity\SkillRelUserComment; use Chamilo\UserBundle\Entity\User; +use SkillRelUser as SkillRelUserManager; /** * Show information about all issued badges with same skill by user. @@ -14,8 +15,8 @@ use Chamilo\UserBundle\Entity\User; */ require_once __DIR__.'/../inc/global.inc.php'; -$userId = isset($_GET['user']) ? intval($_GET['user']) : 0; -$skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0; +$userId = isset($_GET['user']) ? (int) $_GET['user'] : 0; +$skillId = isset($_GET['skill']) ? (int) $_GET['skill'] : 0; if (!$userId || !$skillId) { api_not_allowed(true); @@ -26,7 +27,6 @@ Skill::isAllowed($userId); $em = Database::getManager(); $user = api_get_user_entity($userId); $skill = $em->find('ChamiloCoreBundle:Skill', $skillId); - $currentUserId = api_get_user_id(); if (!$user || !$skill) { @@ -80,7 +80,10 @@ foreach ($userSkills as $index => $skillIssue) { 'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT), 'acquired_level' => $currentSkillLevel, 'argumentation_author_id' => $skillIssue->getArgumentationAuthorId(), - 'argumentation_author_name' => api_get_person_name($argumentationAuthor['firstname'], $argumentationAuthor['lastname']), + 'argumentation_author_name' => api_get_person_name( + $argumentationAuthor['firstname'], + $argumentationAuthor['lastname'] + ), 'argumentation' => $skillIssue->getArgumentation(), 'source_name' => $skillIssue->getSourceName(), 'user_id' => $skillIssue->getUser()->getId(), @@ -91,7 +94,7 @@ foreach ($userSkills as $index => $skillIssue) { 'skill_short_code' => $skillIssue->getSkill()->getShortCode(), 'skill_description' => $skillIssue->getSkill()->getDescription(), 'skill_criteria' => $skillIssue->getSkill()->getCriteria(), - 'badge_assertion' => $skillIssue->getAssertionUrl(), + 'badge_assertion' => SkillRelUserManager::getAssertionUrl($skillIssue), 'comments' => [], 'feedback_average' => $skillIssue->getAverage(), ]; @@ -156,7 +159,7 @@ foreach ($userSkills as $index => $skillIssue) { $formAcquiredLevel = new FormValidator( 'acquired_level'.$skillIssue->getId(), 'post', - $skillIssue->getIssueUrlAll() + SkillRelUserManager::getIssueUrlAll($skillIssue) ); $formAcquiredLevel->addSelect('acquired_level', get_lang('AcquiredLevel'), $acquiredLevel); $formAcquiredLevel->addHidden('user', $skillIssue->getUser()->getId()); @@ -172,14 +175,14 @@ foreach ($userSkills as $index => $skillIssue) { $em->persist($skillIssue); $em->flush(); - header("Location: ".$skillIssue->getIssueUrlAll()); + header('Location: '.SkillRelUserManager::getIssueUrlAll($skillIssue)); exit; } $form = new FormValidator( 'comment'.$skillIssue->getId(), 'post', - $skillIssue->getIssueUrlAll() + SkillRelUserManager::getIssueUrlAll($skillIssue) ); $form->addTextarea('comment', get_lang('NewComment'), ['rows' => 4]); $form->applyFilter('comment', 'trim'); @@ -207,7 +210,7 @@ foreach ($userSkills as $index => $skillIssue) { $em->persist($skillUserComment); $em->flush(); - header("Location: ".$skillIssue->getIssueUrlAll()); + header('Location: '.SkillRelUserManager::getIssueUrlAll($skillIssue)); exit; } diff --git a/main/cron/lang/langstats.class.php b/main/cron/lang/langstats.class.php index 6d0ad415ac..60c630d125 100755 --- a/main/cron/lang/langstats.class.php +++ b/main/cron/lang/langstats.class.php @@ -139,6 +139,7 @@ class langstats return $this->db->lastInsertRowID(); } } + return true; } diff --git a/main/cron/lang/list_unused_langvars.php b/main/cron/lang/list_unused_langvars.php index 9ff99b3934..68154b99e5 100755 --- a/main/cron/lang/list_unused_langvars.php +++ b/main/cron/lang/list_unused_langvars.php @@ -61,7 +61,6 @@ foreach ($files as $file) { } $usedTerms[$term] = $shortFile; } - } } else { $myTerms = []; diff --git a/main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php b/main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php index 482ccd34be..e07d0d8020 100644 --- a/main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php +++ b/main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php @@ -1311,7 +1311,7 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question .api_get_cidreq() ."&id=$exeId'>"; $exerciseTitle = $objExercise->title; - + $message .= sprintf( get_lang('MessageQuestionCertainty'), $exerciseTitle, diff --git a/main/extra/myStudents.php b/main/extra/myStudents.php index ebedee26c5..55e1192db8 100644 --- a/main/extra/myStudents.php +++ b/main/extra/myStudents.php @@ -64,7 +64,6 @@ if (isset($_GET['from']) && $_GET['from'] == 'myspace') { $this_section = SECTION_COURSES; } - $nameTools = get_lang('StudentDetails'); $em = Database::getManager(); @@ -592,7 +591,7 @@ if (!empty($studentId)) { 'absmiddle', 'hspace' => '3px'] diff --git a/main/inc/lib/api.lib.php b/main/inc/lib/api.lib.php index d10d8b0726..9dded82e33 100644 --- a/main/inc/lib/api.lib.php +++ b/main/inc/lib/api.lib.php @@ -273,6 +273,7 @@ define('LOG_MY_FOLDER_NEW_PATH', 'new_path'); define('LOG_TERM_CONDITION_ACCEPTED', 'term_condition_accepted'); define('LOG_USER_CONFIRMED_EMAIL', 'user_confirmed_email'); +define('LOG_USER_REMOVED_LEGAL_ACCEPT', 'user_removed_legal_accept'); define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/'); @@ -3875,13 +3876,13 @@ function convert_sql_date($last_post_datetime) * the only one that is actually from the session, in case there are results from * session 0 *AND* session n). * - * @param array Course properties array (result of api_get_course_info()) - * @param string Tool (learnpath, document, etc) - * @param int The item ID in the given tool - * @param int The session ID (optional) - * @param string $tool + * @param array $_course Course properties array (result of api_get_course_info()) + * @param string $tool Tool (learnpath, document, etc) + * @param int $id The item ID in the given tool + * @param int $session The session ID (optional) * @param int $user_id * @param string $type + * @param string $group_id * * @return int -1 on error, 0 if invisible, 1 if visible */ @@ -3939,7 +3940,7 @@ function api_get_item_visibility( } $row = Database::fetch_array($res); - return $row['visibility']; + return (int) $row['visibility']; } /** diff --git a/main/inc/lib/formvalidator/FormValidator.class.php b/main/inc/lib/formvalidator/FormValidator.class.php index db9333b0ea..65ef3f17dc 100755 --- a/main/inc/lib/formvalidator/FormValidator.class.php +++ b/main/inc/lib/formvalidator/FormValidator.class.php @@ -296,12 +296,19 @@ EOT; * @param string $name * @param string $label * @param array $attributes + * @param bool $required * * @return HTML_QuickForm_textarea */ - public function addTextarea($name, $label, $attributes = []) + public function addTextarea($name, $label, $attributes = [], $required = false) { - return $this->addElement('textarea', $name, $label, $attributes); + $element = $this->addElement('textarea', $name, $label, $attributes); + + if ($required) { + $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required'); + } + + return $element; } /** diff --git a/main/inc/lib/message.lib.php b/main/inc/lib/message.lib.php index 4510bd621d..9cfa2ed407 100755 --- a/main/inc/lib/message.lib.php +++ b/main/inc/lib/message.lib.php @@ -2598,6 +2598,22 @@ class MessageManager } } + /** + * @param int $senderId + * @param string $subject + * @param string $message + */ + public static function sendMessageToAllAdminUsers( + $senderId, + $subject, + $message + ) { + $admins = UserManager::get_all_administrators(); + foreach ($admins as $admin) { + self::send_message_simple($admin['user_id'], $subject, $message, $senderId); + } + } + /** * Execute the SQL necessary to know the number of messages in the database. * diff --git a/main/inc/lib/skill.lib.php b/main/inc/lib/skill.lib.php index 974bbffb12..3d2c59fd34 100755 --- a/main/inc/lib/skill.lib.php +++ b/main/inc/lib/skill.lib.php @@ -3,6 +3,7 @@ use Chamilo\CoreBundle\Component\Utils\ChamiloApi; use Chamilo\CoreBundle\Entity\Skill as SkillEntity; +use Chamilo\CoreBundle\Entity\SkillRelUser as SkillRelUserEntity; use Chamilo\SkillBundle\Entity\SkillRelCourse; use Chamilo\SkillBundle\Entity\SkillRelItem; use Chamilo\UserBundle\Entity\User; @@ -12,6 +13,8 @@ use Fhaculty\Graph\Vertex; /** * Class SkillProfile. * + * @todo break the file in different classes + * * @package chamilo.library */ class SkillProfile extends Model @@ -614,6 +617,51 @@ class SkillRelUser extends Model 'where' => $where, ], 'first'); } + + /** + * Get the URL for the issue. + * + * @param SkillRelUserEntity $skillIssue + * + * @return string + */ + public static function getIssueUrl(SkillRelUserEntity $skillIssue) + { + return api_get_path(WEB_PATH)."badge/{$skillIssue->getId()}"; + } + + /** + * Get the URL for the All issues page. + * + * @param SkillRelUserEntity $skillIssue + * + * @return string + */ + public static function getIssueUrlAll(SkillRelUserEntity $skillIssue) + { + return api_get_path(WEB_PATH)."skill/{$skillIssue->getSkill()->getId()}/user/{$skillIssue->getUser()->getId()}"; + } + + /** + * Get the URL for the assertion. + * + * @param SkillRelUserEntity $skillIssue + * + * @return string + */ + public static function getAssertionUrl(SkillRelUserEntity $skillIssue) + { + $url = api_get_path(WEB_CODE_PATH).'badge/assertion.php?'; + + $url .= http_build_query([ + 'user' => $skillIssue->getUser()->getId(), + 'skill' => $skillIssue->getSkill()->getId(), + 'course' => $skillIssue->getCourse() ? $skillIssue->getCourse()->getId() : 0, + 'session' => $skillIssue->getSession() ? $skillIssue->getSession()->getId() : 0, + ]); + + return $url; + } } /** diff --git a/main/inc/lib/template.lib.php b/main/inc/lib/template.lib.php index 6bda632326..24ce8cf73d 100755 --- a/main/inc/lib/template.lib.php +++ b/main/inc/lib/template.lib.php @@ -1376,6 +1376,7 @@ class Template { $queryString = empty($_SERVER['QUERY_STRING']) ? '' : $_SERVER['QUERY_STRING']; $requestURI = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI']; + return [ 'web' => api_get_path(WEB_PATH), 'web_url' => api_get_web_url(), diff --git a/main/inc/lib/usermanager.lib.php b/main/inc/lib/usermanager.lib.php index ad24cf8e3f..e7adda5a19 100755 --- a/main/inc/lib/usermanager.lib.php +++ b/main/inc/lib/usermanager.lib.php @@ -6157,6 +6157,98 @@ SQL; return true; } + /** + * @param int $userId + * + * @throws Exception + * + * @return string + */ + public static function anonymizeUserWithVerification($userId) + { + $allowDelete = api_get_configuration_value('allow_delete_user_for_session_admin'); + + $message = ''; + if (api_is_platform_admin() || + ($allowDelete && api_is_session_admin()) + ) { + $userToUpdateInfo = api_get_user_info($userId); + $currentUserId = api_get_user_id(); + + if ($userToUpdateInfo && + api_global_admin_can_edit_admin($userId, null, $allowDelete) + ) { + if ($userId != $currentUserId && + self::anonymize($userId) + ) { + $message = Display::return_message( + sprintf(get_lang('UserXAnonymized'), $userToUpdateInfo['complete_name_with_username']), + 'confirmation' + ); + } else { + $message = Display::return_message( + sprintf(get_lang('CannotAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), + 'error' + ); + } + } else { + $message = Display::return_message( + sprintf(get_lang('NoPermissionToAnonymizeUserX'), $userToUpdateInfo['complete_name_with_username']), + 'error' + ); + } + } + + return $message; + } + + /** + * @param int $userId + * + * @throws Exception + * + * @return string + */ + public static function deleteUserWithVerification($userId) + { + $allowDelete = api_get_configuration_value('allow_delete_user_for_session_admin'); + $deleteUserAvailable = api_get_configuration_value('deny_delete_users'); + + $message = ''; + + if (api_is_platform_admin() || + ($allowDelete && api_is_session_admin()) + ) { + $userToUpdateInfo = api_get_user_info($userId); + $currentUserId = api_get_user_id(); + + if ($userToUpdateInfo && $deleteUserAvailable && + api_global_admin_can_edit_admin($userId, null, $allowDelete) + ) { + if ($userId != $currentUserId && + UserManager::delete_user($userId) + ) { + $message = Display::return_message( + get_lang('UserDeleted').': '.$userToUpdateInfo['complete_name_with_username'], + 'confirmation' + ); + } else { + $message = Display::return_message( + get_lang('CannotDeleteUserBecauseOwnsCourse'), + 'error' + ); + } + } else { + $message = Display::return_message( + get_lang('CannotDeleteUser'), + 'error' + ); + } + } + + return $message; + } + /** * @return EncoderFactory */ diff --git a/main/lp/lp_final_item.php b/main/lp/lp_final_item.php index f4206864ba..44502bc63d 100644 --- a/main/lp/lp_final_item.php +++ b/main/lp/lp_final_item.php @@ -54,7 +54,7 @@ if ($checker) { 'normal', false ), - ''. $url .'' + ''.$url.'' ); $tpl->assign('content', $content); $tpl->display_blank_template(); diff --git a/main/lp/lp_view.php b/main/lp/lp_view.php index 6c2c3a9068..95bb07e833 100755 --- a/main/lp/lp_view.php +++ b/main/lp/lp_view.php @@ -35,7 +35,7 @@ $show_learnpath = true; api_protect_course_script(); -$lp_id = !empty($_GET['lp_id']) ? intval($_GET['lp_id']) : 0; +$lp_id = !empty($_GET['lp_id']) ? (int) $_GET['lp_id'] : 0; $sessionId = api_get_session_id(); $course_code = api_get_course_id(); $course_id = api_get_course_int_id(); @@ -60,8 +60,8 @@ $visibility = api_get_item_visibility( $sessionId ); -if (!api_is_allowed_to_edit(false, true, false, false) && - intval($visibility) == 0 +if ($visibility === 0 && + !api_is_allowed_to_edit(false, true, false, false) ) { api_not_allowed(true); } @@ -113,7 +113,7 @@ if (!$is_allowed_to_edit) { } } -$platform_theme = api_get_setting('stylesheets'); // Platform's css. +$platform_theme = api_get_setting('stylesheets'); $my_style = $platform_theme; $ajaxUrl = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_item_prerequisites&'.api_get_cidreq(); $htmlHeadXtra[] = '