Merge branch '1.11.x' of github.com:chamilo/chamilo-lms into 1.11.x

pull/4973/merge
Yannick Warnier 2 years ago
commit 2ac4d47d10
  1. 1
      app/config/mail.conf.dist.php
  2. 43
      main/admin/add_users_to_usergroup.php
  3. 9
      main/admin/index.php
  4. 2
      main/admin/statistics/index.php
  5. 2
      main/admin/user_import.php
  6. 66
      main/admin/user_list.php
  7. 22
      main/admin/user_move_stats.php
  8. 39
      main/auth/justification.php
  9. 2
      main/course_info/about.php
  10. 13
      main/inc/ajax/announcement.ajax.php
  11. 5
      main/inc/ajax/user_manager.ajax.php
  12. 3
      main/inc/lib/CoursesAndSessionsCatalog.class.php
  13. 10
      main/inc/lib/agenda.lib.php
  14. 52
      main/inc/lib/api.lib.php
  15. 13
      main/inc/lib/course.lib.php
  16. 4
      main/inc/lib/sessionmanager.lib.php
  17. 3
      main/inc/lib/social.lib.php
  18. 3
      main/inc/lib/statistics.lib.php
  19. 91
      main/inc/lib/usermanager.lib.php
  20. 3
      main/inc/lib/userportal.lib.php
  21. 12
      main/install/configuration.dist.php
  22. 5
      main/lp/learnpath.class.php
  23. 1
      main/lp/scorm.class.php
  24. 2
      main/session/about.php
  25. 3
      main/social/search.php
  26. 1
      main/template/default/mail/subject_user_edit.tpl
  27. 4
      main/template/default/user_portal/classic_session.tpl
  28. 2
      plugin/ai_helper/AiHelperPlugin.php
  29. 2
      plugin/ai_helper/src/openai/OpenAi.php
  30. 6
      plugin/justification/Justification.php
  31. 3
      plugin/justification/justification_by_user.php
  32. 4
      plugin/justification/lang/english.php
  33. 4
      plugin/justification/lang/french.php
  34. 4
      plugin/justification/lang/spanish.php
  35. 32
      plugin/justification/list.php
  36. 26
      plugin/zoom/Entity/Meeting.php
  37. 38
      plugin/zoom/Entity/Presenter.php
  38. 3
      plugin/zoom/Entity/Registrant.php
  39. 8
      plugin/zoom/README.md
  40. 4
      plugin/zoom/lang/english.php
  41. 4
      plugin/zoom/lang/french.php
  42. 4
      plugin/zoom/lang/spanish.php
  43. 146
      plugin/zoom/lib/ZoomPlugin.php
  44. 14
      plugin/zoom/meeting.php
  45. 95
      plugin/zoom/view/meeting.tpl
  46. 4
      tests/scripts/ldap_encrypt_admin_password.php

@ -40,6 +40,7 @@ $platform_email['DKIM_SELECTOR'] = 'chamilo'; // an indicator of the application
$platform_email['DKIM_DOMAIN'] = 'mydomain.com'; //the domain for e-mail sending, not necessarily api_get_path(WEB_PATH)
$platform_email['DKIM_PRIVATE_KEY_STRING'] = ''; //the private key in a string format
$platform_email['DKIM_PRIVATE_KEY'] = ''; //the private key as the path to a file. The file needs to be accessible to PHP!
$platform_email['DKIM_PASSPHRASE'] = ''; //the passohrase for the private key defined in the last 2 lines
// Some e-mail clients do not understand the descriptive LD+JSON format,
// showing it as a loose JSON string to the final user. If this is your case,
// you might want to set the variable below to 'false' to disable this header.

