parent
791a25abe9
commit
ece1d3a1b3
@ -0,0 +1,662 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use ChamiloSession as Session; |
||||
|
||||
/** |
||||
* @author Bart Mollet |
||||
* @author Julio Montoya <gugli100@gmail.com> 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; |
||||
|
||||
$extraFields = UserManager::createDataPrivacyExtraFields(); |
||||
Session::write('data_privacy_extra_fields', $extraFields); |
||||
|
||||
/** |
||||
* 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, |
||||
v.field_id |
||||
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)"; |
||||
} |
||||
|
||||
$extraFields = Session::read('data_privacy_extra_fields'); |
||||
$extraFieldId = $extraFields['delete_legal']; |
||||
$extraFieldIdDeleteAccount = $extraFields['delete_account_extra_field']; |
||||
|
||||
$extraFieldValue = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
||||
$sql .= " INNER JOIN $extraFieldValue v |
||||
ON ( |
||||
u.id = v.item_id AND |
||||
(field_id = $extraFieldId OR field_id = $extraFieldIdDeleteAccount) AND |
||||
v.value = 1 |
||||
) "; |
||||
|
||||
$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(); |
||||
} |
||||
|
||||
// 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 = (int) $from; |
||||
$number_of_items = (int) $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 = '<img |
||||
src="'.$userPicture.'" width="22" height="22" |
||||
alt="'.api_get_person_name($user[2], $user[3]).'" |
||||
title="'.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[12], |
||||
$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 '<a href="'.api_get_path(WEB_PATH).'whoisonline.php?origin=user_list&id='.$row[0].'">'.$name.'</a>'; |
||||
} |
||||
|
||||
function requestTypeFilter($fieldId, $url_params, $row) |
||||
{ |
||||
$extraFields = Session::read('data_privacy_extra_fields'); |
||||
$extraFieldId = $extraFields['delete_legal']; |
||||
|
||||
if ($fieldId == $extraFieldId) { |
||||
return get_lang('DeleteLegal'); |
||||
} else { |
||||
return get_lang('DeleteAccount'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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 .= '<a href="user_information.php?user_id='.$user_id.'">'. |
||||
Display::return_icon('synthese_view.gif', get_lang('Info')).'</a> '; |
||||
|
||||
$result .= Display::url( |
||||
Display::return_icon('message_new.png'), |
||||
api_get_path(WEB_CODE_PATH).'messages/new_message.php?send_to_user='.$user_id |
||||
); |
||||
$result .= ' '; |
||||
$extraFields = Session::read('data_privacy_extra_fields'); |
||||
$extraFieldId = $extraFields['delete_legal']; |
||||
|
||||
if ($row[10] == $extraFieldId) { |
||||
$result .= Display::url( |
||||
get_lang('RemoveTerms'), |
||||
api_get_self().'?user_id='.$user_id.'&action=delete_terms&sec_token='.$token |
||||
); |
||||
$result .= ' '; |
||||
} |
||||
|
||||
$result .= ' <a href="'.api_get_self().'?action=anonymize&user_id='.$user_id.'&'.$url_params.'&sec_token='.$token.'" onclick="javascript:if(!confirm('."'".addslashes( |
||||
api_htmlentities(get_lang('ConfirmYourChoice')) |
||||
)."'".')) return false;">'. |
||||
Display::return_icon( |
||||
'anonymous.png', |
||||
get_lang('Anonymize'), |
||||
[], |
||||
ICON_SIZE_SMALL |
||||
). |
||||
'</a>'; |
||||
|
||||
if ($user_id != api_get_user_id()) { |
||||
$result .= ' <a href="'.api_get_self().'?action=delete_user&user_id='.$user_id.'&'.$url_params.'&sec_token='.$token.'" onclick="javascript:if(!confirm('."'".addslashes( |
||||
api_htmlentities(get_lang('ConfirmYourChoice')) |
||||
)."'".')) return false;">'. |
||||
Display::return_icon( |
||||
'delete.png', |
||||
get_lang('Delete'), |
||||
[], |
||||
ICON_SIZE_SMALL |
||||
). |
||||
'</a>'; |
||||
} |
||||
|
||||
$editProfileUrl = Display::getProfileEditionLink($user_id, true); |
||||
|
||||
$result .= '<a href="'.$editProfileUrl.'">'. |
||||
Display::return_icon( |
||||
'edit.png', |
||||
get_lang('Edit'), |
||||
[], |
||||
ICON_SIZE_SMALL |
||||
). |
||||
'</a> '; |
||||
|
||||
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 <patrick.cool@UGent.be>, 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 <patrick.cool@UGent.be>, 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_consent.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', '<div id="advanced_search_form" style="display:none;">'); |
||||
$form->addElement('header', get_lang('AdvancedSearch')); |
||||
$form->addText('keyword_firstname', get_lang('FirstName'), false); |
||||
$form->addText('keyword_lastname', get_lang('LastName'), false); |
||||
$form->addText('keyword_username', get_lang('LoginName'), false); |
||||
$form->addText('keyword_email', get_lang('Email'), false); |
||||
$form->addText('keyword_officialcode', get_lang('OfficialCode'), false); |
||||
|
||||
$status_options = []; |
||||
$status_options['%'] = get_lang('All'); |
||||
$status_options[STUDENT] = get_lang('Student'); |
||||
$status_options[COURSEMANAGER] = get_lang('Teacher'); |
||||
$status_options[DRH] = get_lang('Drh'); |
||||
$status_options[SESSIONADMIN] = get_lang('SessionsAdmin'); |
||||
$status_options[PLATFORM_ADMIN] = get_lang('Administrator'); |
||||
|
||||
$form->addElement( |
||||
'select', |
||||
'keyword_status', |
||||
get_lang('Profile'), |
||||
$status_options |
||||
); |
||||
$form->addButtonSearch(get_lang('SearchUsers')); |
||||
|
||||
$defaults = []; |
||||
$defaults['keyword_active'] = 1; |
||||
$defaults['keyword_inactive'] = 1; |
||||
$form->setDefaults($defaults); |
||||
$form->addElement('html', '</div>'); |
||||
|
||||
$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('RequestType'), true, 'width="15px"'); |
||||
$table->set_header(11, 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(11, 'modify_filter'); |
||||
$table->set_column_filter(10, 'requestTypeFilter'); |
||||
|
||||
// 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(); |
@ -0,0 +1,321 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* @package chamilo.admin |
||||
*/ |
||||
$cidReset = true; |
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
|
||||
$this_section = SECTION_PLATFORM_ADMIN; |
||||
|
||||
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0; |
||||
|
||||
$usergroup = new UserGroup(); |
||||
$userGroupInfo = $usergroup->get($id); |
||||
|
||||
if (empty($userGroupInfo)) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$usergroup->protectScript($userGroupInfo); |
||||
|
||||
$calendarPlugin = null; |
||||
if (api_get_plugin_setting('learning_calendar', 'enabled') === 'true') { |
||||
$calendarPlugin = LearningCalendarPlugin::create(); |
||||
} |
||||
|
||||
// Add the JS needed to use the jqgrid |
||||
$htmlHeadXtra[] = api_get_jqgrid_js(); |
||||
$action = isset($_GET['action']) ? Security::remove_XSS($_GET['action']) : null; |
||||
$userId = isset($_GET['user_id']) ? (int) $_GET['user_id'] : 0; |
||||
$calendarId = isset($_REQUEST['calendar_id']) ? (int) $_REQUEST['calendar_id'] : 0; |
||||
|
||||
// setting breadcrumbs |
||||
$interbreadcrumb[] = ['url' => 'usergroups.php', 'name' => get_lang('Classes')]; |
||||
$interbreadcrumb[] = ['url' => '#', 'name' => $userGroupInfo['name']]; |
||||
|
||||
switch ($action) { |
||||
case 'add_calendar': |
||||
$form = new FormValidator( |
||||
'add_calendar', |
||||
'post', |
||||
api_get_self().'?id='.$id.'&user_id='.$userId.'&action=add_calendar' |
||||
); |
||||
|
||||
$userInfo = api_get_user_info($userId); |
||||
$form->addHeader($userInfo['complete_name']); |
||||
$calendarPlugin->getAddUserToCalendarForm($form); |
||||
$form->addButtonSave(get_lang('Add')); |
||||
$form->display(); |
||||
|
||||
if ($form->validate()) { |
||||
$calendarId = $form->getSubmitValue('calendar_id'); |
||||
if (!empty($calendarId)) { |
||||
$calendarPlugin->addUserToCalendar($calendarId, $userId); |
||||
Display::addFlash(Display::return_message(get_lang('Added'), 'confirmation')); |
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
} |
||||
} |
||||
exit; |
||||
break; |
||||
case 'edit_calendar': |
||||
$form = new FormValidator( |
||||
'add_calendar', |
||||
'post', |
||||
api_get_self().'?id='.$id.'&user_id='.$userId.'&action=edit_calendar&calendar_id='.$calendarId |
||||
); |
||||
$userInfo = api_get_user_info($userId); |
||||
$form->addHeader($userInfo['complete_name']); |
||||
$calendarPlugin->getAddUserToCalendarForm($form); |
||||
$form->setDefaults(['calendar_id' => $calendarId]); |
||||
$form->addButtonSave(get_lang('Update')); |
||||
$form->display(); |
||||
|
||||
if ($form->validate()) { |
||||
$calendarId = $form->getSubmitValue('calendar_id'); |
||||
if (!empty($calendarId)) { |
||||
$calendarPlugin->updateUserToCalendar($calendarId, $userId); |
||||
Display::addFlash(Display::return_message(get_lang('Added'), 'confirmation')); |
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
} |
||||
} |
||||
exit; |
||||
break; |
||||
case 'delete': |
||||
$res = $usergroup->delete_user_rel_group($_GET['user_id'], $_GET['id']); |
||||
Display::addFlash(Display::return_message(get_lang('Deleted'), 'confirmation')); |
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
break; |
||||
case 'create_control_point': |
||||
$value = isset($_GET['value']) ? (int) $_GET['value'] : 0; |
||||
$calendarPlugin->addControlPoint($userId, $value); |
||||
Display::addFlash( |
||||
Display::return_message($calendarPlugin->get_lang('ControlPointAdded'), 'confirmation') |
||||
); |
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
case 'add_multiple_users_to_calendar': |
||||
$userList = isset($_REQUEST['user_list']) ? explode(',', $_REQUEST['user_list']) : 0; |
||||
foreach ($userList as $userId) { |
||||
$isAdded = $calendarPlugin->addUserToCalendar($calendarId, $userId); |
||||
if (!$isAdded) { |
||||
$isAdded = $calendarPlugin->updateUserToCalendar($calendarId, $userId); |
||||
} |
||||
} |
||||
|
||||
Display::addFlash( |
||||
Display::return_message(get_lang('Added'), 'confirmation') |
||||
); |
||||
|
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
break; |
||||
} |
||||
|
||||
Display::display_header(); |
||||
|
||||
// jqgrid will use this URL to do the selects |
||||
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_usergroups_users&id='.$id; |
||||
|
||||
// The order is important you need to check the the $column variable in the model.ajax.php file |
||||
$columns = [ |
||||
get_lang('Name'), |
||||
get_lang('Actions'), |
||||
]; |
||||
|
||||
// Column config |
||||
$column_model = [ |
||||
['name' => 'name', 'index' => 'name', 'width' => '35', 'align' => 'left', 'sortable' => 'false'], |
||||
[ |
||||
'name' => 'actions', |
||||
'index' => 'actions', |
||||
'width' => '20', |
||||
'align' => 'center', |
||||
'sortable' => 'false', |
||||
'formatter' => 'action_formatter', |
||||
], |
||||
]; |
||||
|
||||
if (api_get_plugin_setting('learning_calendar', 'enabled') === 'true') { |
||||
$columns = [ |
||||
get_lang('Name'), |
||||
get_lang('Calendar'), |
||||
get_lang('ClassroomActivity'), |
||||
get_lang('TimeSpentByStudentsInCourses'), |
||||
$calendarPlugin->get_lang('NumberDaysAccumulatedInCalendar'), |
||||
$calendarPlugin->get_lang('DifferenceOfDaysAndCalendar'), |
||||
get_lang('Actions'), |
||||
]; |
||||
|
||||
// Column config |
||||
$column_model = [ |
||||
['name' => 'name', 'index' => 'name', 'width' => '35', 'align' => 'left', 'sortable' => 'false'], |
||||
[ |
||||
'name' => 'calendar', |
||||
'index' => 'calendar', |
||||
'width' => '35', |
||||
'align' => 'left', |
||||
'sortable' => 'false', |
||||
'formatter' => 'extra_formatter', |
||||
], |
||||
[ |
||||
'name' => 'gradebook_items', |
||||
'index' => 'gradebook_items', |
||||
'width' => '35', |
||||
'align' => 'left', |
||||
'sortable' => 'false', |
||||
], |
||||
['name' => 'time_spent', 'index' => 'time_spent', 'width' => '35', 'align' => 'left', 'sortable' => 'false'], |
||||
[ |
||||
'name' => 'lp_day_completed', |
||||
'index' => 'lp_day_completed', |
||||
'width' => '35', |
||||
'align' => 'left', |
||||
'sortable' => 'false', |
||||
], |
||||
['name' => 'days_diff', 'index' => 'days_diff', 'width' => '35', 'align' => 'left', 'sortable' => 'false'], |
||||
[ |
||||
'name' => 'actions', |
||||
'index' => 'actions', |
||||
'width' => '20', |
||||
'align' => 'center', |
||||
'sortable' => 'false', |
||||
'formatter' => 'action_formatter', |
||||
], |
||||
]; |
||||
} |
||||
|
||||
// Autowidth |
||||
$extraParams['autowidth'] = 'true'; |
||||
// height auto |
||||
$extraParams['height'] = 'auto'; |
||||
$extraParams['sortname'] = 'name'; |
||||
$extraParams['sortorder'] = 'desc'; |
||||
$extraParams['multiselect'] = true; |
||||
|
||||
$deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), null, ICON_SIZE_SMALL); |
||||
$urlStats = api_get_path(WEB_CODE_PATH); |
||||
|
||||
//$addCalendar = '<a href="'.$urlStats.'mySpace/myStudents.php?student=\'+options.rowId+\'">'.Display::return_icon('agenda.png', get_lang('Agenda'), '', ICON_SIZE_SMALL).'</a>'; |
||||
|
||||
$reportingIcon = Display::return_icon('stats.png', get_lang('Reporting'), '', ICON_SIZE_SMALL); |
||||
$controlPoint = Display::return_icon('add.png', get_lang('ControlPoint'), '', ICON_SIZE_SMALL); |
||||
|
||||
//return \'<a href="session_edit.php?page=resume_session.php&id=\'+options.rowId+\'">'.Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL).'</a>'. |
||||
// With this function we can add actions to the jgrid |
||||
$action_links = ' |
||||
function action_formatter(cellvalue, options, rowObject) { |
||||
var value = rowObject[5]; |
||||
return \''. |
||||
' <a href="'.$urlStats.'admin/usergroup_users.php?action=create_control_point&value=\'+value+\'&id='.$id.'&user_id=\'+options.rowId+\'">'.$controlPoint.'</a>'. |
||||
' <a href="'.$urlStats.'mySpace/myStudents.php?student=\'+options.rowId+\'">'.$reportingIcon.'</a>'. |
||||
' <a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."\'".')) return false;" href="?id='.$id.'&action=delete&user_id=\'+options.rowId+\'">'.$deleteIcon.'</a>\'; |
||||
} |
||||
|
||||
function extra_formatter(cellvalue, options, rowObject) { |
||||
var calendarName = rowObject[1]; |
||||
var calendarId = rowObject[7]; |
||||
|
||||
if (calendarName == "") { |
||||
return \'<a href="'. |
||||
api_get_path(WEB_CODE_PATH).'admin/usergroup_users.php?user_id=\'+options.rowId+\'&id='.$id.'&action=add_calendar&width=700" class="btn btn-primary ajax">'.get_lang('Add').'</a>\'; |
||||
} else { |
||||
return \' \'+calendarName+\' <a href="'. |
||||
api_get_path(WEB_CODE_PATH).'admin/usergroup_users.php?calendar_id=\'+calendarId+\'&user_id=\'+options.rowId+\'&id='.$id.'&action=edit_calendar&width=700" class="btn btn-primary ajax"> '.get_lang('Edit').'</a>\'; |
||||
} |
||||
|
||||
return calendarName; |
||||
|
||||
return \''. |
||||
' <a href="'.$urlStats.'mySpace/myStudents.php?student=\'+options.rowId+\'">'.Display::return_icon('stats.png', get_lang('Reporting'), '', ICON_SIZE_SMALL).'</a>'. |
||||
' <a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES))."\'".')) return false;" href="?id='.$id.'&action=delete&user_id=\'+options.rowId+\'">'.$deleteIcon.'</a>\'; |
||||
}'; |
||||
|
||||
$deleteUrl = api_get_path(WEB_AJAX_PATH).'usergroup.ajax.php?a=delete_user_in_usergroup&group_id='.$id; |
||||
|
||||
$form = new FormValidator( |
||||
'add_multiple_calendar', |
||||
'post', |
||||
api_get_self().'?id='.$id.'&action=add_multiple_users_to_calendar' |
||||
); |
||||
$calendarPlugin->getAddUserToCalendarForm($form); |
||||
$form->addHidden('user_list', ''); |
||||
$form->addButtonSave(get_lang('Add')); |
||||
|
||||
?> |
||||
<script> |
||||
$(function() { |
||||
<?php |
||||
// grid definition see the $usergroup>display() function |
||||
echo Display::grid_js( |
||||
'usergroups', |
||||
$url, |
||||
$columns, |
||||
$column_model, |
||||
$extraParams, |
||||
[], |
||||
$action_links, |
||||
true |
||||
); |
||||
?> |
||||
$("#usergroups").jqGrid( |
||||
"navGrid", |
||||
"#usergroups_pager", |
||||
{ edit: false, add: false, del: true, search: false}, |
||||
{ height:280, reloadAfterSubmit:false }, // edit options |
||||
{ height:280, reloadAfterSubmit:false }, // add options |
||||
{ reloadAfterSubmit:false, url: "<?php echo $deleteUrl; ?>" }, // del options
|
||||
{ width:500 } // search options |
||||
) |
||||
.navButtonAdd('#usergroups_pager',{ |
||||
caption:"<?php echo addslashes($calendarPlugin->get_lang('UpdateCalendar')); ?>",
|
||||
buttonicon:"ui-icon ui-icon-plus", |
||||
onClickButton: function(a) { |
||||
var userIdList = $("#usergroups").jqGrid('getGridParam', 'selarrrow'); |
||||
if (userIdList.length) { |
||||
$(".modal-body #add_multiple_calendar_user_list").val(userIdList); |
||||
$('#myModal').modal(); |
||||
} else { |
||||
alert("<?php echo addslashes(get_lang('SelectStudents')); ?>");
|
||||
} |
||||
}, |
||||
position:"last" |
||||
}); |
||||
}); |
||||
</script> |
||||
|
||||
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> |
||||
<div class="modal-dialog" role="document"> |
||||
<div class="modal-content"> |
||||
<div class="modal-header"> |
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> |
||||
<span aria-hidden="true">×</span></button> |
||||
<h4 class="modal-title" id="myModalLabel"> |
||||
<?php echo $calendarPlugin->get_lang('AddMultipleUsersToCalendar'); ?> |
||||
</h4> |
||||
</div> |
||||
<div class="modal-body"> |
||||
<?php echo $form->display(); ?> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<?php |
||||
|
||||
$usergroup->showGroupTypeSetting = true; |
||||
// Action handling: Adding a note |
||||
if ($action === 'delete' && is_numeric($_GET['id'])) { |
||||
$res = $usergroup->delete_user_rel_group($_GET['user_id'], $_GET['id']); |
||||
Display::addFlash(Display::return_message(get_lang('Deleted'), 'confirmation')); |
||||
header('Location: '.api_get_self().'?id='.$id); |
||||
exit; |
||||
} else { |
||||
$usergroup->displayToolBarUserGroupUsers(); |
||||
} |
||||
|
||||
Display::display_footer(); |
@ -0,0 +1,173 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\CourseRelUser; |
||||
use Chamilo\CoreBundle\Entity\ExtraField; |
||||
use Chamilo\CourseBundle\Entity\CCourseDescription; |
||||
|
||||
/** |
||||
* Course about page |
||||
* Show information about a course. |
||||
* |
||||
* @author Alex Aragon Calixto <alex.aragon@beeznest.com> |
||||
* |
||||
* @package chamilo.course |
||||
*/ |
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
|
||||
$courseId = isset($_GET['course_id']) ? (int) $_GET['course_id'] : 0; |
||||
$token = Security::get_existing_token(); |
||||
$em = Database::getManager(); |
||||
//userID |
||||
$userId = api_get_user_id(); |
||||
|
||||
/** @var Course $course */ |
||||
$course = $em->find('ChamiloCoreBundle:Course', $courseId); |
||||
|
||||
if (!$course) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$userRepo = UserManager::getRepository(); |
||||
$fieldsRepo = $em->getRepository('ChamiloCoreBundle:ExtraField'); |
||||
$fieldTagsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag'); |
||||
|
||||
/** @var CCourseDescription $courseDescription */ |
||||
$courseDescriptionTools = $em->getRepository('ChamiloCourseBundle:CCourseDescription') |
||||
->findBy( |
||||
[ |
||||
'cId' => $course->getId(), |
||||
'sessionId' => 0, |
||||
], |
||||
[ |
||||
'id' => 'DESC', |
||||
'descriptionType' => 'ASC', |
||||
] |
||||
); |
||||
|
||||
$courseValues = new ExtraFieldValue('course'); |
||||
$userValues = new ExtraFieldValue('user'); |
||||
|
||||
$urlCourse = api_get_path(WEB_PATH).'main/course/about.php?course_id='.$courseId; |
||||
$courseTeachers = $course->getTeachers(); |
||||
$teachersData = []; |
||||
|
||||
/** @var CourseRelUser $teacherSubscription */ |
||||
foreach ($courseTeachers as $teacherSubscription) { |
||||
$teacher = $teacherSubscription->getUser(); |
||||
$userData = [ |
||||
'complete_name' => $teacher->getCompleteName(), |
||||
'image' => UserManager::getUserPicture( |
||||
$teacher->getId(), |
||||
USER_IMAGE_SIZE_ORIGINAL |
||||
), |
||||
'diploma' => $teacher->getDiplomas(), |
||||
'openarea' => $teacher->getOpenarea(), |
||||
]; |
||||
|
||||
$teachersData[] = $userData; |
||||
} |
||||
|
||||
$tagField = $fieldsRepo->findOneBy([ |
||||
'extraFieldType' => ExtraField::COURSE_FIELD_TYPE, |
||||
'variable' => 'tags', |
||||
]); |
||||
|
||||
$courseTags = []; |
||||
|
||||
if (!is_null($tagField)) { |
||||
$courseTags = $fieldTagsRepo->getTags($tagField, $courseId); |
||||
} |
||||
|
||||
$courseDescription = $courseObjectives = $courseTopics = $courseMethodology = $courseMaterial = $courseResources = $courseAssessment = ''; |
||||
$courseCustom = []; |
||||
foreach ($courseDescriptionTools as $descriptionTool) { |
||||
switch ($descriptionTool->getDescriptionType()) { |
||||
case CCourseDescription::TYPE_DESCRIPTION: |
||||
$courseDescription = $descriptionTool->getContent(); |
||||
break; |
||||
case CCourseDescription::TYPE_OBJECTIVES: |
||||
$courseObjectives = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_TOPICS: |
||||
$courseTopics = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_METHODOLOGY: |
||||
$courseMethodology = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_COURSE_MATERIAL: |
||||
$courseMaterial = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_RESOURCES: |
||||
$courseResources = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_ASSESSMENT: |
||||
$courseAssessment = $descriptionTool; |
||||
break; |
||||
case CCourseDescription::TYPE_CUSTOM: |
||||
$courseCustom[] = $descriptionTool; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
$topics = [ |
||||
'objectives' => $courseObjectives, |
||||
'topics' => $courseTopics, |
||||
'methodology' => $courseMethodology, |
||||
'material' => $courseMaterial, |
||||
'resources' => $courseResources, |
||||
'assessment' => $courseAssessment, |
||||
'custom' => array_reverse($courseCustom), |
||||
]; |
||||
|
||||
$subscriptionUser = CourseManager::is_user_subscribed_in_course($userId, $course->getCode()); |
||||
|
||||
$plugin = BuyCoursesPlugin::create(); |
||||
$checker = $plugin->isEnabled(); |
||||
$courseIsPremium = null; |
||||
if ($checker) { |
||||
$courseIsPremium = $plugin->getItemByProduct( |
||||
$courseId, |
||||
BuyCoursesPlugin::PRODUCT_TYPE_COURSE |
||||
); |
||||
} |
||||
|
||||
$courseItem = [ |
||||
'code' => $course->getCode(), |
||||
'title' => $course->getTitle(), |
||||
'description' => $courseDescription, |
||||
'image' => CourseManager::getPicturePath($course, true), |
||||
'syllabus' => $topics, |
||||
'tags' => $courseTags, |
||||
'teachers' => $teachersData, |
||||
'extra_fields' => $courseValues->getAllValuesForAnItem( |
||||
$course->getId(), |
||||
null, |
||||
true |
||||
), |
||||
'subscription' => $subscriptionUser, |
||||
]; |
||||
|
||||
$metaInfo = '<meta property="og:url" content="'.$urlCourse.'" />'; |
||||
$metaInfo .= '<meta property="og:type" content="website" />'; |
||||
$metaInfo .= '<meta property="og:title" content="'.$courseItem['title'].'" />'; |
||||
$metaInfo .= '<meta property="og:description" content="'.$courseDescription.'" />'; |
||||
$metaInfo .= '<meta property="og:image" content="'.$courseItem['image'].'" />'; |
||||
|
||||
$htmlHeadXtra[] = $metaInfo; |
||||
$htmlHeadXtra[] = api_get_asset('readmore-js/readmore.js'); |
||||
|
||||
$template = new Template($course->getTitle(), true, true, false, true, false); |
||||
$template->assign('course', $courseItem); |
||||
$essence = Essence\Essence::instance(); |
||||
$template->assign('essence', $essence); |
||||
$template->assign('is_premium', $courseIsPremium); |
||||
$template->assign('token', $token); |
||||
$template->assign('url', $urlCourse); |
||||
$layout = $template->get_template('course_home/about.tpl'); |
||||
$content = $template->fetch($layout); |
||||
$template->assign('content', $content); |
||||
$template->display_one_col_template(); |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,80 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* This class handles the SCORM export of fill-in-the-blanks questions. |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormAnswerFillInBlanks extends Answer |
||||
{ |
||||
/** |
||||
* Export the text with missing words. |
||||
* |
||||
* As a side effect, it stores two lists in the class : |
||||
* the missing words and their respective weightings. |
||||
*/ |
||||
public function export() |
||||
{ |
||||
$js = ''; |
||||
// get all enclosed answers |
||||
$blankList = []; |
||||
foreach ($this->answer as $i => $answer) { |
||||
$blankList[] = '['.$answer.']'; |
||||
} |
||||
|
||||
// splits text and weightings that are joined with the character '::' |
||||
$listAnswerInfo = FillBlanks::getAnswerInfo($answer); |
||||
//$switchableAnswerSet = $listAnswerInfo['switchable']; |
||||
|
||||
// display empty [input] with the right width for student to fill it |
||||
$answer = ''; |
||||
$answerList = []; |
||||
for ($i = 0; $i < count($listAnswerInfo['common_words']) - 1; $i++) { |
||||
// display the common words |
||||
$answer .= $listAnswerInfo['common_words'][$i]; |
||||
// display the blank word |
||||
$attributes['style'] = 'width:'.$listAnswerInfo['input_size'][$i].'px'; |
||||
$answer .= FillBlanks::getFillTheBlankHtml( |
||||
$this->questionJSId, |
||||
$this->questionJSId + 1, |
||||
'', |
||||
$attributes, |
||||
$answer, |
||||
$listAnswerInfo, |
||||
true, |
||||
$i, |
||||
'question_'.$this->questionJSId.'_fib_'.($i + 1) |
||||
); |
||||
$answerList[] = $i + 1; |
||||
} |
||||
|
||||
// display the last common word |
||||
$answer .= $listAnswerInfo['common_words'][$i]; |
||||
|
||||
// because [] is parsed here we follow this procedure: |
||||
// 1. find everything between the [ and ] tags |
||||
$jstmpw = 'questions_answers_ponderation['.$this->questionJSId.'] = new Array();'."\n"; |
||||
$jstmpw .= 'questions_answers_ponderation['.$this->questionJSId.'][0] = 0;'."\n"; |
||||
|
||||
foreach ($listAnswerInfo['weighting'] as $key => $weight) { |
||||
$jstmpw .= 'questions_answers_ponderation['.$this->questionJSId.']['.($key + 1).'] = '.$weight.";\n"; |
||||
} |
||||
|
||||
$wordList = "'".implode("', '", $listAnswerInfo['words'])."'"; |
||||
$answerList = "'".implode("', '", $answerList)."'"; |
||||
|
||||
$html = '<tr><td colspan="2"><table width="100%">'; |
||||
$html .= '<tr> |
||||
<td> |
||||
'.$answer.' |
||||
</td> |
||||
</tr></table></td></tr>'; |
||||
$js .= 'questions_answers['.$this->questionJSId.'] = new Array('.$answerList.');'."\n"; |
||||
$js .= 'questions_answers_correct['.$this->questionJSId.'] = new Array('.$wordList.');'."\n"; |
||||
$js .= 'questions_types['.$this->questionJSId.'] = \'fib\';'."\n"; |
||||
$js .= $jstmpw; |
||||
|
||||
return [$js, $html]; |
||||
} |
||||
} |
@ -0,0 +1,100 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* This class handles the SCORM export of matching questions. |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormAnswerMatching extends Answer |
||||
{ |
||||
/** |
||||
* Export the question part as a matrix-choice, with only one possible answer per line. |
||||
* |
||||
* @author Amand Tihon <amand@alrj.org> |
||||
*/ |
||||
public function export() |
||||
{ |
||||
$js = ''; |
||||
// prepare list of right proposition to allow |
||||
// - easiest display |
||||
// - easiest randomisation if needed one day |
||||
// (here I use array_values to change array keys from $code1 $code2 ... to 0 1 ...) |
||||
// get max length of displayed array |
||||
$nbrAnswers = $this->selectNbrAnswers(); |
||||
$counter = 1; |
||||
$questionId = $this->questionJSId; |
||||
$jstmpw = 'questions_answers_ponderation['.$questionId.'] = new Array();'."\n"; |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.'][0] = 0;'."\n"; |
||||
|
||||
// Options (A, B, C, ...) that will be put into the list-box |
||||
$options = []; |
||||
$letter = 'A'; |
||||
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { |
||||
$answerCorrect = $this->isCorrect($answerId); |
||||
$answer = $this->selectAnswer($answerId); |
||||
$realAnswerId = $this->selectAutoId($answerId); |
||||
if (!$answerCorrect) { |
||||
$options[$realAnswerId]['Lettre'] = $letter; |
||||
// answers that will be shown at the right side |
||||
$options[$realAnswerId]['Reponse'] = $answer; |
||||
$letter++; |
||||
} |
||||
} |
||||
|
||||
$html = []; |
||||
$jstmp = ''; |
||||
$jstmpc = ''; |
||||
|
||||
// Answers |
||||
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { |
||||
$identifier = 'question_'.$questionId.'_matching_'; |
||||
$answer = $this->selectAnswer($answerId); |
||||
$answerCorrect = $this->isCorrect($answerId); |
||||
$weight = $this->selectWeighting($answerId); |
||||
$jstmp .= $answerId.','; |
||||
|
||||
if ($answerCorrect) { |
||||
$html[] = '<tr class="option_row">'; |
||||
//$html[] = '<td width="40%" valign="top"><b>'.$counter.'</b>. '.$answer."</td>"; |
||||
$html[] = '<td width="40%" valign="top"> '.$answer."</td>"; |
||||
$html[] = '<td width="20%" align="center"> '; |
||||
$html[] = '<select name="'.$identifier.$counter.'" id="'.$identifier.$counter.'">'; |
||||
$html[] = ' <option value="0">--</option>'; |
||||
// fills the list-box |
||||
foreach ($options as $key => $val) { |
||||
$html[] = '<option value="'.$key.'">'.$val['Lettre'].'</option>'; |
||||
} |
||||
|
||||
$html[] = '</select> </td>'; |
||||
$html[] = '<td width="40%" valign="top">'; |
||||
foreach ($options as $key => $val) { |
||||
$html[] = '<b>'.$val['Lettre'].'.</b> '.$val['Reponse'].'<br />'; |
||||
} |
||||
$html[] = '</td></tr>'; |
||||
|
||||
$jstmpc .= '['.$answerCorrect.','.$counter.'],'; |
||||
|
||||
$myWeight = explode('@', $weight); |
||||
if (count($myWeight) == 2) { |
||||
$weight = $myWeight[0]; |
||||
} else { |
||||
$weight = $myWeight[0]; |
||||
} |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.']['.$counter.'] = '.$weight.";\n"; |
||||
$counter++; |
||||
} |
||||
} |
||||
|
||||
$js .= 'questions_answers['.$questionId.'] = new Array('.substr($jstmp, 0, -1).');'."\n"; |
||||
$js .= 'questions_answers_correct['.$questionId.'] = new Array('.substr($jstmpc, 0, -1).');'."\n"; |
||||
$js .= 'questions_types['.$questionId.'] = \'matching\';'."\n"; |
||||
$js .= $jstmpw; |
||||
|
||||
$htmlResult = '<tr><td colspan="2"><table id="question_'.$questionId.'" width="100%">'; |
||||
$htmlResult .= implode("\n", $html); |
||||
$htmlResult .= '</table></td></tr>'."\n"; |
||||
|
||||
return [$js, $htmlResult]; |
||||
} |
||||
} |
@ -0,0 +1,119 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* This class handles the export to SCORM of a multiple choice question |
||||
* (be it single answer or multiple answers). |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormAnswerMultipleChoice extends Answer |
||||
{ |
||||
/** |
||||
* Return HTML code for possible answers. |
||||
*/ |
||||
public function export() |
||||
{ |
||||
$js = []; |
||||
$type = $this->getQuestionType(); |
||||
$questionId = $this->questionJSId; |
||||
$jstmpw = 'questions_answers_ponderation['.$questionId.'] = new Array();'; |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.'][0] = 0;'; |
||||
$jstmpw .= 'questions_answers_correct['.$questionId.'] = new Array();'; |
||||
$html = []; |
||||
|
||||
//not sure if we are going to export also the MULTIPLE_ANSWER_COMBINATION to SCORM |
||||
//if ($type == MCMA || $type == MULTIPLE_ANSWER_COMBINATION ) { |
||||
if ($type == MCMA) { |
||||
$id = 1; |
||||
$jstmp = ''; |
||||
$jstmpc = ''; |
||||
foreach ($this->answer as $i => $answer) { |
||||
$identifier = 'question_'.$questionId.'_multiple_'.$i; |
||||
$html[] = |
||||
'<tr> |
||||
<td align="center" width="5%"> |
||||
<input name="'.$identifier.'" id="'.$identifier.'" value="'.$i.'" type="checkbox" /> |
||||
</td> |
||||
<td width="95%"> |
||||
<label for="'.$identifier.'">'.Security::remove_XSS($this->answer[$i]).'</label> |
||||
</td> |
||||
</tr>'; |
||||
|
||||
$jstmp .= $i.','; |
||||
if ($this->correct[$i]) { |
||||
$jstmpc .= $i.','; |
||||
} |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.']['.$i.'] = '.$this->weighting[$i].";"; |
||||
$jstmpw .= 'questions_answers_correct['.$questionId.']['.$i.'] = '.$this->correct[$i].';'; |
||||
$id++; |
||||
} |
||||
$js[] = 'questions_answers['.$questionId.'] = new Array('.substr($jstmp, 0, -1).');'."\n"; |
||||
$js[] = 'questions_types['.$questionId.'] = \'mcma\';'."\n"; |
||||
$js[] = $jstmpw; |
||||
} elseif ($type == MULTIPLE_ANSWER_COMBINATION) { |
||||
$js = ''; |
||||
$id = 1; |
||||
$jstmp = ''; |
||||
$jstmpc = ''; |
||||
foreach ($this->answer as $i => $answer) { |
||||
$identifier = 'question_'.$questionId.'_exact_'.$i; |
||||
$html[] = |
||||
'<tr> |
||||
<td align="center" width="5%"> |
||||
<input name="'.$identifier.'" id="'.$identifier.'" value="'.$i.'" type="checkbox" /> |
||||
</td> |
||||
<td width="95%"> |
||||
<label for="'.$identifier.'">'.Security::remove_XSS($this->answer[$i]).'</label> |
||||
</td> |
||||
</tr>'; |
||||
|
||||
$jstmp .= $i.','; |
||||
if ($this->correct[$i]) { |
||||
$jstmpc .= $i.','; |
||||
} |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.']['.$i.'] = '.$this->weighting[$i].';'; |
||||
$jstmpw .= 'questions_answers_correct['.$questionId.']['.$i.'] = '.$this->correct[$i].';'; |
||||
$id++; |
||||
} |
||||
$js[] = 'questions_answers['.$questionId.'] = new Array('.substr($jstmp, 0, -1).');'; |
||||
$js[] = 'questions_types['.$questionId.'] = "exact";'; |
||||
$js[] = $jstmpw; |
||||
} else { |
||||
$id = 1; |
||||
$jstmp = ''; |
||||
$jstmpc = ''; |
||||
foreach ($this->answer as $i => $answer) { |
||||
$identifier = 'question_'.$questionId.'_unique_'.$i; |
||||
$identifier_name = 'question_'.$questionId.'_unique_answer'; |
||||
$html[] = |
||||
'<tr> |
||||
<td align="center" width="5%"> |
||||
<input name="'.$identifier_name.'" id="'.$identifier.'" value="'.$i.'" type="checkbox"/> |
||||
</td> |
||||
<td width="95%"> |
||||
<label for="'.$identifier.'">'.Security::remove_XSS($this->answer[$i]).'</label> |
||||
</td> |
||||
</tr>'; |
||||
$jstmp .= $i.','; |
||||
if ($this->correct[$i]) { |
||||
$jstmpc .= $i; |
||||
} |
||||
$jstmpw .= 'questions_answers_ponderation['.$questionId.']['.$i.'] = '.$this->weighting[$i].';'; |
||||
$jstmpw .= 'questions_answers_correct['.$questionId.']['.$i.'] = '.$this->correct[$i].';'; |
||||
$id++; |
||||
} |
||||
$js[] = 'questions_answers['.$questionId.'] = new Array('.substr($jstmp, 0, -1).');'; |
||||
$js[] = 'questions_types['.$questionId.'] = \'mcua\';'; |
||||
$js[] = $jstmpw; |
||||
} |
||||
|
||||
$htmlResult = '<tr><td colspan="2"><table id="question_'.$questionId.'" width="100%">'; |
||||
$htmlResult .= implode("\n", $html); |
||||
$htmlResult .= '</table></td></tr>'; |
||||
|
||||
$js = implode("\n", $js); |
||||
|
||||
return [$js, $htmlResult]; |
||||
} |
||||
} |
@ -0,0 +1,56 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* This class handles the SCORM export of true/false questions. |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormAnswerTrueFalse extends Answer |
||||
{ |
||||
/** |
||||
* Return the XML flow for the possible answers. |
||||
* That's one <response_lid>, containing several <flow_label>. |
||||
* |
||||
* @author Amand Tihon <amand@alrj.org> |
||||
*/ |
||||
public function export() |
||||
{ |
||||
$js = ''; |
||||
$html = '<tr><td colspan="2"><table width="100%">'; |
||||
$identifier = 'question_'.$this->questionJSId.'_tf'; |
||||
$identifier_true = $identifier.'_true'; |
||||
$identifier_false = $identifier.'_false'; |
||||
$html .= |
||||
'<tr> |
||||
<td align="center" width="5%"> |
||||
<input name="'.$identifier_true.'" id="'.$identifier_true.'" value="'.$this->trueGrade.'" type="radio" /> |
||||
</td> |
||||
<td width="95%"> |
||||
<label for="'.$identifier_true.'">'.get_lang('True').'</label> |
||||
</td> |
||||
</tr>'; |
||||
$html .= |
||||
'<tr> |
||||
<td align="center" width="5%"> |
||||
<input name="'.$identifier_false.'" id="'.$identifier_false.'" value="'.$this->falseGrade.'" type="radio" /> |
||||
</td> |
||||
<td width="95%"> |
||||
<label for="'.$identifier_false.'">'.get_lang('False').'</label> |
||||
</td> |
||||
</tr></table></td></tr>'; |
||||
$js .= 'questions_answers['.$this->questionJSId.'] = new Array(\'true\',\'false\');'."\n"; |
||||
$js .= 'questions_types['.$this->questionJSId.'] = \'tf\';'."\n"; |
||||
if ($this->response === 'TRUE') { |
||||
$js .= 'questions_answers_correct['.$this->questionJSId.'] = new Array(\'true\');'."\n"; |
||||
} else { |
||||
$js .= 'questions_answers_correct['.$this->questionJSId.'] = new Array(\'false\');'."\n"; |
||||
} |
||||
$jstmpw = 'questions_answers_ponderation['.$this->questionJSId.'] = new Array();'."\n"; |
||||
$jstmpw .= 'questions_answers_ponderation['.$this->questionJSId.'][0] = 0;'."\n"; |
||||
$jstmpw .= 'questions_answers_ponderation['.$this->questionJSId.'][1] = '.$this->weighting[1].";\n"; |
||||
$js .= $jstmpw; |
||||
|
||||
return [$js, $html]; |
||||
} |
||||
} |
@ -0,0 +1,184 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* A SCORM item. It corresponds to a single question. |
||||
* This class allows export from Chamilo SCORM 1.2 format of a single question. |
||||
* It is not usable as-is, but must be subclassed, to support different kinds of questions. |
||||
* |
||||
* Every start_*() and corresponding end_*(), as well as export_*() methods return a string. |
||||
* |
||||
* Attached files are NOT exported. |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormAssessmentItem |
||||
{ |
||||
public $question; |
||||
public $question_ident; |
||||
public $answer; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param ScormQuestion $question the Question object we want to export |
||||
*/ |
||||
public function __construct($question) |
||||
{ |
||||
$this->question = $question; |
||||
$this->question->setAnswer(); |
||||
$this->questionIdent = 'QST_'.$question->id; |
||||
} |
||||
|
||||
/** |
||||
* Start the XML flow. |
||||
* |
||||
* This opens the <item> block, with correct attributes. |
||||
*/ |
||||
public function start_page() |
||||
{ |
||||
$head = ''; |
||||
/*if ($this->standalone) { |
||||
$charset = 'UTF-8'; |
||||
$head = '<?xml version="1.0" encoding="'.$charset.'" standalone="no"?>';
|
||||
$head .= '<html>'; |
||||
}*/ |
||||
|
||||
return $head; |
||||
} |
||||
|
||||
/** |
||||
* End the XML flow, closing the </item> tag. |
||||
*/ |
||||
public function end_page() |
||||
{ |
||||
/*if ($this->standalone) { |
||||
return '</html>'; |
||||
}*/ |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Start document header. |
||||
*/ |
||||
public function start_header() |
||||
{ |
||||
/*if ($this->standalone) { |
||||
return '<head>'; |
||||
}*/ |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Print CSS inclusion. |
||||
*/ |
||||
public function css() |
||||
{ |
||||
$css = ''; |
||||
// if ($this->standalone) { |
||||
// $css = '<style type="text/css" media="screen, projection">'; |
||||
// $css .= '/*<![CDATA[*/'."\n"; |
||||
// $css .= '/*]]>*/'."\n"; |
||||
// $css .= '</style>'."\n"; |
||||
// $css .= '<style type="text/css" media="print">'; |
||||
// $css .= '/*<![CDATA[*/'."\n"; |
||||
// $css .= '/*]]>*/'."\n"; |
||||
// $css .= '</style>'; |
||||
// } |
||||
|
||||
return $css; |
||||
} |
||||
|
||||
/** |
||||
* End document header. |
||||
*/ |
||||
public function end_header() |
||||
{ |
||||
// if ($this->standalone) { |
||||
// return '</head>'; |
||||
// } |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Start the itemBody. |
||||
*/ |
||||
public function start_js() |
||||
{ |
||||
$js = '<script type="text/javascript" src="assets/api_wrapper.js"></script>'; |
||||
// if ($this->standalone) { |
||||
// return '<script>'; |
||||
// } |
||||
|
||||
return $js; |
||||
} |
||||
|
||||
/** |
||||
* End the itemBody part. |
||||
*/ |
||||
public function end_js() |
||||
{ |
||||
/*if ($this->standalone) { |
||||
return '</script>'; |
||||
}*/ |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Start the itemBody. |
||||
*/ |
||||
public function start_body() |
||||
{ |
||||
/*if ($this->standalone) { |
||||
return '<body><form id="dokeos_scorm_form" method="post" action="">'; |
||||
}*/ |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* End the itemBody part. |
||||
*/ |
||||
public function end_body() |
||||
{ |
||||
/*if ($this->standalone) { |
||||
return '<br /><input class="btn" type="button" id="dokeos_scorm_submit" name="dokeos_scorm_submit" value="OK" /></form></body>'; |
||||
}*/ |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* Export the question as a SCORM Item. |
||||
* This is a default behaviour, some classes may want to override this. |
||||
* |
||||
* @return string|array a string, the XML flow for an Item |
||||
*/ |
||||
public function export() |
||||
{ |
||||
list($js, $html) = $this->question->export(); |
||||
/*if ($this->standalone) { |
||||
$res = $this->start_page() |
||||
.$this->start_header() |
||||
.$this->css() |
||||
.$this->start_js() |
||||
.$this->common_js() |
||||
.$js |
||||
.$this->end_js() |
||||
.$this->end_header() |
||||
.$this->start_body() |
||||
.$html |
||||
.$this->end_body() |
||||
.$this->end_page(); |
||||
|
||||
return $res; |
||||
} else { |
||||
return [$js, $html]; |
||||
}*/ |
||||
return [$js, $html]; |
||||
} |
||||
} |
@ -0,0 +1,221 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use Chamilo\CourseBundle\Entity\CQuiz; |
||||
use Symfony\Component\Serializer\Encoder\JsonEncoder; |
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; |
||||
use Symfony\Component\Serializer\Serializer; |
||||
|
||||
/** |
||||
* This class represents an entire exercise to be exported in SCORM. |
||||
* It will be represented by a single <section> containing several <item>. |
||||
* |
||||
* Some properties cannot be exported, as SCORM does not support them : |
||||
* - type (one page or multiple pages) |
||||
* - start_date and end_date |
||||
* - max_attempts |
||||
* - show_answer |
||||
* - anonymous_attempts |
||||
* |
||||
* @author Julio Montoya |
||||
* @author Amand Tihon <amand@alrj.org> |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormExercise |
||||
{ |
||||
public $exercise; |
||||
public $standalone; |
||||
|
||||
/** |
||||
* ScormExercise constructor. |
||||
* |
||||
* @param Exercise $exe |
||||
* @param bool $standalone |
||||
*/ |
||||
public function __construct($exe, $standalone) |
||||
{ |
||||
$this->exercise = $exe; |
||||
$this->standalone = $standalone; |
||||
} |
||||
|
||||
/** |
||||
* Start the XML flow. |
||||
* |
||||
* This opens the <item> block, with correct attributes. |
||||
*/ |
||||
public function startPage() |
||||
{ |
||||
$charset = 'UTF-8'; |
||||
$head = '<?xml version="1.0" encoding="'.$charset.'" standalone="no"?><html>';
|
||||
|
||||
return $head; |
||||
} |
||||
|
||||
/** |
||||
* End the XML flow, closing the </item> tag. |
||||
*/ |
||||
public function end_page() |
||||
{ |
||||
return '</html>'; |
||||
} |
||||
|
||||
/** |
||||
* Start document header. |
||||
*/ |
||||
public function start_header() |
||||
{ |
||||
return '<head>'; |
||||
} |
||||
|
||||
/** |
||||
* Common JS functions. |
||||
*/ |
||||
public function common_js() |
||||
{ |
||||
$js = file_get_contents(api_get_path(SYS_CODE_PATH).'exercise/export/scorm/common.js'); |
||||
|
||||
return $js."\n"; |
||||
} |
||||
|
||||
/** |
||||
* End the itemBody part. |
||||
*/ |
||||
public function end_js() |
||||
{ |
||||
return '</script>'; |
||||
} |
||||
|
||||
/** |
||||
* Start the itemBody. |
||||
*/ |
||||
public function start_body() |
||||
{ |
||||
return '<body>'. |
||||
'<h1>'.$this->exercise->selectTitle().'</h1><p>'.$this->exercise->selectDescription()."</p>". |
||||
'<form id="chamilo_scorm_form" method="post" action="">'. |
||||
'<table width="100%">'; |
||||
} |
||||
|
||||
/** |
||||
* End the itemBody part. |
||||
*/ |
||||
public function end_body() |
||||
{ |
||||
$button = '<input |
||||
id="chamilo_scorm_submit" |
||||
class="btn btn-primary" |
||||
type="button" |
||||
name="chamilo_scorm_submit" |
||||
value="OK" />'; |
||||
|
||||
return '</table><br />'.$button.'</form></body>'; |
||||
} |
||||
|
||||
/** |
||||
* Export the question as a SCORM Item. |
||||
* |
||||
* This is a default behaviour, some classes may want to override this. |
||||
* |
||||
* @param $standalone: Boolean stating if it should be exported as a stand-alone question |
||||
* |
||||
* @return string string, the XML flow for an Item |
||||
*/ |
||||
public function export() |
||||
{ |
||||
global $charset; |
||||
|
||||
/*$head = ''; |
||||
if ($this->standalone) { |
||||
$head = '<?xml version = "1.0" encoding = "'.$charset.'" standalone = "no"?>'."\n"
|
||||
.'<!DOCTYPE questestinterop SYSTEM "ims_qtiasiv2p1.dtd">'."\n"; |
||||
}*/ |
||||
|
||||
list($js, $html) = $this->exportQuestions(); |
||||
$res = $this->startPage() |
||||
.$this->start_header() |
||||
.$this->css() |
||||
.$this->globalAssets() |
||||
.$this->start_js() |
||||
.$this->common_js() |
||||
.$js |
||||
.$this->end_js() |
||||
.$this->end_header() |
||||
.$this->start_body() |
||||
.$html |
||||
.$this->end_body() |
||||
.$this->end_page(); |
||||
|
||||
return $res; |
||||
} |
||||
|
||||
/** |
||||
* Export the questions, as a succession of <items>. |
||||
* |
||||
* @author Amand Tihon <amand@alrj.org> |
||||
*/ |
||||
public function exportQuestions() |
||||
{ |
||||
$js = $html = ''; |
||||
$encoders = [new JsonEncoder()]; |
||||
$normalizers = [new ObjectNormalizer()]; |
||||
|
||||
$em = Database::getManager(); |
||||
// Export cquiz data |
||||
/** @var CQuiz $exercise */ |
||||
$exercise = $em->find('ChamiloCourseBundle:CQuiz', $this->exercise->iId); |
||||
$exercise->setDescription(''); |
||||
$exercise->setTextWhenFinished(''); |
||||
|
||||
$serializer = new Serializer($normalizers, $encoders); |
||||
$jsonContent = $serializer->serialize($exercise, 'json'); |
||||
$js .= "var exerciseInfo = JSON.parse('".$jsonContent."');\n"; |
||||
|
||||
$counter = 0; |
||||
$scormQuestion = new ScormQuestion(); |
||||
foreach ($this->exercise->selectQuestionList() as $q) { |
||||
list($jstmp, $htmltmp) = $scormQuestion->exportQuestionToScorm($q, $counter); |
||||
$js .= $jstmp."\n"; |
||||
$html .= $htmltmp."\n"; |
||||
$counter++; |
||||
} |
||||
|
||||
return [$js, $html]; |
||||
} |
||||
|
||||
/** |
||||
* Print CSS inclusion. |
||||
*/ |
||||
private function css() |
||||
{ |
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* End document header. |
||||
*/ |
||||
private function end_header() |
||||
{ |
||||
return '</head>'; |
||||
} |
||||
|
||||
/** |
||||
* Start the itemBody. |
||||
*/ |
||||
private function start_js() |
||||
{ |
||||
return '<script>'; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
private function globalAssets() |
||||
{ |
||||
$assets = '<script type="text/javascript" src="assets/jquery/jquery.min.js"></script>'."\n"; |
||||
$assets .= '<script type="text/javascript" src="assets/api_wrapper.js"></script>'."\n"; |
||||
$assets .= '<link href="assets/bootstrap/bootstrap.min.css" rel="stylesheet" media="screen" type="text/css" />'; |
||||
|
||||
return $assets; |
||||
} |
||||
} |
@ -0,0 +1,223 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* The ScormQuestion class is a gateway to getting the answers exported |
||||
* (the question is just an HTML text, while the answers are the most important). |
||||
* It is important to note that the SCORM export process is done in two parts. |
||||
* First, the HTML part (which is the presentation), and second the JavaScript |
||||
* part (the process). |
||||
* The two bits are separate to allow for a one-big-javascript and a one-big-html |
||||
* files to be built. Each export function thus returns an array of HTML+JS. |
||||
* |
||||
* |
||||
* @author Claro Team <cvs@claroline.net> |
||||
* @author Yannick Warnier <yannick.warnier@beeznest.com> |
||||
* |
||||
* @package chamilo.exercise.scorm |
||||
*/ |
||||
class ScormQuestion extends Question |
||||
{ |
||||
public $js_id; |
||||
public $answer; |
||||
|
||||
/** |
||||
* ScormQuestion constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
parent::__construct(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the HTML + JS flow corresponding to one question. |
||||
* |
||||
* @param int $questionId The question ID |
||||
* @param bool $standalone (ie including XML tag, DTD declaration, etc) |
||||
* @param int $jsId The JavaScript ID for this question. |
||||
* Due to the nature of interactions, we must have a natural sequence for |
||||
* questions in the generated JavaScript. |
||||
* |
||||
* @return string|array |
||||
*/ |
||||
public function exportQuestionToScorm( |
||||
$questionId, |
||||
$jsId |
||||
) { |
||||
$question = self::read($questionId); |
||||
if (!$question) { |
||||
return ''; |
||||
} |
||||
$this->id = $question->id; |
||||
$this->js_id = $jsId; |
||||
$this->type = $question->type; |
||||
$this->question = $question->question; |
||||
$this->description = $question->description; |
||||
$this->weighting = $question->weighting; |
||||
$this->position = $question->position; |
||||
$this->picture = $question->picture; |
||||
$assessmentItem = new ScormAssessmentItem($this); |
||||
|
||||
return $assessmentItem->export(); |
||||
} |
||||
|
||||
/** |
||||
* Include the correct answer class and create answer. |
||||
*/ |
||||
public function setAnswer() |
||||
{ |
||||
switch ($this->type) { |
||||
case MCUA: |
||||
$this->answer = new ScormAnswerMultipleChoice($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case MCMA: |
||||
case GLOBAL_MULTIPLE_ANSWER: |
||||
$this->answer = new ScormAnswerMultipleChoice($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case TF: |
||||
$this->answer = new ScormAnswerTrueFalse($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case FIB: |
||||
$this->answer = new ScormAnswerFillInBlanks($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case MATCHING: |
||||
case MATCHING_DRAGGABLE: |
||||
case DRAGGABLE: |
||||
$this->answer = new ScormAnswerMatching($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case ORAL_EXPRESSION: |
||||
case FREE_ANSWER: |
||||
$this->answer = new ScormAnswerFree($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case HOT_SPOT: |
||||
$this->answer = new ScormAnswerHotspot($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case MULTIPLE_ANSWER_COMBINATION: |
||||
$this->answer = new ScormAnswerMultipleChoice($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case HOT_SPOT_ORDER: |
||||
$this->answer = new ScormAnswerHotspot($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
case HOT_SPOT_DELINEATION: |
||||
$this->answer = new ScormAnswerHotspot($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
// not supported |
||||
case UNIQUE_ANSWER_NO_OPTION: |
||||
case MULTIPLE_ANSWER_TRUE_FALSE: |
||||
case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE: |
||||
case UNIQUE_ANSWER_IMAGE: |
||||
case CALCULATED_ANSWER: |
||||
$this->answer = new ScormAnswerMultipleChoice($this->id); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
default: |
||||
$this->answer = new stdClass(); |
||||
$this->answer->questionJSId = $this->js_id; |
||||
break; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @throws Exception |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function export() |
||||
{ |
||||
$html = $this->getQuestionHTML(); |
||||
$js = $this->getQuestionJS(); |
||||
|
||||
if (is_object($this->answer) && $this->answer instanceof Answer) { |
||||
list($js2, $html2) = $this->answer->export(); |
||||
$js .= $js2; |
||||
$html .= $html2; |
||||
} else { |
||||
throw new \Exception('Question not supported. Exercise: '.$this->selectTitle()); |
||||
} |
||||
|
||||
return [$js, $html]; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function createAnswersForm($form) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function processAnswersCreation($form, $exercise) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Returns an HTML-formatted question. |
||||
*/ |
||||
public function getQuestionHTML() |
||||
{ |
||||
$title = $this->selectTitle(); |
||||
$description = $this->selectDescription(); |
||||
$cols = 2; |
||||
$s = '<tr> |
||||
<td colspan="'.$cols.'" id="question_'.$this->id.'_title" valign="middle" style="background-color:#d6d6d6;"> |
||||
'.$title.' |
||||
</td> |
||||
</tr> |
||||
<tr> |
||||
<td valign="top" colspan="'.$cols.'"> |
||||
<i>'.$description.'</i> |
||||
</td> |
||||
</tr>'; |
||||
|
||||
return $s; |
||||
} |
||||
|
||||
/** |
||||
* Return the JavaScript code bound to the question. |
||||
*/ |
||||
public function getQuestionJS() |
||||
{ |
||||
$weight = $this->selectWeighting(); |
||||
$js = ' |
||||
questions.push('.$this->js_id.'); |
||||
$(document).ready(function() { |
||||
if (exerciseInfo.randomAnswers == true) { |
||||
$("#question_'.$this->js_id.'").shuffleRows(); |
||||
} |
||||
});'; |
||||
$js .= "\n"; |
||||
|
||||
switch ($this->type) { |
||||
case ORAL_EXPRESSION: |
||||
/*$script = file_get_contents(api_get_path(LIBRARY_PATH) . 'javascript/rtc/RecordRTC.js'); |
||||
$script .= file_get_contents(api_get_path(LIBRARY_PATH) . 'wami-recorder/recorder.js'); |
||||
$script .= file_get_contents(api_get_path(LIBRARY_PATH) . 'wami-recorder/gui.js'); |
||||
$js .= $script;*/ |
||||
break; |
||||
case HOT_SPOT: |
||||
//put the max score to 0 to avoid discounting the points of |
||||
//non-exported quiz types in the SCORM |
||||
$weight = 0; |
||||
break; |
||||
} |
||||
$js .= 'questions_score_max['.$this->js_id.'] = '.$weight.";"; |
||||
|
||||
return $js; |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
var questions = new Array(); |
||||
var questions_answers = new Array(); |
||||
var questions_answers_correct = new Array(); |
||||
var questions_types = new Array(); |
||||
var questions_score_max = new Array(); |
||||
var questions_answers_ponderation = new Array(); |
||||
|
||||
/** |
||||
* Adds the event listener |
||||
*/ |
||||
function addListeners(e) { |
||||
loadPage(); |
||||
var myButton = document.getElementById('chamilo_scorm_submit'); |
||||
addEvent(myButton, 'click', doQuit, false); |
||||
addEvent(myButton, 'click', disableButton, false); |
||||
addEvent(window, 'unload', unloadPage, false); |
||||
} |
||||
|
||||
/** Disables the submit button on SCORM result submission **/ |
||||
function disableButton() { |
||||
var mybtn = document.getElementById('chamilo_scorm_submit'); |
||||
mybtn.setAttribute('disabled', 'disabled'); |
||||
} |
||||
|
||||
addEvent(window,'load', addListeners, false); |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,27 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
/** |
||||
* Responses to AJAX calls. |
||||
*/ |
||||
require_once __DIR__.'/../global.inc.php'; |
||||
|
||||
$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : ''; |
||||
$isAllowedToEdit = api_is_allowed_to_edit(); |
||||
|
||||
switch ($action) { |
||||
case 'delete_user_in_usergroup': |
||||
if ($isAllowedToEdit) { |
||||
$userGroup = new UserGroup(); |
||||
$userId = isset($_REQUEST['id']) ? $_REQUEST['id'] : 0; |
||||
$userIdList = explode(',', $userId); |
||||
$groupId = isset($_REQUEST['group_id']) ? $_REQUEST['group_id'] : 0; |
||||
foreach ($userIdList as $userId) { |
||||
$userGroup->delete_user_rel_group($userId, $groupId); |
||||
} |
||||
} |
||||
break; |
||||
default: |
||||
echo ''; |
||||
break; |
||||
} |
||||
exit; |
@ -0,0 +1,37 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
/** |
||||
* Class HookCreateCourse. |
||||
*/ |
||||
class HookCreateCourse extends HookEvent implements HookCreateCourseEventInterface |
||||
{ |
||||
/** |
||||
* HookCreateCourse constructor. |
||||
* |
||||
* @throws Exception |
||||
*/ |
||||
protected function __construct() |
||||
{ |
||||
parent::__construct('HookCreateCourse'); |
||||
} |
||||
|
||||
/** |
||||
* Update all the observers. |
||||
* |
||||
* @param int $type |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function notifyCreateCourse($type) |
||||
{ |
||||
$this->eventData['type'] = $type; |
||||
|
||||
/** @var HookCreateCourseObserverInterface $observer */ |
||||
foreach ($this->observers as $observer) { |
||||
$observer->hookCreateCourse($this); |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
} |
@ -0,0 +1,23 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
/** |
||||
* This file contains all Hook interfaces and their relation. |
||||
* They are used for Hook classes. |
||||
* |
||||
* @package chamilo.library.hook |
||||
*/ |
||||
|
||||
/** |
||||
* Interface HookCreateUserEventInterface. |
||||
*/ |
||||
interface HookCreateCourseEventInterface extends HookEventInterface |
||||
{ |
||||
/** |
||||
* Update all the observers. |
||||
* |
||||
* @param int $type |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function notifyCreateCourse($type); |
||||
} |
@ -0,0 +1,21 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
/** |
||||
* This file contains all Hook interfaces and their relation. |
||||
* They are used for Hook classes. |
||||
* |
||||
* @package chamilo.library.hook |
||||
*/ |
||||
|
||||
/** |
||||
* Interface CreateUserHookInterface. |
||||
*/ |
||||
interface HookCreateCourseObserverInterface extends HookObserverInterface |
||||
{ |
||||
/** |
||||
* @param HookCreateCourseEventInterface $hook |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function hookCreateCourse(HookCreateCourseEventInterface $hook); |
||||
} |
@ -1,553 +0,0 @@ |
||||
/** |
||||
* JavaScript functions to handle standard behaviors of a QuickForm advmultiselect element |
||||
* |
||||
* @category HTML |
||||
* @package HTML_QuickForm_advmultiselect |
||||
* @author Laurent Laville <pear@laurent-laville.org> |
||||
* @copyright 2007-2009 Laurent Laville |
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: qfamsHandler.js,v 1.13 2009/02/06 09:49:22 farell Exp $ |
||||
* @since File available since Release 1.3.0 |
||||
*/ |
||||
|
||||
if (typeof QFAMS === "undefined" || !QFAMS) { |
||||
/** |
||||
* The QFAMS global namespace object. If QFAMS is already defined, the |
||||
* existing QFAMS object will not be overwritten so that defined |
||||
* namespaces are preserved. |
||||
* @class QFAMS |
||||
* @static |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
var QFAMS = {}; |
||||
} |
||||
|
||||
/** |
||||
* QFAMS.env is used to keep track of end-user preferences |
||||
* for persistant values. |
||||
* |
||||
* @class QFAMS.env |
||||
* @static |
||||
*/ |
||||
QFAMS.env = QFAMS.env || { |
||||
/** |
||||
* Keeps the persistant selection preference when items are selected or unselected |
||||
* |
||||
* @property persistantSelection |
||||
* @type Boolean |
||||
*/ |
||||
persistantSelection: false, |
||||
|
||||
/** |
||||
* Keeps the persistant selection preference when items are moved up or down |
||||
* |
||||
* @property persistantMove |
||||
* @type Boolean |
||||
*/ |
||||
persistantMove: true |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.updateCounter as a |
||||
* text tools to replace all childs of 'c' element by a new text node of 'v' value |
||||
* |
||||
* @param dom element c html element; <span> is best use in most case |
||||
* @param string v new counter value |
||||
* |
||||
* @method updateCounter |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.updateCounter = function (c, v) { |
||||
var i; |
||||
var nodeText = null; |
||||
|
||||
if (c !== null) { |
||||
// remove all previous child nodes of 'c' element
|
||||
if (c.childNodes) { |
||||
for (i = 0; i < c.childNodes.length; i++) { |
||||
c.removeChild(c.childNodes[i]); |
||||
} |
||||
} |
||||
// add new text value 'v'
|
||||
nodeText = document.createTextNode(v); |
||||
c.appendChild(nodeText); |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.updateLiveCounter as a |
||||
* standard onclick event handler to dynamic change value of counter |
||||
* that display current selection |
||||
* |
||||
* @method updateLiveCounter |
||||
* @static |
||||
* @return void |
||||
* @private |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.updateLiveCounter = function () { |
||||
var lbl = this.parentNode; |
||||
var selectedCount = 0; |
||||
|
||||
// Find all the checkboxes...
|
||||
var div = lbl.parentNode; |
||||
var inputs = div.getElementsByTagName('input'); |
||||
for (var i = 0; i < inputs.length; i++) { |
||||
if (inputs[i].checked == 1) { |
||||
selectedCount++; |
||||
} |
||||
} |
||||
var e = div.id; |
||||
var qfamsName = e.substring(e.indexOf('_', 0) + 1, e.length); |
||||
// updates item count
|
||||
var span = document.getElementById(qfamsName + '_selected'); |
||||
QFAMS.updateCounter(span, selectedCount + '/' + inputs.length); |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.editSelection |
||||
* in single select box mode, to edit current selection and update live counter |
||||
* |
||||
* @param string qfamsName QuickForm advmultiselect element name |
||||
* @param integer selectMode Selection mode (0 = uncheck, 1 = check, 2 = toggle) |
||||
* |
||||
* @method editSelection |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.editSelection = function (qfamsName, selectMode) { |
||||
if (selectMode !== 0 && selectMode !== 1 && selectMode !== 2) { |
||||
return; |
||||
} |
||||
var selectedCount = 0; |
||||
|
||||
// Find all the checkboxes...
|
||||
var ams = document.getElementById('qfams_' + qfamsName); |
||||
var inputs = ams.getElementsByTagName('input'); |
||||
|
||||
// Loop through all checkboxes (input element)
|
||||
for (var i = 0; i < inputs.length; i++) { |
||||
if (selectMode === 2) { |
||||
if (inputs[i].checked == 0) { |
||||
inputs[i].checked = 1; |
||||
} else if (inputs[i].checked == 1) { |
||||
inputs[i].checked = 0; |
||||
} |
||||
} else { |
||||
inputs[i].checked = selectMode; |
||||
} |
||||
if (inputs[i].checked == 1) { |
||||
selectedCount++; |
||||
} |
||||
} |
||||
|
||||
// updates selected item count
|
||||
var span = document.getElementById(qfamsName + '_selected'); |
||||
QFAMS.updateCounter(span, selectedCount + '/' + inputs.length); |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.moveSelection |
||||
* in double select box mode, to move current selection and update live counter |
||||
* |
||||
* @param string qfamsName QuickForm advmultiselect element name |
||||
* @param dom element selectLeft Data source list |
||||
* @param dom element selectRight Target data list |
||||
* @param dom element selectHidden Full data source (selected, unselected) |
||||
* private usage |
||||
* @param string action Action name (add, remove, all, none, toggle) |
||||
* @param string arrange Sort option (none, asc, desc) |
||||
* |
||||
* @method moveSelection |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveSelection = function (qfamsName, selectLeft, selectRight, selectHidden, action, arrange) { |
||||
var isIE = /*@cc_on!@*/false; //IE detector
|
||||
var source = null; |
||||
var target = null; |
||||
var option; |
||||
var c = null; |
||||
var s = null; |
||||
var i; |
||||
var maxFrom, maxTo; |
||||
|
||||
if (action === 'add' || action === 'all' || action === 'toggle') { |
||||
source = selectLeft; |
||||
target = selectRight; |
||||
} else { |
||||
source = selectRight; |
||||
target = selectLeft; |
||||
} |
||||
// Don't do anything if nothing selected. Otherwise we throw javascript errors.
|
||||
if (source.selectedIndex === -1 && (action === 'add' || action === 'remove')) { |
||||
return; |
||||
} |
||||
maxFrom = source.options.length; |
||||
maxTo = target.options.length; |
||||
|
||||
// check if target list is empty and remove fake empty option (tip to be XHTML compliant)
|
||||
if (maxTo > 0 && target.options[0].value === "") { |
||||
target.removeAttribute("disabled"); |
||||
target.options[0] = null; |
||||
} |
||||
|
||||
// Add items to the 'TO' list.
|
||||
for (i = (maxFrom - 1); i >= 0; i--) { |
||||
if (action === 'all' || action === 'none' || action === 'toggle' || source.options[i].selected === true) { |
||||
if (source.options[i].disabled === false) { |
||||
if (isIE) { |
||||
option = source.options[i].removeNode(true); |
||||
option.selected = QFAMS.env.persistantSelection; |
||||
target.appendChild(option); |
||||
} else { |
||||
option = source.options[i].cloneNode(true); |
||||
option.selected = QFAMS.env.persistantSelection; |
||||
target.options[target.options.length] = option; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Remove items from the 'FROM' list.
|
||||
if (!isIE) { |
||||
for (i = (maxFrom - 1); i >= 0; i--) { |
||||
if (action === 'all' || action === 'none' || action === 'toggle' || source.options[i].selected === true) { |
||||
if (source.options[i].disabled === false) { |
||||
source.options[i] = null; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Add items to the 'FROM' list for toggle function
|
||||
if (action === 'toggle') { |
||||
for (i = (maxTo - 1); i >= 0; i--) { |
||||
if (target.options[i].disabled === false) { |
||||
if (isIE) { |
||||
option = target.options[i].removeNode(true); |
||||
option.selected = QFAMS.env.persistantSelection; |
||||
source.appendChild(option); |
||||
} else { |
||||
option = target.options[i].cloneNode(true); |
||||
option.selected = QFAMS.env.persistantSelection; |
||||
source.options[source.options.length] = option; |
||||
} |
||||
} |
||||
} |
||||
if (!isIE) { |
||||
for (i = (maxTo - 1); i >= 0; i--) { |
||||
if (target.options[i].disabled === false) { |
||||
target.options[i] = null; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// updates unselected item count
|
||||
c = document.getElementById(qfamsName + '_unselected'); |
||||
s = document.getElementById(qfamsName + '-f'); |
||||
QFAMS.updateCounter(c, s.length); |
||||
|
||||
// updates selected item count
|
||||
c = document.getElementById(qfamsName + '_selected'); |
||||
s = document.getElementById(qfamsName + '-t'); |
||||
QFAMS.updateCounter(c, s.length); |
||||
|
||||
// Sort list if required
|
||||
if (arrange !== 'none') { |
||||
QFAMS.sortList(target, QFAMS.compareText, arrange); |
||||
} |
||||
|
||||
// Set the appropriate items as 'selected in the hidden select.
|
||||
// These are the values that will actually be posted with the form.
|
||||
QFAMS.updateHidden(selectHidden, selectRight); |
||||
|
||||
// Order alphabetically
|
||||
|
||||
//var sourceId = $(source).attr('id');
|
||||
var targetId = $(target).attr('id'); |
||||
var options = $('#' + targetId +' option'); |
||||
|
||||
var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get(); |
||||
arr.sort(function (o1, o2) { |
||||
//return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0;
|
||||
// Ignore case
|
||||
var t1 = o1.t.toLowerCase(), t2 = o2.t.toLowerCase(); |
||||
return t1 > t2 ? 1 : t1 < t2 ? -1 : 0; |
||||
}); |
||||
|
||||
options.each(function(i, o) { |
||||
o.value = arr[i].v; |
||||
$(o).text(arr[i].t); |
||||
}); |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.sortList to |
||||
* sort selection list if option is given in HTML_QuickForm_advmultiselect class constructor |
||||
* |
||||
* @param dom element list Selection data list |
||||
* @param prototype compareFunction to sort each element of a list |
||||
* @param string arrange Sort option (none, asc, desc) |
||||
* |
||||
* @method sortList |
||||
* @static |
||||
* @return void |
||||
* @private |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.sortList = function (list, compareFunction, arrange) |
||||
{ |
||||
var i; |
||||
var options = new Array(list.options.length); |
||||
|
||||
for (i = 0; i < options.length; i++) { |
||||
options[i] = new Option(list.options[i].text, |
||||
list.options[i].value, |
||||
list.options[i].defaultSelected, |
||||
list.options[i].selected); |
||||
} |
||||
options.sort(compareFunction); |
||||
if (arrange === 'desc') { |
||||
options.reverse(); |
||||
} |
||||
list.options.length = 0; |
||||
for (i = 0; i < options.length; i++) { |
||||
list.options[i] = options[i]; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* QFAMS.compareText |
||||
* is a callback function to sort each element of two lists A and B |
||||
* |
||||
* @param string option1 single element of list A |
||||
* @param string option2 single element of list B |
||||
* |
||||
* @method compareText |
||||
* @static |
||||
* @return integer -1 if option1 is less than option2, |
||||
* 0 if option1 is equal to option2 |
||||
* 1 if option1 is greater than option2 |
||||
* @private |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.compareText = function (option1, option2) { |
||||
if (option1.text === option2.text) { |
||||
return 0; |
||||
} |
||||
return option1.text < option2.text ? -1 : 1; |
||||
}; |
||||
|
||||
/** |
||||
* QFAMS.updateHidden |
||||
* updates the private list that handle selection of all elements (selected and unselected) |
||||
* |
||||
* @param dom element h hidden list (contains all elements) |
||||
* @param dom element r selection list (contains only elements selected) |
||||
* |
||||
* @method updateHidden |
||||
* @static |
||||
* @return void |
||||
* @private |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.updateHidden = function (h, r) { |
||||
var i; |
||||
|
||||
for (i = 0; i < h.length; i++) { |
||||
h.options[i].selected = false; |
||||
} |
||||
|
||||
for (i = 0; i < r.length; i++) { |
||||
h.options[h.length] = new Option(r.options[i].text, r.options[i].value); |
||||
h.options[h.length - 1].selected = true; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* With QFAMS.moveUp |
||||
* end-user may arrange and element up to the selection list |
||||
* |
||||
* @param dom element l selection list (contains only elements selected) |
||||
* @param dom element h hidden list (contains all elements) |
||||
* |
||||
* @method moveUp |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveUp = function (l, h) { |
||||
var indice = l.selectedIndex; |
||||
if (indice < 0) { |
||||
return; |
||||
} |
||||
if (indice > 0) { |
||||
QFAMS.moveSwap(l, indice, indice - 1); |
||||
QFAMS.updateHidden(h, l); |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* With QFAMS.moveDown |
||||
* end-user may arrange and element down to the selection list |
||||
* |
||||
* @param dom element l selection list (contains only elements selected) |
||||
* @param dom element h hidden list (contains all elements) |
||||
* |
||||
* @method moveDown |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveDown = function (l, h) { |
||||
var indice = l.selectedIndex; |
||||
if (indice < 0) { |
||||
return; |
||||
} |
||||
if (indice < l.options.length - 1) { |
||||
QFAMS.moveSwap(l, indice, indice + 1); |
||||
QFAMS.updateHidden(h, l); |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* With QFAMS.moveTop |
||||
* end-user may arrange and element up to the top of selection list |
||||
* |
||||
* @param dom element l selection list (contains only elements selected) |
||||
* @param dom element h hidden list (contains all elements) |
||||
* |
||||
* @method moveTop |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveTop = function (l, h) { |
||||
var indice = l.selectedIndex; |
||||
if (indice < 0) { |
||||
return; |
||||
} |
||||
while (indice > 0) { |
||||
QFAMS.moveSwap(l, indice, indice - 1); |
||||
QFAMS.updateHidden(h, l); |
||||
indice--; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* With QFAMS.moveBottom |
||||
* end-user may arrange and element down to the bottom of selection list |
||||
* |
||||
* @param dom element l selection list (contains only elements selected) |
||||
* @param dom element h hidden list (contains all elements) |
||||
* |
||||
* @method moveBottom |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveBottom = function (l, h) { |
||||
var indice = l.selectedIndex; |
||||
if (indice < 0) { |
||||
return; |
||||
} |
||||
while (indice < l.options.length - 1) { |
||||
QFAMS.moveSwap(l, indice, indice + 1); |
||||
QFAMS.updateHidden(h, l); |
||||
indice++; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* With QFAMS.moveSwap |
||||
* end-user may invert two elements position in the selection list |
||||
* |
||||
* @param dom element l selection list (contains only elements selected) |
||||
* @param integer i element source indice |
||||
* @param integer j element target indice |
||||
* |
||||
* @method moveSwap |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.moveSwap = function (l, i, j) { |
||||
var node; |
||||
|
||||
node = l.replaceChild(l.options[i], l.options[j]); |
||||
if (i > j) { |
||||
l.insertBefore(node, l.options[j].nextSibling); |
||||
} else { |
||||
l.insertBefore(node, l.options[i]); |
||||
} |
||||
|
||||
if (QFAMS.env.persistantMove) { |
||||
l.selectedIndex = j; |
||||
} else { |
||||
l.selectedIndex = -1; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* Uses QFAMS.init to |
||||
* initialize onclick event handler for all checkbox element |
||||
* of a QuickForm advmultiselect element with single select box. |
||||
* |
||||
* @method init |
||||
* @static |
||||
* @return void |
||||
* @public |
||||
* @since 1.5.0 |
||||
*/ |
||||
QFAMS.init = function (elm) |
||||
{ |
||||
var e, i; |
||||
|
||||
for (e = 0; e < elm.length; e++) { |
||||
var div = document.getElementById('qfams_' + elm[e]); |
||||
if (div !== null) { |
||||
var inputs = div.getElementsByTagName('input'); |
||||
if (inputs !== null) { |
||||
for (i = 0; i < inputs.length; i++) { |
||||
inputs[i].onclick = QFAMS.updateLiveCounter; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
$(function() { |
||||
|
||||
$('.advmultiselect_checkbox').click(function() { |
||||
var id = $(this).attr('id'); |
||||
var selectName = id + '-f'; |
||||
var selectId = selectName.replace('_select_all', ''); |
||||
var selectDestinationId = selectId.replace('-f', '-t'); |
||||
|
||||
$('#'+selectDestinationId).prop("disabled", false); |
||||
|
||||
var checked = !$('#'+ id).is(':checked'); |
||||
if (!checked) { |
||||
$('#users-f option').prop('selected', true); |
||||
QFAMS.moveSelection('users', this.form.elements['users-f[]'], this.form.elements['users-t[]'], this.form.elements['users[]'], 'add', 'none'); |
||||
} else { |
||||
$('#users-t option').prop('selected', true); |
||||
QFAMS.moveSelection('users', this.form.elements['users-f[]'], this.form.elements['users-t[]'], this.form.elements['users[]'], 'remove', 'none'); |
||||
} |
||||
}); |
||||
}); |
@ -0,0 +1,397 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
use Chamilo\CoreBundle\Entity\Repository\LegalRepository; |
||||
|
||||
/** |
||||
* @package chamilo.messages |
||||
*/ |
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
|
||||
api_block_anonymous_users(); |
||||
|
||||
if (!api_get_configuration_value('enable_gdpr')) { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
$userId = api_get_user_id(); |
||||
$userInfo = api_get_user_info(); |
||||
|
||||
$substitutionTerms = [ |
||||
'password' => get_lang('EncryptedData'), |
||||
'salt' => get_lang('RandomData'), |
||||
'empty' => get_lang('NoData'), |
||||
]; |
||||
|
||||
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; |
||||
$formToString = ''; |
||||
|
||||
if (api_get_setting('allow_terms_conditions') === 'true') { |
||||
$form = new FormValidator('delete_term', 'post', api_get_self().'?action=delete_legal&user_id='.$userId); |
||||
$form->addHtml(Display::return_message(get_lang('WhyYouWantToDeleteYourLegalAgreement'))); |
||||
$form->addTextarea('explanation', get_lang('ExplanationDeleteLegal'), [], true); |
||||
$form->addHidden('action', 'delete_legal'); |
||||
$form->addButtonSave(get_lang('DeleteLegal')); |
||||
$formToString = $form->returnForm(); |
||||
|
||||
$formDelete = new FormValidator('delete_account', 'post', api_get_self().'?action=delete_account&user_id='.$userId); |
||||
$formDelete->addTextarea('explanation', get_lang('ExplanationDeleteAccount'), [], true); |
||||
$formDelete->addHidden('action', 'delete_account'); |
||||
$formDelete->addButtonDelete(get_lang('DeleteAccount')); |
||||
$formToString .= $formDelete->returnForm(); |
||||
} |
||||
|
||||
switch ($action) { |
||||
case 'send_legal': |
||||
$language = api_get_interface_language(); |
||||
$language = api_get_language_id($language); |
||||
$terms = LegalManager::get_last_condition($language); |
||||
if (!$terms) { |
||||
//look for the default language |
||||
$language = api_get_setting('platformLanguage'); |
||||
$language = api_get_language_id($language); |
||||
$terms = LegalManager::get_last_condition($language); |
||||
} |
||||
|
||||
$legalAcceptType = $terms['version'].':'.$terms['language_id'].':'.time(); |
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'legal_accept', |
||||
$legalAcceptType |
||||
); |
||||
|
||||
Event::addEvent( |
||||
LOG_TERM_CONDITION_ACCEPTED, |
||||
LOG_USER_OBJECT, |
||||
api_get_user_info($userId), |
||||
api_get_utc_datetime() |
||||
); |
||||
|
||||
$bossList = UserManager::getStudentBossList($userId); |
||||
if (!empty($bossList)) { |
||||
$bossList = array_column($bossList, 'boss_id'); |
||||
$currentUserInfo = api_get_user_info($userId); |
||||
foreach ($bossList as $bossId) { |
||||
$subjectEmail = sprintf( |
||||
get_lang('UserXSignedTheAgreement'), |
||||
$currentUserInfo['complete_name'] |
||||
); |
||||
$contentEmail = sprintf( |
||||
get_lang('UserXSignedTheAgreementTheDateY'), |
||||
$currentUserInfo['complete_name'], |
||||
api_get_local_time($time) |
||||
); |
||||
|
||||
MessageManager::send_message_simple( |
||||
$bossId, |
||||
$subjectEmail, |
||||
$contentEmail, |
||||
$user_id |
||||
); |
||||
} |
||||
} |
||||
Display::addFlash(Display::return_message(get_lang('Saved'))); |
||||
break; |
||||
case 'delete_account': |
||||
if ($formDelete->validate()) { |
||||
$explanation = $formDelete->getSubmitValue('explanation'); |
||||
UserManager::createDataPrivacyExtraFields(); |
||||
|
||||
// Remove delete agreement if it was sent: |
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_legal_agreement_consent_removal', |
||||
'' |
||||
); |
||||
|
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_legal_agreement_consent_removal_justification', |
||||
'' |
||||
); |
||||
|
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_delete_account', |
||||
1 |
||||
); |
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_delete_account_justification', |
||||
$explanation |
||||
); |
||||
|
||||
Display::addFlash(Display::return_message(get_lang('Saved'))); |
||||
Event::addEvent( |
||||
LOG_USER_DELETE_ACCOUNT_REQUEST, |
||||
LOG_USER_OBJECT, |
||||
$userInfo |
||||
); |
||||
|
||||
$url = api_get_path(WEB_CODE_PATH).'admin/'; |
||||
$link = Display::url($url, $url); |
||||
$subject = get_lang('RequestForDeleteAccount'); |
||||
$content = sprintf( |
||||
get_lang('TheUserXAskDeleteAccountWithJustifactionXGoHereX'), |
||||
$userInfo['complete_name'], |
||||
$explanation, |
||||
$link |
||||
); |
||||
|
||||
$email = api_get_configuration_value('data_protection_officer_email'); |
||||
if (!empty($email)) { |
||||
api_mail_html('', $email, $subject, $content); |
||||
} else { |
||||
MessageManager::sendMessageToAllAdminUsers(api_get_user_id(), $subject, $content); |
||||
} |
||||
} |
||||
break; |
||||
case 'delete_legal': |
||||
if ($form->validate()) { |
||||
$explanation = $form->getSubmitValue('explanation'); |
||||
|
||||
UserManager::createDataPrivacyExtraFields(); |
||||
|
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_legal_agreement_consent_removal', |
||||
1 |
||||
); |
||||
|
||||
UserManager::update_extra_field_value( |
||||
$userId, |
||||
'request_for_legal_agreement_consent_removal_justification', |
||||
$explanation |
||||
); |
||||
|
||||
/*$extraFieldValue = new ExtraFieldValue('user'); |
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable( |
||||
$userId, |
||||
'legal_accept' |
||||
); |
||||
$result = $extraFieldValue->delete($value['id']);*/ |
||||
|
||||
Display::addFlash(Display::return_message(get_lang('Sent'))); |
||||
|
||||
Event::addEvent( |
||||
LOG_USER_REMOVED_LEGAL_ACCEPT, |
||||
LOG_USER_OBJECT, |
||||
$userInfo |
||||
); |
||||
|
||||
$url = api_get_path(WEB_CODE_PATH).'admin/'; |
||||
$link = Display::url($url, $url); |
||||
$subject = get_lang('RequestForLegalConsentRemoval'); |
||||
$content = sprintf( |
||||
get_lang('TheUserXAskRemovalWithJustifactionXGoHereX'), |
||||
$userInfo['complete_name'], |
||||
$explanation, |
||||
$link |
||||
); |
||||
|
||||
$email = api_get_configuration_value('data_protection_officer_email'); |
||||
if (!empty($email)) { |
||||
api_mail_html('', $email, $subject, $content); |
||||
} else { |
||||
MessageManager::sendMessageToAllAdminUsers(api_get_user_id(), $subject, $content); |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
|
||||
$propertiesToJson = UserManager::getRepository()->getPersonalDataToJson($userId, $substitutionTerms); |
||||
|
||||
if (!empty($_GET['export'])) { |
||||
$filename = md5(mt_rand(0, 1000000)).'.json'; |
||||
$path = api_get_path(SYS_ARCHIVE_PATH).$filename; |
||||
$writeResult = file_put_contents($path, $propertiesToJson); |
||||
if ($writeResult !== false) { |
||||
DocumentManager::file_send_for_download($path, true, $filename); |
||||
exit; |
||||
} |
||||
} |
||||
|
||||
$allowSocial = api_get_setting('allow_social_tool') === 'true'; |
||||
|
||||
$nameTools = get_lang('PersonalDataReport'); |
||||
$show_message = null; |
||||
|
||||
if ($allowSocial) { |
||||
$this_section = SECTION_SOCIAL; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_PATH).'main/social/home.php', |
||||
'name' => get_lang('SocialNetwork'), |
||||
]; |
||||
} else { |
||||
$this_section = SECTION_MYPROFILE; |
||||
$interbreadcrumb[] = [ |
||||
'url' => api_get_path(WEB_PATH).'main/auth/profile.php', |
||||
'name' => get_lang('Profile'), |
||||
]; |
||||
} |
||||
|
||||
$interbreadcrumb[] = ['url' => '#', 'name' => get_lang('PersonalDataReport')]; |
||||
|
||||
// LEFT CONTENT |
||||
$socialMenuBlock = ''; |
||||
if ($allowSocial) { |
||||
// Block Social Menu |
||||
$socialMenuBlock = SocialManager::show_social_menu('personal-data'); |
||||
} |
||||
|
||||
// MAIN CONTENT |
||||
$personalDataContent = '<ul>'; |
||||
$properties = json_decode($propertiesToJson); |
||||
|
||||
foreach ($properties as $key => $value) { |
||||
if (is_array($value) || is_object($value)) { |
||||
switch ($key) { |
||||
case 'extraFields': |
||||
$personalDataContent .= '<li>'.$key.': </li><ul>'; |
||||
foreach ($value as $subValue) { |
||||
$personalDataContent .= '<li>'.$subValue->variable.': '.$subValue->value.'</li>'; |
||||
} |
||||
$personalDataContent .= '</ul>'; |
||||
break; |
||||
case 'portals': |
||||
case 'roles': |
||||
case 'achievedSkills': |
||||
case 'sessionAsGeneralCoach': |
||||
case 'classes': |
||||
case 'courses': |
||||
case 'groupNames': |
||||
case 'groups': |
||||
$personalDataContent .= '<li>'.$key.': </li><ul>'; |
||||
foreach ($value as $subValue) { |
||||
$personalDataContent .= '<li>'.$subValue.'</li>'; |
||||
} |
||||
$personalDataContent .= '</ul>'; |
||||
break; |
||||
case 'sessionCourseSubscriptions': |
||||
$personalDataContent .= '<li>'.$key.': </li><ul>'; |
||||
foreach ($value as $session => $courseList) { |
||||
$personalDataContent .= '<li>'.$session.'<ul>'; |
||||
foreach ($courseList as $course) { |
||||
$personalDataContent .= '<li>'.$course.'</li>'; |
||||
} |
||||
$personalDataContent .= '</ul>'; |
||||
} |
||||
$personalDataContent .= '</ul>'; |
||||
break; |
||||
default: |
||||
//var_dump($key); |
||||
break; |
||||
} |
||||
|
||||
/*foreach ($value as $subValue) { |
||||
foreach ($subValue as $subSubValue) { |
||||
var_dump($subSubValue); |
||||
//$personalDataContent .= '<li>'.$subSubValue.'</li>'; |
||||
} |
||||
}*/ |
||||
//skip in some cases |
||||
/*sif (!empty($value['date'])) { |
||||
$personalDataContent .= '<li>'.$key.': '.$value['date'].'</li>'; |
||||
} else { |
||||
$personalDataContent .= '<li>'.$key.': '.get_lang('ComplexDataNotShown').'</li>'; |
||||
}*/ |
||||
} else { |
||||
$personalDataContent .= '<li>'.$key.': '.$value.'</li>'; |
||||
} |
||||
} |
||||
$personalDataContent .= '</ul>'; |
||||
|
||||
// Check terms acceptation |
||||
$permitionBlock = ''; |
||||
if (api_get_setting('allow_terms_conditions') === 'true') { |
||||
$extraFieldValue = new ExtraFieldValue('user'); |
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable( |
||||
$userId, |
||||
'legal_accept' |
||||
); |
||||
$permitionBlock .= Display::return_icon('accept_na.png', get_lang('NotAccepted')); |
||||
if (isset($value['value']) && !empty($value['value'])) { |
||||
list($legalId, $legalLanguageId, $legalTime) = explode(':', $value['value']); |
||||
$permitionBlock = get_lang('CurrentStatus').': '. |
||||
Display::return_icon('accept.png', get_lang('LegalAgreementAccepted')).get_lang('LegalAgreementAccepted'). |
||||
'<br />'; |
||||
$permitionBlock .= get_lang('Date').': '.api_get_local_time($legalTime).'<br />'; |
||||
$permitionBlock .= $formToString; |
||||
|
||||
/*$permitionBlock .= Display::url( |
||||
get_lang('DeleteLegal'), |
||||
api_get_self().'?action=delete_legal&user_id='.$userId, |
||||
['class' => 'btn btn-danger btn-xs'] |
||||
);*/ |
||||
} else { |
||||
// @TODO add action handling for button |
||||
$permitionBlock .= Display::url( |
||||
get_lang('SendLegal'), |
||||
api_get_self().'?action=send_legal&user_id='.$userId, |
||||
['class' => 'btn btn-primary btn-xs'] |
||||
); |
||||
} |
||||
} else { |
||||
$permitionBlock .= get_lang('NoTermsAndConditionsAvailable'); |
||||
} |
||||
|
||||
//Build the final array to pass to template |
||||
$personalData = []; |
||||
$personalData['data'] = $personalDataContent; |
||||
//$personalData['responsible'] = api_get_setting('personal_data_responsible_org'); |
||||
|
||||
$em = Database::getManager(); |
||||
/** @var LegalRepository $legalTermsRepo */ |
||||
$legalTermsRepo = $em->getRepository('ChamiloCoreBundle:Legal'); |
||||
// Get data about the treatment of data |
||||
$treatmentTypes = LegalManager::getTreatmentTypeList(); |
||||
|
||||
foreach ($treatmentTypes as $id => $item) { |
||||
$personalData['treatment'][$item]['title'] = get_lang('PersonalData'.ucfirst($item).'Title'); |
||||
$legalTerm = $legalTermsRepo->findOneByTypeAndLanguage($id, api_get_language_id($user_language)); |
||||
$legalTermContent = ''; |
||||
if (!empty($legalTerm[0]) && is_array($legalTerm[0])) { |
||||
$legalTermContent = $legalTerm[0]['content']; |
||||
} |
||||
$personalData['treatment'][$item]['content'] = $legalTermContent; |
||||
} |
||||
$officerName = api_get_configuration_value('data_protection_officer_name'); |
||||
$officerRole = api_get_configuration_value('data_protection_officer_role'); |
||||
$officerEmail = api_get_configuration_value('data_protection_officer_email'); |
||||
if (!empty($officerName)) { |
||||
$personalData['officer_name'] = $officerName; |
||||
$personalData['officer_role'] = $officerRole; |
||||
$personalData['officer_email'] = $officerEmail; |
||||
} |
||||
|
||||
$tpl = new Template(null); |
||||
|
||||
$actions = Display::url( |
||||
Display::return_icon('excel.png', get_lang('Export'), [], ICON_SIZE_MEDIUM), |
||||
api_get_path(WEB_CODE_PATH).'social/personal_data.php?export=1' |
||||
); |
||||
|
||||
$tpl->assign('actions', Display::toolbarAction('toolbar', [$actions])); |
||||
|
||||
$termLink = ''; |
||||
if (api_get_setting('allow_terms_conditions') === 'true') { |
||||
$url = api_get_path(WEB_CODE_PATH).'social/terms.php'; |
||||
$termLink = Display::url($url, $url); |
||||
} |
||||
|
||||
// Block Social Avatar |
||||
SocialManager::setSocialUserBlock($tpl, api_get_user_id(), 'messages'); |
||||
if (api_get_setting('allow_social_tool') === 'true') { |
||||
$tpl->assign('social_menu_block', $socialMenuBlock); |
||||
$tpl->assign('personal_data', $personalData); |
||||
} else { |
||||
$tpl->assign('social_menu_block', ''); |
||||
$tpl->assign('personal_data_block', $personalDataContent); |
||||
} |
||||
|
||||
$tpl->assign('permission', $permitionBlock); |
||||
$tpl->assign('term_link', $termLink); |
||||
$socialLayout = $tpl->get_template('social/personal_data.tpl'); |
||||
$tpl->display($socialLayout); |
@ -0,0 +1,52 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
$cidReset = true; |
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php'; |
||||
|
||||
if (api_get_setting('allow_terms_conditions') !== 'true') { |
||||
api_not_allowed(true); |
||||
} |
||||
|
||||
api_block_anonymous_users(); |
||||
|
||||
$language = api_get_interface_language(); |
||||
$language = api_get_language_id($language); |
||||
$term = LegalManager::get_last_condition($language); |
||||
|
||||
if (!$term) { |
||||
// look for the default language |
||||
$language = api_get_setting('platformLanguage'); |
||||
$language = api_get_language_id($language); |
||||
$term = LegalManager::get_last_condition($language); |
||||
} |
||||
|
||||
$socialMenuBlock = ''; |
||||
$allowSocial = api_get_setting('allow_social_tool') === 'true'; |
||||
|
||||
if ($allowSocial) { |
||||
// Block Social Menu |
||||
$socialMenuBlock = SocialManager::show_social_menu('personal-data'); |
||||
} |
||||
|
||||
$tpl = new Template(null); |
||||
|
||||
$actions = Display::url( |
||||
Display::return_icon('back.png', get_lang('Back'), [], ICON_SIZE_MEDIUM), |
||||
api_get_path(WEB_CODE_PATH).'social/personal_data.php' |
||||
); |
||||
|
||||
$tpl->assign('actions', Display::toolbarAction('toolbar', [$actions])); |
||||
|
||||
// Block Social Avatar |
||||
SocialManager::setSocialUserBlock($tpl, api_get_user_id(), 'messages'); |
||||
if (api_get_setting('allow_social_tool') === 'true') { |
||||
$tpl->assign('social_menu_block', $socialMenuBlock); |
||||
} else { |
||||
$tpl->assign('social_menu_block', ''); |
||||
} |
||||
$tpl->assign('term', $term); |
||||
|
||||
$socialLayout = $tpl->get_template('social/terms.tpl'); |
||||
$tpl->display($socialLayout); |
Loading…
Reference in new issue