@ -25,6 +25,7 @@ $interbreadcrumb[] = ['url' => 'usergroups.php', 'name' => get_lang('Classes')];
// setting the name of the tool
$tool_name = get_lang('SubscribeUsersToClass');
$showAllStudentByDefault = api_get_configuration_value('usergroup_add_user_show_all_student_by_default');
$htmlHeadXtra[] = '
<script>
@ -35,6 +36,11 @@ $(function () {
});
});
function activeUsers(originalUrl) {
var searchValue = document.getElementById("first_letter_user").value;
window.location.href = originalUrl + "&firstLetterUser=" + encodeURIComponent(searchValue);
}
function add_user_to_session (code, content) {
document.getElementById("user_to_add").value = "";
document.getElementById("ajax_list_users_single").innerHTML = "";
@ -87,7 +93,7 @@ function change_select(reset) {
if (reset) {
document.formulaire["first_letter_user"].value = "";
if ('.(api_get_configuration_value('usergroup_add_user_show_all_student_by_default') ? 0 : 1).') {
if ('.($showAllStudentByDefault ? 0 : 1).') {
document.formulaire["form_sent"].value = "1";
return;
@ -129,10 +135,10 @@ if (empty($id)) {
$first_letter_user = '';
if (isset($_POST['form_sent']) && $_POST['form_sent']) {
if ((isset($_POST['form_sent']) && $_POST['form_sent']) || isset($_REQUEST['firstLetterUser'])) {
$form_sent = $_POST['form_sent'];
$elements_posted = $_POST['elements_in_name'] ?? null;
$first_letter_user = $_POST['firstLetterUser'];
$first_letter_user = Security::remove_XSS($_REQUEST['firstLetterUser']);
if (!is_array($elements_posted)) {
$elements_posted = [];
@ -247,7 +253,9 @@ if (!empty($first_letter_user) && strlen($first_letter_user) >= 3) {
}
$activeUser = isset($_REQUEST['active_users']) ? (int) $_REQUEST['active_users'] : null;
$conditions['active'] = $activeUser;
if (1 === $activeUser) {
$conditions['active'] = $activeUser;
}
$filterData = [];
if ($searchForm->validate()) {
@ -268,7 +276,7 @@ $hideElementsIn = [];
foreach ($list_in as $listedUserId) {
$userInfo = api_get_user_info($listedUserId);
if (isset($activeUser) && ((int) $activeUser != $userInfo['active'])) {
if (1 === $activeUser && empty($userInfo['active'])) {
$hideElementsIn[] = $listedUserId;
continue;
}
@ -279,7 +287,7 @@ foreach ($list_in as $listedUserId) {
$user_with_any_group = !empty($_REQUEST['user_with_any_group']);
$user_list = [];
if (!empty($conditions)) {
if (!(!$showAllStudentByDefault && !isset($_POST['firstLetterUser']) && !isset($_REQUEST['active_users'])) && !$user_with_any_group) {
$user_list = UserManager::getUserListLike($conditions, $order, true, 'OR');
}
@ -306,17 +314,16 @@ if (!empty($user_list)) {
continue;
}
if (isset($activeUser) && ((int) $activeUser != $item['active'])) {
continue;
}
if (!in_array($item['user_id'], $list_in)) {
$elements_not_in[$item['user_id']] = formatCompleteName($item, $orderListByOfficialCode);
}
}
}
if (api_get_configuration_value('usergroup_add_user_show_all_student_by_default')
if (!$showAllStudentByDefault && !isset($_POST['firstLetterUser']) && !isset($_REQUEST['active_users'])) {
$elements_not_in = [];
}
if ($showAllStudentByDefault
&& empty($elements_not_in)
&& empty($first_letter_user)
) {
@ -362,13 +369,13 @@ echo '<a href="usergroup_user_import.php">'.
echo '<a href="'.api_get_self().'?id='.$id.'&action=export">'.
Display::return_icon('export_csv.png', get_lang('Export'), [], ICON_SIZE_MEDIUM).'</a>';
$newUrl = api_get_self().'?id='.$id.'&active_users=1';
$buttonLabel = get_lang('OnlyShowActiveUsers');
if ($activeUser) {
$buttonLabel = get_lang('ShowAllUsers') ;
$newUrl = api_get_self().'?id='.$id;
}
echo '<a href="' . htmlspecialchars($newUrl) . '" class="btn btn-default">' . $buttonLabel . '</a>';
$isActiveUser = !empty($activeUser);
$activeUsersParam = $isActiveUser ? '0' : '1';
$newUrl = api_get_self() . '?id=' . $id . '&active_users=' . $activeUsersParam;
$buttonLabelKey = $isActiveUser ? 'ShowAllUsers' : 'OnlyShowActiveUsers';
$buttonLabel = get_lang($buttonLabelKey);
echo '<a href="#" onclick="activeUsers(\'' . htmlspecialchars($newUrl) . '\'); return false;" class="btn btn-default">' . $buttonLabel . '</a>';
echo '</div>';

@ -194,6 +194,15 @@ if (api_is_platform_admin()) {
return !in_array($item['url'], $urls);
});
}
$allowJustification = ((api_get_plugin_setting('justification', 'tool_enable') === 'true') && (api_get_plugin_setting('justification', 'access_for_session_admin') === 'true'));
if ($allowJustification) {
$items[] = [
'class' => 'item-justification-list',
'url' => api_get_path(WEB_PLUGIN_PATH).'justification/list.php',
'label' => get_lang('Justification'),
];
}
}
if (api_get_configuration_value('allow_session_admin_extra_access')) {

@ -1501,7 +1501,7 @@ switch ($report) {
foreach ($intervals as $minutes) {
$sql = "SELECT count(distinct(user_id))
FROM $table WHERE
DATE_ADD(tms, INTERVAL '$minutes' MINUTE) > UTC_TIMESTAMP()";
tms > DATE_SUB(UTC_TIMESTAMP(), INTERVAL '$minutes' MINUTE)";
$query = Database::query($sql);
$counts[$minutes] = 0;
if (Database::num_rows($query) > 0) {

@ -153,6 +153,8 @@ function validate_data($users, $checkUniqueEmail = false)
} else {
$userFromEmail = api_get_user_info_from_email($user['Email']);
if (!empty($userFromEmail)) {
$user['id'] = $userFromEmail['id'];
$user['UserName'] = $userFromEmail['username'];
$user['message'] .= Display::return_message(get_lang('EmailUsedTwice'), 'warning');
$user['has_error'] = true;
} else {

@ -476,22 +476,44 @@ function get_user_data($from, $number_of_items, $column, $direction)
$user[7] = '-1';
}
}
// forget about the expiration date field
$users[] = [
$user[0], // id
$photo,
$user[1],
$user[2],
$user[3],
$user[4], // username
$user[5], // email
$user[6],
$user[7], // active
api_get_local_time($user[8]),
api_get_local_time($user[9], null, null, true),
$user[0],
];
if (api_get_configuration_value('admin_user_list_add_first_connexion_column')) {
$firstConnectionDate = Tracking::get_first_connection_date($user[0]);
if ($firstConnectionDate == '') {
$firstConnectionDate = get_lang('NoConnexion');
}
// forget about the expiration date field
$users[] = [
$user[0], // id
$photo,
$user[1],
$user[2],
$user[3],
$user[4], // username
$user[5], // email
$user[6],
$user[7], // active
api_get_local_time($user[8]),
api_get_local_time($user[9], null, null, true),
$firstConnectionDate,
$user[0],
];
} else {
// forget about the expiration date field
$users[] = [
$user[0], // id
$photo,
$user[1],
$user[2],
$user[3],
$user[4], // username
$user[5], // email
$user[6],
$user[7], // active
api_get_local_time($user[8]),
api_get_local_time($user[9], null, null, true),
$user[0],
];
}
}
return $users;
@ -542,7 +564,7 @@ function modify_filter($user_id, $url_params, $row)
$is_admin = in_array($user_id, $_admins_list);
$statusname = api_get_status_langvars();
$user_is_anonymous = false;
$current_user_status_label = $row['7'];
$current_user_status_label = $statusname[$row['7']];
if ($current_user_status_label == $statusname[ANONYMOUS]) {
$user_is_anonymous = true;
@ -1077,14 +1099,20 @@ $table->set_header(7, get_lang('Profile'));
$table->set_header(8, get_lang('Active'));
$table->set_header(9, get_lang('RegistrationDate'));
$table->set_header(10, get_lang('LatestLogin'));
$table->set_header(11, get_lang('Action'), false);
if (api_get_configuration_value('admin_user_list_add_first_connexion_column')) {
$table->set_header(11, get_lang('FirstLoginInPlatform'), false);
$table->set_header(12, get_lang('Action'), false);
$table->set_column_filter(12, 'modify_filter');
} else {
$table->set_header(11, get_lang('Action'), false);
$table->set_column_filter(11, 'modify_filter');
}
$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, [UserManager::class, 'getActiveFilterForTable']);
$table->set_column_filter(11, 'modify_filter');
// Hide email column if login is email, to avoid column with same data
if (api_get_setting('login_is_email') === 'true') {

@ -60,12 +60,14 @@ if (isset($_REQUEST['load_ajax'])) {
echo 'User added to the session';
}
// Registering user to the new session
SessionManager::subscribeUsersToSession(
$new_session_id,
[$user_id],
false,
false
);
if ($update_database) {
SessionManager::subscribeUsersToSession(
$new_session_id,
[$user_id],
false,
false
);
}
}
$course_info = api_get_course_info($origin_course_code);
@ -247,8 +249,8 @@ if (!empty($user_list)) {
echo '<tr>';
foreach ($course_list as $course) {
echo '<td>';
if (isset($course['id_session']) && !empty($course['id_session'])) {
echo '<b>'.get_lang('SessionName').'</b> '.$my_session_list[$course['id_session']].'<br />';
if (isset($course['session_id']) && !empty($course['session_id'])) {
echo '<b>'.get_lang('SessionName').'</b> '.$my_session_list[$course['session_id']].'<br />';
}
echo $course['name'];
echo ' ('.$course['code'].') ';
@ -262,10 +264,10 @@ if (!empty($user_list)) {
foreach ($course_list as $course) {
$course_code = $course['code'];
if (empty($course['id_session'])) {
if (empty($course['session_id'])) {
$session_id = 0;
} else {
$session_id = $course['id_session'];
$session_id = $course['session_id'];
}
echo '<td>';
echo get_lang('MoveTo');

@ -83,19 +83,32 @@ $action = isset($_REQUEST['a']) ? $_REQUEST['a'] : '';
$justificationContent = '';
switch ($action) {
case 'notify_justification':
// notification to all admins action
$userInfo = api_get_user_info();
// get_all_administrators
$adminList = UserManager::get_all_administrators();
$link = api_get_path(WEB_PATH).'plugin/justification/justification_by_user.php?user_id='.api_get_user_id();
$emailToAdminSubject = $plugin->get_lang('JustificationsCompleted').': '.$userInfo['complete_name'];
$emailToAdminContent = $emailToAdminSubject.' <br /><br />'.'<a href="'.$link.'">'.$link.'</a>';
foreach ($adminList as $adminId => $data) {
MessageManager::send_message_simple(
$adminId,
$emailToAdminSubject,
$emailToAdminContent,
api_get_user_id());
$link = api_get_path(WEB_PATH).'plugin/justification/justification_by_user.php?user_id='.api_get_user_id();
$notificationEmailSubject = $plugin->get_lang('JustificationsCompleted').': '.$userInfo['complete_name'];
$notificationEmailContent = $notificationEmailSubject.' <br /><br />'.'<a href="'.$link.'">'.$link.'</a>';
if (api_get_plugin_setting('justification', 'notification_to_creator_only') === 'true') {
$sql = "select creator_id from user where user_id = " . api_get_user_id();
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
$row = Database::fetch_array($result);
$sendToAllAdmins = false;
MessageManager::send_message_simple(
$row['creator_id'],
$notificationEmailSubject,
$notificationEmailContent,
api_get_user_id());
}
}
if ($sendToAllAdmins) {
// get_all_administrators
$adminList = UserManager::get_all_administrators();
foreach ($adminList as $adminId => $data) {
MessageManager::send_message_simple(
$adminId,
$notificationEmailSubject,
$notificationEmailContent,
api_get_user_id());
}
}
Display::addFlash(Display::return_message(get_lang('MessageSent')));
header('Location: '.api_get_self().'?a=notification_sent');

@ -18,7 +18,7 @@ $cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
if (api_get_setting('course_catalog_published') != 'true' && api_is_anonymous()) {
if ((api_get_setting('course_catalog_published') != 'true' && api_is_anonymous()) || api_get_configuration_value('course_about_block_all_access') == 'true') {
api_not_allowed(true);
}

@ -14,6 +14,7 @@ $courseCode = api_get_course_id();
$courseId = api_get_course_int_id();
$groupId = api_get_group_id();
$sessionId = api_get_session_id();
$currentUserId = api_get_user_id();
$isTutor = false;
if (!empty($groupId)) {
@ -26,9 +27,13 @@ if (!empty($groupId)) {
switch ($action) {
case 'preview':
$userInCourse = false;
if (CourseManager::is_user_subscribed_in_course($currentUserId, CourseManager::get_course_code_from_course_id($courseId), $sessionId)) {
$userInCourse = true;
}
$allowToEdit = (
api_is_allowed_to_edit(false, true) ||
(api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous()) ||
(api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous() && $userInCourse) ||
($sessionId && api_is_coach() && api_get_configuration_value('allow_coach_to_edit_announcements'))
);
@ -47,7 +52,11 @@ switch ($action) {
// Last chance ... students can send announcements.
if ($groupProperties['announcements_state'] == GroupManager::TOOL_PRIVATE_BETWEEN_USERS) {
$allowToEdit = true;
// check if user is a group member to give access
$groupInfo = GroupManager::get_group_properties($groupId);
if (array_key_exists($currentUserId,GroupManager::get_subscribed_users($groupInfo))) {
$allowToEdit = true;
}
}
}

@ -96,7 +96,7 @@ switch ($action) {
echo json_encode($dates);
break;
case 'get_user_like':
if (api_is_platform_admin() || api_is_drh()) {
if (api_is_platform_admin() || api_is_drh() || api_is_session_admin()) {
$query = $_REQUEST['q'];
$conditions = [
'username' => $query,
@ -121,7 +121,8 @@ switch ($action) {
$courseId = (int) $request->get('course_id');
$sessionId = (int) $request->get('session_id');
$userId = (int) $request->get('user_id');
$hash = (string) $request->get('hash');
$userId = (int) UserManager::decryptUserHash($hash);
$user_info = api_get_user_info($userId);

@ -1780,6 +1780,7 @@ class CoursesAndSessionsCatalog
$plugin = \BuyCoursesPlugin::create();
$isThisSessionOnSale = $plugin->getBuyCoursePluginPrice($session);
$userIdHash = UserManager::generateUserHash($coachId);
$sessionsBlock = [
'id' => $session->getId(),
'name' => $session->getName(),
@ -1788,7 +1789,7 @@ class CoursesAndSessionsCatalog
'nbr_users' => $session->getNbrUsers(),
'coach_id' => $coachId,
'coach_url' => $generalCoach
? api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$coachId
? api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash
: '',
'coach_name' => $coachName,
'coach_avatar' => UserManager::getUserPicture($coachId, USER_IMAGE_SIZE_SMALL),

@ -5219,10 +5219,12 @@ class Agenda
foreach ($invitation->getInvitees() as $invitee) {
$inviteeUser = $invitee->getUser();
$eventInfo['invitees'][] = [
'id' => $inviteeUser->getId(),
'name' => $inviteeUser->getCompleteNameWithUsername(),
];
if (!is_null($inviteeUser)) {
$eventInfo['invitees'][] = [
'id' => $inviteeUser->getId(),
'name' => $inviteeUser->getCompleteNameWithUsername(),
];
}
}
}

@ -1820,7 +1820,8 @@ function _api_format_user($user, $add_password = false, $loadAvatars = true)
$result['profile_url'] = api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user_id;
// Send message link
$sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$user_id;
$userIdHash = UserManager::generateUserHash($user_id);
$sendMessage = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash;
$result['complete_name_with_message_link'] = Display::url(
$result['complete_name_with_username'],
$sendMessage,
@ -9774,6 +9775,9 @@ function api_mail_html(
}
$mail->DKIM_private_string = api_get_mail_configuration_value('DKIM_PRIVATE_KEY_STRING');
$mail->DKIM_private = api_get_mail_configuration_value('DKIM_PRIVATE_KEY');
if (!empty(api_get_mail_configuration_value['DKIM_PASSPHRASE'])) {
$mail->DKIM_passphrase = api_get_mail_configuration_value['DKIM_PASSPHRASE'];
}
}
// Send the mail message.
@ -10615,9 +10619,22 @@ function api_decrypt_ldap_password(string $encryptedText): string
} else {
return false;
}
$secret = hex2bin($secret);
$iv = base64_decode(substr($encryptedText, 0, 16), true);
$data = base64_decode(substr($encryptedText, 16), true);
return api_decrypt_hash($encryptedText,$secret);
}
/**
* Decrypt sent hash encoded with secret
*
* @param $encryptedText The hash text to be decrypted
* @param $secret The secret used to encoded the hash
*
* @return string The decrypted text or false
*/
function api_decrypt_hash(string $encryptedHash, string $secret): string
{
$iv = base64_decode(substr($encryptedHash, 0, 16), true);
$data = base64_decode(substr($encryptedHash, 16), true);
$tag = substr($data, strlen($data) - 16);
$data = substr($data, 0, strlen($data) - 16);
@ -10634,3 +10651,30 @@ function api_decrypt_ldap_password(string $encryptedText): string
return false;
}
}
/**
* Encrypt sent data with secret
*
* @param $data The text to be encrypted
* @param $secret The secret to use encode data
*
* @return string The encrypted text or false
*/
function api_encrypt_hash($data, $secret)
{
$iv = random_bytes(12);
$tag = '';
$encrypted = openssl_encrypt(
$data,
'aes-256-gcm',
$secret,
OPENSSL_RAW_DATA,
$iv,
$tag,
'',
16
);
return base64_encode($iv) . base64_encode($encrypted . $tag);
}

@ -2222,7 +2222,8 @@ class CourseManager
$userPicture = UserManager::getUserPicture($teacher['user_id'], USER_IMAGE_SIZE_SMALL);
$teachers['avatar'] = $userPicture;
}
$teachers['url'] = $url.'&user_id='.$teacher['user_id'];
$userIdHash = UserManager::generateUserHash($teacher['user_id']);
$teachers['url'] = $url.'&hash='.$userIdHash;
$listTeachers[] = $teachers;
}
@ -2255,7 +2256,8 @@ class CourseManager
$teacher['lastname']
);
if ($add_link_to_profile) {
$url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$teacher['user_id'];
$userIdHash = UserManager::generateUserHash($teacher['user_id']);
$url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash;
$teacher_name = Display::url(
$teacher_name,
$url,
@ -2337,7 +2339,9 @@ class CourseManager
$row['avatar'] = $loadAvatars
? UserManager::getUserPicture($row['user_id'], USER_IMAGE_SIZE_SMALL)
: '';
$row['url'] = "$url&user_id={$row['user_id']}";
$userIdHash = UserManager::generateUserHash($row['user_id']);
$row['url'] = $url.'&hash='.$userIdHash;
$row['hash'] = $userIdHash;
$coaches[] = $row;
}
@ -2368,7 +2372,8 @@ class CourseManager
foreach ($coachList as $coach_course) {
$coach_name = $coach_course['full_name'];
if ($add_link_to_profile) {
$url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$coach_course['user_id'].'&course_id='.$courseId.'&session_id='.$session_id;
$userIdHash = UserManager::generateUserHash($coach_course['user_id']);
$url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash.'&course_id='.$courseId.'&session_id='.$session_id;
$coach_name = Display::url(
$coach_name,
$url,

@ -491,6 +491,10 @@ class SessionManager
$userId = (int) $userId;
if (!api_is_platform_admin() && !api_is_session_admin() && !api_is_teacher()) {
api_not_allowed(true);
}
if (!api_is_platform_admin()) {
if (api_is_session_admin() &&
'false' === api_get_setting('allow_session_admins_to_manage_all_sessions')

@ -1220,9 +1220,10 @@ class SocialManager extends UserManager
'new-message.png',
$sendMessageText
);
$userIdHash = UserManager::generateUserHash($user_id);
$sendMessageUrl = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?'.http_build_query([
'a' => 'get_user_popup',
'user_id' => $user_id,
'hash' => $userIdHash,
]);
$links .= '<li>';

@ -415,9 +415,10 @@ class Statistics
}
// User id.
$userIdHash = UserManager::generateUserHash($row[6]);
$row[5] = Display::url(
$row[5],
api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&user_id='.$row[6],
api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash,
['class' => 'ajax']
);

@ -577,7 +577,9 @@ class UserManager
false,
false,
false
);
);
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
$layoutSubject = $tplSubject->get_template('mail/subject_registration_platform.tpl');
$emailSubject = $tplSubject->fetch($layoutSubject);
$sender_name = api_get_person_name(
@ -1742,7 +1744,18 @@ class UserManager
$tplContent->assign('status_type', $status);
$creatorInfo = api_get_user_info($creator_id);
$creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : '';
$emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
$tplSubject = new Template(
null,
false,
false,
false,
false,
false
);
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
$layoutSubject = $tplSubject->get_template('mail/subject_user_edit.tpl');
$emailSubject = $tplSubject->fetch($layoutSubject);
if (!is_null($password) && api_get_configuration_value('send_two_inscription_confirmation_mail')) {
// The user has a new password *and* we need to tell him so,
@ -1765,7 +1778,7 @@ class UserManager
api_mail_html(
$recipient_name,
$email,
$emailsubject,
$emailSubject,
$emailBody,
$sender_name,
$email_admin,
@ -1793,7 +1806,7 @@ class UserManager
api_mail_html(
$recipient_name,
$email,
$emailsubject,
$emailSubject,
$emailBody,
$sender_name,
$email_admin,
@ -1821,7 +1834,7 @@ class UserManager
api_mail_html(
$recipient_name,
$email,
$emailsubject,
$emailSubject,
$emailBody,
$sender_name,
$email_admin,
@ -2394,6 +2407,13 @@ class UserManager
$sql_query .= ' WHERE 1 = 1 ';
if (count($conditions) > 0) {
$andActive = "";
if (isset($conditions['active'])) {
$andActive = " AND active = " . (int) $conditions['active'];
unset($conditions['active']);
}
$temp_conditions = [];
foreach ($conditions as $field => $value) {
$field = Database::escape_string($field);
@ -2405,18 +2425,23 @@ class UserManager
}
}
if (!empty($temp_conditions)) {
$sql_query .= ' AND '.implode(' '.$condition.' ', $temp_conditions);
$sql_query .= ' AND ('.implode(' '.$condition.' ', $temp_conditions).') ';
}
if (api_is_multiple_url_enabled()) {
$sql_query .= ' AND auru.access_url_id = '.api_get_current_access_url_id();
}
$sql_query .= $andActive;
} else {
if (api_is_multiple_url_enabled()) {
$sql_query .= ' AND auru.access_url_id = '.api_get_current_access_url_id();
}
}
if (api_is_session_admin() && (api_get_setting('prevent_session_admins_to_manage_all_users') === 'true')) {
$sql_query .= ' AND user.creator_id = '.api_get_user_id();
}
if (!empty($onlyThisUserList)) {
$onlyThisUserListToString = implode("','", $onlyThisUserList);
$sql_query .= " AND user.id IN ('$onlyThisUserListToString') ";
@ -7842,10 +7867,18 @@ SQL;
public static function getAllowedRolesAsTeacher(): array
{
return [
COURSEMANAGER,
SESSIONADMIN,
];
if (api_get_configuration_value('course_allow_student_role_to_be_teacher')) {
return [
STUDENT,
COURSEMANAGER,
SESSIONADMIN,
];
} else {
return [
COURSEMANAGER,
SESSIONADMIN,
];
}
}
/**
@ -8188,4 +8221,42 @@ SQL;
return $url;
}
/**
* return user hash based on user_id and loggedin user's salt
*
* @param int user_id id of the user for whom we need the hash
*
* @return string containing the hash
*/
public static function generateUserHash(int $user_id): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return rawurlencode(api_encrypt_hash($user_id, $user->getSalt()));
}
/**
* return decrypted hash or false
*
* @param string hash hash that is to be decrypted
*
* @return string
*/
public static function decryptUserHash(string $hash): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return api_decrypt_hash(rawurldecode($hash), $user->getSalt());
}
}

@ -2033,8 +2033,9 @@ class IndexManager
$params['category_id'] = $session_box['category_id'];
$params['title'] = $session_box['title'];
$params['id_coach'] = $coachId;
$userIdHash = UserManager::generateUserHash($coachId);
$params['coach_url'] = api_get_path(WEB_AJAX_PATH).
'user_manager.ajax.php?a=get_user_popup&user_id='.$coachId;
'user_manager.ajax.php?a=get_user_popup&hash='.$userIdHash;
$params['coach_name'] = !empty($session_box['coach']) ? $session_box['coach'] : null;
$params['coach_avatar'] = UserManager::getUserPicture(
$coachId,

@ -2521,3 +2521,15 @@ INSERT INTO extra_field_options (field_id, option_value, display_text, priority,
// login/passwords in the main login form. Browsers might choose not to
// support this feature.
//$_configuration['security_login_autocomplete_disable'] = false;
// Block session about page access for all users
// $_configuration['session_about_block_all_access'] = false;
// Block course about page access for all users
// $_configuration['course_about_block_all_access'] = false;
// Add the user first connexion column to the page main/admin/user_list.php
// $_configuration['admin_user_list_add_first_connexion_column'] = false;
// Set the following parameter to true to enable student to be assign as teacher of a course
//$_configuration['course_allow_student_role_to_be_teacher'] = false;

@ -1138,6 +1138,11 @@ class learnpath
// Updates the display order of all lps.
$this->update_display_order();
// Remove prerequisite based on the deleted LP
$sql = "UPDATE $lp
SET prerequisite = 0 where c_id = $course_id AND prerequisite = ".$this->lp_id;
Database::query($sql);
api_item_property_update(
api_get_course_info(),
TOOL_LEARNPATH,

@ -771,6 +771,7 @@ class scorm extends learnpath
}
$zipFile->extract(
PCLZIP_OPT_REPLACE_NEWER,
PCLZIP_CB_PRE_EXTRACT,
$callBack
);

@ -20,7 +20,7 @@ $cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
if (api_get_setting('course_catalog_published') != 'true' && api_is_anonymous()) {
if ((api_get_setting('course_catalog_published') != 'true' && api_is_anonymous()) || api_get_configuration_value('session_about_block_all_access') == 'true') {
api_not_allowed(true);
}

@ -98,9 +98,10 @@ if ($query != '' || ($query_vars['search_type'] == '1' && count($query_vars) > 2
<em class="fa fa-user"></em> '.get_lang('SendInvitation').'</a>';
}
$userIdHash = UserManager::generateUserHash($user_info['user_id']);
$sendMessageUrl = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?'.http_build_query([
'a' => 'get_user_popup',
'user_id' => $user_info['user_id'],
'hash' => $userIdHash,
]);
$sendMessage = Display::toolbarButton(

@ -0,0 +1 @@
{{ '[' ~ _s.site_name ~ '] ' ~ 'YourReg'|get_lang ~ ' ' ~ _s.site_name }}

@ -119,7 +119,7 @@
<img src="{{ 'teacher.png'|icon(16) }}" width="16" height="16">
{% for coach in item.coaches %}
{{ loop.index > 1 ? ' | ' }}
<a href="{{ _p.web_ajax ~ 'user_manager.ajax.php?' ~ {'a': 'get_user_popup', 'user_id': coach.user_id, 'session_id': row.id, 'course_id': item.real_id }|url_encode() }}"
<a href="{{ _p.web_ajax ~ 'user_manager.ajax.php?' ~ {'a': 'get_user_popup', 'hash': coach.hash, 'session_id': row.id, 'course_id': item.real_id }|url_encode() }}"
data-title="{{ coach.full_name }}" class="ajax">
{{ coach.firstname }}, {{ coach.lastname }}
</a>
@ -186,4 +186,4 @@
<!-- end view simple info -->
{% endif %}
</div>
{% endfor %}
{% endfor %}

@ -76,7 +76,7 @@ class AiHelperPlugin extends Plugin
$ai = new OpenAi($apiKey, $organizationId);
$temperature = 0.2;
$model = 'text-davinci-003';
$model = 'gpt-3.5-turbo-instruct';
$maxTokens = 2000;
$frequencyPenalty = 0;
$presencePenalty = 0.6;

@ -5,7 +5,7 @@ require_once 'OpenAiUrl.php';
class OpenAi
{
private $model = "text-davinci-003"; // See https://platform.openai.com/docs/models for possible models
private $model = "gpt-3.5-turbo-instruct"; // See https://platform.openai.com/docs/models for possible models
private $headers;
private $contentTypes;
private $timeout = 0;

@ -6,10 +6,12 @@ class Justification extends Plugin
protected function __construct()
{
parent::__construct(
'1.1',
'Julio Montoya',
'1.2',
'Julio Montoya, Nicolas Ducoulombier',
[
'tool_enable' => 'boolean',
'notification_to_creator_only' => 'boolean',
'access_for_session_admin' => 'boolean',
'default_course_id' => 'text',
]
);

@ -3,7 +3,8 @@
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$allowSessionAdmins = api_get_plugin_setting('justification', 'access_for_session_admin') === 'true';
api_protect_admin_script($allowSessionAdmins);
$tool = 'justification';
$plugin = Justification::create();

@ -21,3 +21,7 @@ $strings['JustificationDate'] = "Justification date";
$strings['DocumentListForUserX'] = "Document list of user %s";
$strings['JustificationsCompleted'] = "Justifications completed";
$strings['SendNotificationToAllAdmins'] = "Send a notification to the administrator";
$strings['notification_to_creator_only'] = "Send notification to user's creator only";
$strings['notification_to_creator_only_help'] = "If activated then the notification will be sent only to the user who created the user who send the justifications and not to all admins";
$strings['access_for_session_admin'] = "Enable session admins to manage users in plugin";
$strings['access_for_session_admin_help'] = "If activated it enables session admins to access the plugin and the user's list and justification management.";

@ -21,3 +21,7 @@ $strings['SubscribeToASession'] = "S'inscrire à une session d'examen";
$strings['DocumentListForUserX'] = "Liste des documents pour %s";
$strings['JustificationsCompleted'] = "Dossier complété";
$strings['SendNotificationToAllAdmins'] = "Envoyer une notification à l'administrateur";
$strings['notification_to_creator_only'] = "Envoyer la notification uniquement au créateur";
$strings['notification_to_creator_only_help'] = "Si cette option est activée alors la notification est envoyée uniquement à l'utilisateur qui a créé l'utilisateur qui envoie les justificatifs et non à tous les admins de la plateforme";
$strings['access_for_session_admin'] = "Permettre aux administrateurs de session de gérer les utilisateurs dans le plugin";
$strings['access_for_session_admin_help'] = "Si activé alors les administrateurs de session peuvent accéder au plugin et à la liste des utilisateurs et la gestion de leurs justificatifs.";

@ -21,3 +21,7 @@ $strings['SubscribeToASession'] = "Inscribirse a una sesion de examen";
$strings['DocumentListForUserX'] = "Lista de documentos para %s";
$strings['JustificationsCompleted'] = "justificativos completados";
$strings['SendNotificationToAllAdmins'] = "Enviar una notificación al administrador";
$strings['notification_to_creator_only'] = "Enviar la notificación solo al creador del usuario";
$strings['notification_to_creator_only_help'] = "Si esta opción esta activada entonces la notificación sera enviada solo al usuario que ha creado el usuario quien envia sus justificativo";
$strings['access_for_session_admin'] = "Permitir a los administradores de sesión gestionar los usuarios en el plugin";
$strings['access_for_session_admin_help'] = "Si activado entonces los administradores de sesión pueden acceder al plugin y a la lista de usuarios y gestionar sus justificativos.";

@ -3,7 +3,8 @@
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script();
$allowSessionAdmins = api_get_plugin_setting('justification', 'access_for_session_admin') === 'true';
api_protect_admin_script($allowSessionAdmins);
$tool = 'justification';
$plugin = Justification::create();
@ -31,12 +32,15 @@ switch ($action) {
break;
}
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Add'),
api_get_path(WEB_PLUGIN_PATH).'justification/add.php',
'plus',
'primary'
);
if (api_is_platform_admin()) {
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Add'),
api_get_path(WEB_PLUGIN_PATH).'justification/add.php',
'plus',
'primary'
);
}
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('Users'),
api_get_path(WEB_PLUGIN_PATH).'justification/justification_by_user.php',
@ -44,12 +48,14 @@ $actionLinks .= Display::toolbarButton(
'primary'
);
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('SetNewCourse'),
api_get_path(WEB_PLUGIN_PATH).'justification/set_course.php',
'book',
'primary'
);
if (api_is_platform_admin()) {
$actionLinks .= Display::toolbarButton(
$plugin->get_lang('SetNewCourse'),
api_get_path(WEB_PLUGIN_PATH).'justification/set_course.php',
'book',
'primary'
);
}
$tpl->assign(
'actions',

@ -245,7 +245,31 @@ class Meeting
*/
public function getRegistrants()
{
return $this->registrants;
return $this->registrants->filter(function (Registrant $registrant) {
return !$registrant instanceof Presenter;
});
}
/**
* @return ArrayCollection<int, Presenter>
*/
public function getPresenters(): ArrayCollection
{
return $this->registrants->filter(function (Registrant $registrant) {
return $registrant instanceof Presenter;
});
}
public function hasUserAsPresenter(User $user): bool
{
$presenters = $this->getPresenters();
$criteria = Criteria::create();
$criteria->where(
Criteria::expr()->eq('user', $user)
);
return $presenters->matching($criteria)->count() > 0;
}
/**

@ -0,0 +1,38 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Zoom;
use Doctrine\ORM\Mapping as ORM;
use Exception;
/**
* @ORM\Entity()
* @ORM\HasLifecycleCallbacks()
*/
class Presenter extends Registrant
{
public function __toString()
{
return sprintf('Presenter %d', $this->id);
}
/**
* @ORM\PostLoad()
*
* @throws Exception
*/
public function postLoad()
{
parent::postLoad();
}
/**
* @ORM\PreFlush()
*/
public function preFlush()
{
parent::preFlush();
}
}

@ -23,6 +23,9 @@ use Exception;
* }
* )
* @ORM\HasLifecycleCallbacks
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({"registrant" = "Chamilo\PluginBundle\Zoom\Registrant", "presenter" = "Chamilo\PluginBundle\Zoom\Presenter"})
*/
class Registrant
{

@ -97,6 +97,14 @@ a generic account that works for all the users that start meetings.
Please, execute this queries in your database:
**Updatnig to v0.6 from v.0.5**
```sql
UPDATE plugin_zoom_registrant SET type = 'registrant';
ALTER TABLE plugin_zoom_registrant
ADD type VARCHAR(255) NOT NULL;
```
**Updating to v0.5 from v.0.4**
```sql

@ -21,6 +21,8 @@ $strings[ZoomPlugin::SETTING_CLIENT_SECRET.'_help'] = 'For a Server-to-Server OA
$strings[ZoomPlugin::SETTING_SECRET_TOKEN] = 'Secret token';
$strings[ZoomPlugin::SETTING_SECRET_TOKEN.'_help'] = 'For a Server-to-Server OAuth application type';
$strings['enableParticipantRegistration'] = 'Enable participant registration';
$strings['enablePresenter'] = 'Enable presenter';
$strings['enablePresenter_help'] = 'It requires that <i>Enable participant registration</i> settings is enabled.';
$strings['enableCloudRecording'] = 'Automatic recording type';
$strings['enableGlobalConference'] = 'Enable global conference';
$strings['enableGlobalConferencePerUser'] = 'Enable global conference per user';
@ -132,6 +134,7 @@ $strings['RecurringWithNoFixedTime'] = "Recurring with no fixed time";
$strings['RegisterAllCourseUsers'] = "Register all course users";
$strings['RegisteredUserListWasUpdated'] = "Registered user list updated";
$strings['RegisteredUsers'] = "Registered users";
$strings['RegisteredPresenters'] = "Registered presenters";
$strings['RegisterNoUser'] = "Register no user";
$strings['RegisterTheseGroupMembers'] = "Register these group members";
$strings['ScheduleAMeeting'] = "Schedule a meeting";
@ -185,3 +188,4 @@ $strings['WebinarDeleted'] = "Webinar deleted";
$strings['UrlForSelfRegistration'] = "URL for self registration";
$strings['RegisterMeToConference'] = "Register me to conference";
$strings['UnregisterMeToConference'] = "Unregister me to conference";
$strings['Presenters'] = "Presenters";

@ -167,3 +167,7 @@ $strings['RegisterMeToConference'] = "M'inscrire à la visio";
$strings['UnregisterMeToConference'] = "Me désinscrire de la visio";
$strings['ForEveryone'] = "Tout le monde";
$strings['SomeUsers'] = "Utilisateurs inscrits (à inscrire après)";
$strings['Presenters'] = "Animateurs";
$strings['RegisteredPresenters'] = "Animateurs enregistrés";
$strings['enablePresenter_help'] = "Il est nécessaire que l'option <i>Activer l'inscription des participants</i> soit sur Oui.";
$strings['enablePresenter'] = 'Activer les animateurs';

@ -9,6 +9,8 @@ $strings['tool_enable'] = 'Herramienta activada';
$strings['apiKey'] = "Clave API (<em>API Key</em>)";
$strings['apiSecret'] = "Código secreto de API (<em>API Secret</em>)";
$strings['enableParticipantRegistration'] = "Activar la inscripción de participantes";
$strings['enablePresenter'] = 'Activar presentadores';
$strings['enablePresenter_help'] = 'Requiere que el parametro <i>Activar la inscripción de participantes</i> este activado.';
$strings['enableCloudRecording'] = "Tipo de grabación automática";
$strings['enableGlobalConference'] = "Activar las conferencias globales";
$strings['enableGlobalConferencePerUser'] = "Activar las conferencias globales por usuario";
@ -119,6 +121,7 @@ $strings['RecurringWithNoFixedTime'] = "Recurrente, sin hora fija";
$strings['RegisterAllCourseUsers'] = "Inscribir todos los usuarios del curso";
$strings['RegisteredUserListWasUpdated'] = "Lista de usuarios inscritos actualizada";
$strings['RegisteredUsers'] = "Usuarios inscritos";
$strings['RegisteredPresenters'] = "Presentadores registrados";
$strings['RegisterNoUser'] = "No inscribir ningún usuario";
$strings['RegisterTheseGroupMembers'] = "Inscribir los miembros de estos grupos";
$strings['ScheduleAMeeting'] = "Programar una conferencia";
@ -168,3 +171,4 @@ $strings['WebinarDeleted'] = "Seminario web borrado";
$strings['UrlForSelfRegistration'] = "URL para auto registro";
$strings['RegisterMeToConference'] = "Registrarme a la conferencia";
$strings['UnregisterMeToConference'] = "Cancelar registro a la conferencia";
$strings['Presenters'] = "Presentadores";

@ -19,6 +19,7 @@ use Chamilo\PluginBundle\Zoom\API\WebinarSettings;
use Chamilo\PluginBundle\Zoom\Meeting;
use Chamilo\PluginBundle\Zoom\MeetingActivity;
use Chamilo\PluginBundle\Zoom\MeetingRepository;
use Chamilo\PluginBundle\Zoom\Presenter;
use Chamilo\PluginBundle\Zoom\Recording;
use Chamilo\PluginBundle\Zoom\RecordingRepository;
use Chamilo\PluginBundle\Zoom\Registrant;
@ -59,7 +60,7 @@ class ZoomPlugin extends Plugin
public function __construct()
{
parent::__construct(
'0.5',
'0.6',
'Sébastien Ducoulombier, Julio Montoya, Angel Fernando Quiroz Campos',
[
'tool_enable' => 'boolean',
@ -71,6 +72,7 @@ class ZoomPlugin extends Plugin
self::SETTING_CLIENT_SECRET => 'text',
self::SETTING_SECRET_TOKEN => 'text',
'enableParticipantRegistration' => 'boolean',
'enablePresenter' => 'boolean',
'enableCloudRecording' => [
'type' => 'select',
'options' => [
@ -623,6 +625,60 @@ class ZoomPlugin extends Plugin
return $form;
}
public function getRegisterPresenterForm(Meeting $meeting): FormValidator
{
$form = new FormValidator('register_presenter', 'post', $_SERVER['REQUEST_URI']);
$presenterIdSelect = $form->addSelect('presenterIds', $this->get_lang('RegisteredPresenters'));
$presenterIdSelect->setMultiple(true);
$form->addButtonSend($this->get_lang('UpdateRegisteredUserList'));
$users = $meeting->getRegistrableUsers();
foreach ($users as $user) {
$presenterIdSelect->addOption(
api_get_person_name($user->getFirstname(), $user->getLastname()),
$user->getId()
);
}
if ($form->validate()) {
$selectedPresenterIds = $form->getSubmitValue('presenterIds') ?: [];
$selectedPresenters = [];
foreach ($users as $user) {
if (in_array($user->getId(), $selectedPresenterIds)) {
$selectedPresenters[] = $user;
}
}
try {
$this->updatePresenterList($meeting, $selectedPresenters);
Display::addFlash(
Display::return_message($this->get_lang('RegisteredUserListWasUpdated'), 'confirm')
);
} catch (Exception $exception) {
Display::addFlash(
Display::return_message($exception->getMessage(), 'error')
);
}
}
$registeredPresenterIds = [];
foreach ($meeting->getPresenters() as $registrant) {
if ($registrant instanceof Presenter) {
$registeredPresenterIds[] = $registrant->getUser()->getId();
}
}
$presenterIdSelect->setSelected($registeredPresenterIds);
return $form;
}
/**
* Generates a meeting recording files management form.
* Takes action on validation.
@ -1250,6 +1306,16 @@ class ZoomPlugin extends Plugin
return true;
}
$currentUser = api_get_user_entity(api_get_user_id());
if ('true' === $this->get('enableParticipantRegistration')
&& 'true' === $this->get('enablePresenter')
&& $currentUser
&& $meeting->hasUserAsPresenter($currentUser)
) {
return true;
}
return $meeting->isUserMeeting() && $meeting->getUser()->getId() == api_get_user_id();
}
@ -1559,6 +1625,32 @@ class ZoomPlugin extends Plugin
return $failedUsers;
}
/**
* @param Meeting $meeting
* @param array<User> $users
*
* @throws OptimisticLockException
* @throws \Doctrine\ORM\ORMException
*
* @return array
*/
public function registerPresenters(Meeting $meeting, array $users): array
{
$failedUsers = [];
foreach ($users as $user) {
try {
$this->registerUser($meeting, $user, false, true);
} catch (Exception $exception) {
$failedUsers[$user->getId()] = $exception->getMessage();
}
}
Database::getManager()->flush();
return $failedUsers;
}
/**
* Removes registrants from a meeting.
*
@ -1626,13 +1718,55 @@ class ZoomPlugin extends Plugin
$this->unregister($meeting, $registrantsToRemove);
}
private function updatePresenterList($meeting, $users)
{
/** @var array<Registrant> $presenters */
$presenters = $meeting->getPresenters();
$presenterToAdd = [];
foreach ($users as $user) {
$foundPresenter = false;
foreach ($presenters as $presenter) {
if ($presenter->getUser() === $user) {
$foundPresenter = true;
break;
}
}
if (!$foundPresenter) {
$presenterToAdd[] = $user;
}
}
$registrantsToRemove = [];
foreach ($presenters as $registrant) {
$found = false;
foreach ($users as $user) {
if ($registrant->getUser() === $user) {
$found = true;
break;
}
}
if (!$found) {
$registrantsToRemove[] = $registrant;
}
}
$this->registerPresenters($meeting, $presenterToAdd);
$this->unregister($meeting, $registrantsToRemove);
}
/**
* @throws Exception
* @throws OptimisticLockException
*
* @return Registrant
*/
private function registerUser(Meeting $meeting, User $user, $andFlush = true)
private function registerUser(Meeting $meeting, User $user, $andFlush = true, bool $isPresenter = false)
{
if (empty($user->getEmail())) {
throw new Exception($this->get_lang('CannotRegisterWithoutEmailAddress'));
@ -1652,7 +1786,13 @@ class ZoomPlugin extends Plugin
);
}
$registrantEntity = (new Registrant())
$registrantEntity = new Registrant();
if ($isPresenter) {
$registrantEntity = new Presenter();
}
$registrantEntity
->setMeeting($meeting)
->setUser($user)
->setMeetingRegistrant($meetingRegistrant)

@ -3,6 +3,7 @@
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Zoom\Meeting;
use Chamilo\PluginBundle\Zoom\Registrant;
use Chamilo\PluginBundle\Zoom\Webinar;
require_once __DIR__.'/config.php';
@ -65,11 +66,20 @@ if ($plugin->userIsConferenceManager($meeting)) {
$tpl->assign('deleteMeetingForm', $plugin->getDeleteMeetingForm($meeting, $returnURL)->returnForm());
}
if (false === $meeting->isGlobalMeeting() && false == $meeting->isCourseMeeting()) {
if ('true' === $plugin->get('enableParticipantRegistration') && $meeting->requiresRegistration()) {
$pluginEnableParticipantRegistration = 'true' === $plugin->get('enableParticipantRegistration');
if ($pluginEnableParticipantRegistration && $meeting->requiresRegistration()) {
if (false === $meeting->isGlobalMeeting()
&& false == $meeting->isCourseMeeting()
) {
$tpl->assign('registerParticipantForm', $plugin->getRegisterParticipantForm($meeting)->returnForm());
$tpl->assign('registrants', $meeting->getRegistrants());
}
if ('true' === $plugin->get('enablePresenter') && !$meeting->isCourseMeeting()) {
$tpl->assign('registerPresenterForm', $plugin->getRegisterPresenterForm($meeting)->returnForm());
$tpl->assign('presenters', $meeting->getPresenters());
}
}
if (ZoomPlugin::RECORDING_TYPE_NONE !== $plugin->getRecordingSetting() &&

@ -69,45 +69,68 @@
<hr>
{{ registerParticipantForm }}
{% endif %}
{% if registerPresenterForm %}
{{ registerPresenterForm }}
{% endif %}
{{ fileForm }}
{# {% if registrants and meeting.meetingInfoGet.settings.approval_type != 2 %}#}
{% if registrants.count > 0 %}
<script>
function copyJoinURL(event, url) {
event.target.textContent = '{{ 'CopyingJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}';
navigator.clipboard.writeText(url).then(
function() {
event.target.textContent = '{{ 'JoinURLCopied'|get_plugin_lang('ZoomPlugin')|escape }}';
}, function() {
event.target.textContent = '{{ 'CouldNotCopyJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}' + ' ' + url;
<div class="row">
<div class="col-m6">
{% if presenters %}
<h3>{{ 'Presenters'|get_plugin_lang('ZoomPlugin') }}</h3>
<table class="table">
{% for presenter in presenters %}
<tr>
<td>
{{ presenter.fullName }}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
<div class="col-m6">
{# {% if registrants and meeting.meetingInfoGet.settings.approval_type != 2 %}#}
{% if registrants.count > 0 %}
<script>
function copyJoinURL(event, url) {
event.target.textContent = '{{ 'CopyingJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}';
navigator.clipboard.writeText(url).then(
function() {
event.target.textContent = '{{ 'JoinURLCopied'|get_plugin_lang('ZoomPlugin')|escape }}';
}, function() {
event.target.textContent = '{{ 'CouldNotCopyJoinURL'|get_plugin_lang('ZoomPlugin')|escape }}' + ' ' + url;
}
);
}
);
}
</script>
<h3>{{ 'Users' | get_lang }}</h3>
<br />
<table class="table">
{% for registrant in registrants %}
<tr>
<td>
{{ registrant.fullName }}
</td>
<td>
{# {% if registrant.joinUrl %}#}
{# <a class="btn btn-primary" onclick="copyJoinURL(event, '{{ registrant.joinUrl }}')">#}
{# {{ 'CopyJoinAsURL'|get_plugin_lang('ZoomPlugin') }}#}
{# </a>#}
{# {% else %}#}
{# <a class="btn btn-primary disabled" >#}
{# {{ 'JoinURLNotAvailable'|get_plugin_lang('ZoomPlugin') }}#}
{# </a>#}
{# {% endif %}#}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</script>
<h3>{{ 'Users' | get_lang }}</h3>
<br />
<table class="table">
{% for registrant in registrants %}
<tr>
<td>
{{ registrant.fullName }}
</td>
<td>
{# {% if registrant.joinUrl %}#}
{# <a class="btn btn-primary" onclick="copyJoinURL(event, '{{ registrant.joinUrl }}')">#}
{# {{ 'CopyJoinAsURL'|get_plugin_lang('ZoomPlugin') }}#}
{# </a>#}
{# {% else %}#}
{# <a class="btn btn-primary disabled" >#}
{# {{ 'JoinURLNotAvailable'|get_plugin_lang('ZoomPlugin') }}#}
{# </a>#}
{# {% endif %}#}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
</div>
{% else %}
{% include 'zoom/view/meeting_details.tpl' %}
{% endif %}

@ -24,8 +24,8 @@ if (!empty($argv[1])) {
exit();
}
if (!empty(api_get_configuration_value('ldap_encrypt_admin_password'))) {
echo "The encrypted password is : " . encrypt(api_get_configuration_value('ldap_encrypt_admin_password'), $password) .PHP_EOL;
if (!empty(api_get_configuration_value('ldap_admin_password_salt'))) {
echo "The encrypted password is : " . encrypt(api_get_configuration_value('ldap_admin_password_salt'), $password) .PHP_EOL;
} else {
echo "There is no salt defined in app/config/configuration.php for variable 'ldap_admin_password_salt'".PHP_EOL.PHP_EOL;
}

Loading…
Cancel
Save