Minor: Format code

pull/5783/head
Angel Fernando Quiroz Campos 1 year ago
parent d17817a0e5
commit 8074dcf81d
No known key found for this signature in database
GPG Key ID: B284841AE3E562CD
  1. 4
      main/admin/add_users_to_usergroup.php
  2. 1
      main/attendance/my_missing_signatures.php
  3. 2
      main/auth/justification.php
  4. 34
      main/common_cartridge/export/Cc13Convert.php
  5. 8
      main/common_cartridge/export/Cc13ExportConvert.php
  6. 4
      main/common_cartridge/export/src/converter/CcConverterQuiz.php
  7. 2
      main/common_cartridge/export/src/lib/assesment/CcAssesmentHelper.php
  8. 2
      main/common_cartridge/export/src/lib/assesment/CcAssesmentQuestionFib.php
  9. 1
      main/common_cartridge/export/src/lib/assesment/CcAssesmentRenderFibtype.php
  10. 17
      main/common_cartridge/export/src/utils/CcHelpers.php
  11. 5
      main/common_cartridge/import/Cc1p3Convert.php
  12. 4
      main/common_cartridge/import/Imscc13Import.php
  13. 4
      main/common_cartridge/import/src/base/CcBase.php
  14. 8
      main/common_cartridge/import/src/converter/Cc13Quiz.php
  15. 19
      main/gradebook/all_my_gradebooks.php
  16. 2
      main/inc/ajax/announcement.ajax.php
  17. 1
      main/inc/ajax/user_manager.ajax.php
  18. 13
      main/inc/lib/CoursesAndSessionsCatalog.class.php
  19. 22
      main/inc/lib/api.lib.php
  20. 2
      main/inc/lib/attendance.lib.php
  21. 2
      main/inc/lib/course.lib.php
  22. 14
      main/inc/lib/course_request.lib.php
  23. 1
      main/inc/lib/document.lib.php
  24. 2
      main/inc/lib/events.lib.php
  25. 36
      main/inc/lib/security.lib.php
  26. 8
      main/inc/lib/sessionmanager.lib.php
  27. 106
      main/inc/lib/statistics.lib.php
  28. 219
      main/inc/lib/tracking.lib.php
  29. 4
      main/inc/lib/usergroup.lib.php
  30. 85
      main/inc/lib/usermanager.lib.php
  31. 2
      main/inc/lib/userportal.lib.php
  32. 45
      main/inc/lib/webservices/Rest.php
  33. 3
      main/inc/lib/webservices/WebService.class.php
  34. 4
      main/mySpace/index.php
  35. 6
      main/mySpace/time_report.php
  36. 2
      main/wiki/wiki.inc.php
  37. 4
      src/Chamilo/CourseBundle/Component/CourseCopy/CourseSelectForm.php

@ -371,11 +371,11 @@ echo '<a href="'.api_get_self().'?id='.$id.'&action=export">'.
$isActiveUser = !empty($activeUser);
$activeUsersParam = $isActiveUser ? '0' : '1';
$newUrl = api_get_self() . '?id=' . $id . '&active_users=' . $activeUsersParam;
$newUrl = api_get_self().'?id='.$id.'&active_users='.$activeUsersParam;
$buttonLabelKey = $isActiveUser ? 'ShowAllUsers' : 'OnlyShowActiveUsers';
$buttonLabel = get_lang($buttonLabelKey);
echo '<a href="#" onclick="activeUsers(\'' . htmlspecialchars($newUrl) . '\'); return false;" class="btn btn-default">' . $buttonLabel . '</a>';
echo '<a href="#" onclick="activeUsers(\''.htmlspecialchars($newUrl).'\'); return false;" class="btn btn-default">'.$buttonLabel.'</a>';
echo '</div>';

@ -76,7 +76,6 @@ foreach ($calendars as $calendar) {
$presences[$calendar['courseId']]['calendars'][$calendar['calendarId']]['date_time'] = api_convert_and_format_date($calendar['date_time'], null, date_default_timezone_get());
}
$template = new Template(get_lang('MyMissingSignatures'));
$template->assign('presences', $presences);
$content = $template->fetch($template->get_template('/attendance/my_missing_signatures.tpl'));

@ -87,7 +87,7 @@ switch ($action) {
$notificationEmailSubject = $plugin->get_lang('JustificationsCompleted').': '.$userInfo['complete_name'];
$notificationEmailContent = $notificationEmailSubject.' <br /><br />'.'<a href="'.$link.'">'.$link.'</a>';
if (api_get_plugin_setting('justification', 'notification_to_creator_only') === 'true') {
$sql = "select creator_id from user where user_id = " . api_get_user_id();
$sql = "select creator_id from user where user_id = ".api_get_user_id();
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
$row = Database::fetch_array($result);

@ -4,14 +4,15 @@
class Cc13Convert
{
/**
* Converts a course object into a CC13 package and writes it to disk
* @param string $packagedir
* @param string $outdir
* Converts a course object into a CC13 package and writes it to disk.
*
* @param \Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse The Course object is "augmented" with info from the api_get_course_info() function, into the "$objCourse->info" array attribute.
* @return bool
*
* @throws Exception
*
* @return bool
*/
public static function convert(string $packagedir, string $outdir, \Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse)
public static function convert(string $packagedir, string $outdir, Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse)
{
$dir = realpath($packagedir);
if (empty($dir)) {
@ -131,12 +132,11 @@ class Cc13Convert
}
/**
* Return array of type $sections[1]['quiz', [sequence]] where sequence is the result of a call to getSequence()
* @param array $itemData
* @param string $itemType
* @param int $count
* @param string $courseCode The course code litteral
* Return array of type $sections[1]['quiz', [sequence]] where sequence is the result of a call to getSequence().
*
* @param string $courseCode The course code litteral
* @param ?array $itmesExtraData If defined, represents the items IDs selected in the course export form
*
* @return array
* @reference self::getSequence()
*/
@ -192,11 +192,13 @@ class Cc13Convert
/**
* Return array of items by category and item ID ("test" level, not "question" level) with details like title,
* comment (description), type, questions, max_attempt, etc.
* @param array $objItems Array of item objects as returned by the course backup code
* @param ?int $categoryId
*
* @param array $objItems Array of item objects as returned by the course backup code
* @param ?int $categoryId
* @param ?string $itemType
* @param ?string $coursecode
* @param ?array $itemQuestions
* @param ?array $itemQuestions
*
* @return array|mixed
*/
protected static function getSequence(array $objItems, ?int $categoryId = null, ?string $itemType = null, ?string $coursecode = null, ?array $itemQuestions = null)
@ -309,11 +311,7 @@ class Cc13Convert
* Process the different types of activities exported from the course.
* When dealing with tests, the "sequence" provided here is a test, not a question.
* For each sequence, call the corresponding CcConverter[Type] object instantiation method in export/src/converter/.
* @param CcIItem $item
* @param CcIManifest $manifest
* @param array $sequence
* @param string $packageroot
* @param string $outdir
*
* @return void
*/
protected static function processSequence(CcIItem &$item, CcIManifest &$manifest, array $sequence, string $packageroot, string $outdir)

@ -6,8 +6,10 @@ use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver;
class Cc13ExportConvert
{
/**
* Export the CommonCartridge object to the app/cache/course_backups/CourseCC13Archiver_[hash] directory
* Export the CommonCartridge object to the app/cache/course_backups/CourseCC13Archiver_[hash] directory.
*
* @param \Chamilo\CourseBundle\Component\CourseCopy\Course $objCourse
*
* @return false|string
*/
public static function export($objCourse)
@ -33,8 +35,10 @@ class Cc13ExportConvert
/**
* @param $backupDir
* @param $objCourse
* @return string Filename of the created .imscc (zip) file
*
* @throws Exception
*
* @return string Filename of the created .imscc (zip) file
*/
public static function createImscc($backupDir, $objCourse)
{

@ -12,9 +12,11 @@ class CcConverterQuiz extends CcConverters
}
/**
* Convert a quiz to a CC XML file (.xml) in a subfolder of the whole CC archive
* Convert a quiz to a CC XML file (.xml) in a subfolder of the whole CC archive.
*
* @param $outdir
* @param $objQuizz
*
* @return bool true
*/
public function convert($outdir, $objQuizz): bool

@ -102,7 +102,7 @@ abstract class CcAssesmentHelper
* @param cc_assesment_section $section
* @param unknown_type $rootpath
* @param unknown_type $contextid
* @param string $outdir
* @param string $outdir
*/
public static function processQuestions(&$objQuizz, &$manifest, CcAssesmentSection &$section, $rootpath, $contextid, $outdir)
{

@ -32,7 +32,7 @@ class CcAssesmentQuestionFib extends CcAssesmentQuestionProcBase
'ponderation' => $answerScore,
'comment' => $answer['comment'],
];
$questionScore ++;
$questionScore++;
}
if (count($correctAnswerNodes) == 0) {
throw new RuntimeException('No correct answer!');

@ -21,6 +21,7 @@ class CcAssesmentRenderFibtype extends CcQuestionMetadataBase
$this->setSetting(CcQtiTags::FIBTYPE, CcQtiValues::STRING);
$this->qtype = CcQtiProfiletype::FIELD_ENTRY;
}
public function add_material(CcAssesmentMaterial $object)
{
$this->materials[] = $object;

@ -88,8 +88,6 @@ abstract class CcHelpers
/**
* Get list of embedded files.
*
* @param string $html
*
* @return multitype:mixed
*/
public static function embeddedFiles(string $html, string $courseDir = null)
@ -114,11 +112,13 @@ abstract class CcHelpers
}
/**
* Return an array of static media dependencies found in a given document file or a document and its neighbours in the same folder
* Return an array of static media dependencies found in a given document file or a document and its neighbours in the same folder.
*
* @param $packageroot
* @param $contextid
* @param $folder
* @param $docfilepath
*
* @return array
*/
public static function embeddedMapping($packageroot, $contextid = null, $folder = null, $docfilepath = null)
@ -260,13 +260,15 @@ abstract class CcHelpers
}
/**
* Detect embedded files in the given HTML string
* @param string $content The HTML string content
* @param CcIManifest $manifest Manifest object (usually empty at this point) that will be filled
* Detect embedded files in the given HTML string.
*
* @param string $content The HTML string content
* @param CcIManifest $manifest Manifest object (usually empty at this point) that will be filled
* @param $packageroot
* @param $contextid
* @param $outdir
* @param $webcontent
*
* @return array
*/
public static function processLinkedFiles(
@ -276,8 +278,7 @@ abstract class CcHelpers
$contextid,
$outdir,
$webcontent = false
)
{
) {
// Detect all embedded files
// copy all files in the cc package stripping any spaces and using only lowercase letters
// add those files as resources of the type webcontent to the manifest

@ -34,8 +34,7 @@ class Cc1p3Convert extends CcBase
}
/**
* Scan the imsmanifest.xml structure to find elements to import to documents, links, forums, quizzes
* @return void
* Scan the imsmanifest.xml structure to find elements to import to documents, links, forums, quizzes.
*/
public function generateImportData(): void
{
@ -47,7 +46,7 @@ class Cc1p3Convert extends CcBase
// Scan for organization items or resources that are tests (question banks)
$items = $xpath->query('/imscc:manifest/imscc:organizations/imscc:organization/imscc:item | /imscc:manifest/imscc:resources/imscc:resource[@type="'.static::CC_TYPE_QUESTION_BANK.'"]');
$this->createInstances($items, 0,$countInstances);
$this->createInstances($items, 0, $countInstances);
$resources = new Cc13Resource();
$forums = new Cc13Forum();

@ -36,8 +36,10 @@ class Imscc13Import
}
/**
* Read the imsmanifest.xml file in the app/cache/imsccImport temp folder
* Read the imsmanifest.xml file in the app/cache/imsccImport temp folder.
*
* @param $filepath
*
* @return void
*/
public function execute($filepath)

@ -67,8 +67,10 @@ class CcBase
}
/**
* Find the imsmanifest.xml file inside the given folder and return its path
* Find the imsmanifest.xml file inside the given folder and return its path.
*
* @param string $folder Full path name of the folder in which we expect to find imsmanifest.xml
*
* @return false|string
*/
public static function getManifest(string $folder)

@ -4,7 +4,8 @@
class Cc13Quiz extends Cc13Entities
{
/**
* Get all data from the object instance (coming from the xml file) into a clean array
* Get all data from the object instance (coming from the xml file) into a clean array.
*
* @return array
*/
public function generateData()
@ -23,8 +24,10 @@ class Cc13Quiz extends Cc13Entities
}
/**
* Create a quiz based on the information available in the assessment structure
* Create a quiz based on the information available in the assessment structure.
*
* @param $quiz
*
* @return void
*/
public function storeQuiz($quiz)
@ -272,6 +275,7 @@ class Cc13Quiz extends Cc13Entities
$xpath = Cc1p3Convert::newxPath($assessment, Cc1p3Convert::getquizns());
$fieldEntry = $xpath->query('/xmlns:questestinterop/xmlns:assessment/xmlns:rubric/xmlns:material/xmlns:mattext');
$response = !empty($fieldEntry->item(0)->nodeValue) ? $fieldEntry->item(0)->nodeValue : '';
return $response;
}

@ -46,7 +46,7 @@ Display::display_header(get_lang('GlobalGradebook'));
api_block_anonymous_users();
$user_id = api_get_user_id();
$userCoursesList = CourseManager::get_courses_list_by_user_id ($user_id, true, false, false, [], true, true);
$userCoursesList = CourseManager::get_courses_list_by_user_id($user_id, true, false, false, [], true, true);
foreach ($userCoursesList as $course) {
$course_code = $course['code'];
@ -60,9 +60,9 @@ foreach ($userCoursesList as $course) {
$courseInfo = api_get_course_info($course_code);
if (!empty($course['session_name'])) {
$title = "<h2>" . $courseInfo['title'] . " (" . $course['session_name'] . ")</h2>";
$title = "<h2>".$courseInfo['title']." (".$course['session_name'].")</h2>";
} else {
$title = "<h2>" . $courseInfo['title'] . "</h2>";
$title = "<h2>".$courseInfo['title']."</h2>";
}
$cats = Category::load(
@ -75,18 +75,18 @@ foreach ($userCoursesList as $course) {
false
);
$showTitle = true;
$showTitle = true;
foreach ($cats as $cat) {
$allcat = $cat->get_subcategories($stud_id, $course_code, $session_id);
$alleval = $cat->get_evaluations($stud_id, false, $course_code, $session_id);
$alllink = $cat->get_links($stud_id, true, $course_code, $session_id);
if ($cat->get_parent_id() != 0) {
$i++;
} else {
if (empty($allcat) && empty($alleval) && empty($alllink)) {
continue;
}
} else {
if (empty($allcat) && empty($alleval) && empty($alllink)) {
continue;
}
if ($showTitle) {
echo $title;
$showTitle = false;
@ -126,4 +126,3 @@ $showTitle = true;
}
Display::display_footer();

@ -54,7 +54,7 @@ switch ($action) {
if ($groupProperties['announcements_state'] == GroupManager::TOOL_PRIVATE_BETWEEN_USERS) {
// check if user is a group member to give access
$groupInfo = GroupManager::get_group_properties($groupId);
if (array_key_exists($currentUserId,GroupManager::get_subscribed_users($groupInfo))) {
if (array_key_exists($currentUserId, GroupManager::get_subscribed_users($groupInfo))) {
$allowToEdit = true;
}
}

@ -372,7 +372,6 @@ switch ($action) {
api_not_allowed(false, null, 403);
}
$status = isset($_REQUEST['status']) ? (int) $_REQUEST['status'] : DRH;
$active = isset($_REQUEST['active']) ? (int) $_REQUEST['active'] : null;

@ -317,10 +317,9 @@ class CoursesAndSessionsCatalog
}
/**
* @param string $categoryCode
* @param int $randomValue
* @param array $limit will be used if $randomValue is not set.
* This array should contain 'start' and 'length' keys
* @param int $randomValue
* @param array $limit will be used if $randomValue is not set.
* This array should contain 'start' and 'length' keys
*
* @return array
*/
@ -1856,12 +1855,12 @@ class CoursesAndSessionsCatalog
$pageDiv .= self::getPageNumberItem(
1,
$pageLength,
null,
null,
'',
$categoryCode,
$action,
$fields,
$sortKeys
$fields,
$sortKeys
);
if ($pageBottom > 2) {
$pageDiv .= self::getPageNumberItem(

@ -9443,9 +9443,9 @@ function api_site_use_cookie_warning_cookie_exist()
*
* @param int $time The time in seconds
* @param string $originFormat Optional.
* PHP (used for scorm)
* JS (used in most cases and understood by excel)
* LANG (used to present unit in the user language)
* PHP (used for scorm)
* JS (used in most cases and understood by excel)
* LANG (used to present unit in the user language)
*
* @return string (00h00'00")
*/
@ -9685,7 +9685,7 @@ function api_mail_html(
api_get_setting('siteName'),
[
'id' => 'header-logo',
'class' => 'img-responsive'
'class' => 'img-responsive',
]
);
$logoTag = \Display::url($imgTag, api_get_path(WEB_PATH));
@ -10641,11 +10641,11 @@ function api_decrypt_ldap_password(string $encryptedText): string
return false;
}
return api_decrypt_hash($encryptedText,$secret);
return api_decrypt_hash($encryptedText, $secret);
}
/**
* Decrypt sent hash encoded with secret
* Decrypt sent hash encoded with secret.
*
* @param $encryptedText The hash text to be decrypted
* @param $secret The secret used to encoded the hash
@ -10674,7 +10674,7 @@ function api_decrypt_hash(string $encryptedHash, string $secret): string
}
/**
* Encrypt sent data with secret
* Encrypt sent data with secret.
*
* @param $data The text to be encrypted
* @param $secret The secret to use encode data
@ -10683,10 +10683,10 @@ function api_decrypt_hash(string $encryptedHash, string $secret): string
*/
function api_encrypt_hash($data, $secret)
{
$iv = random_bytes(12);
$tag = '';
$iv = random_bytes(12);
$tag = '';
$encrypted = openssl_encrypt(
$encrypted = openssl_encrypt(
$data,
'aes-256-gcm',
$secret,
@ -10697,5 +10697,5 @@ function api_encrypt_hash($data, $secret)
16
);
return base64_encode($iv) . base64_encode($encrypted . $tag);
return base64_encode($iv).base64_encode($encrypted.$tag);
}

@ -2916,7 +2916,7 @@ class Attendance
$attendanceCalendarId,
$file,
$attendanceId,
$courseId = NULL
$courseId = null
) {
$allowSignature = api_get_configuration_value('enable_sign_attendance_sheet');
if (!$allowSignature) {

@ -2341,7 +2341,7 @@ class CourseManager
: '';
$userIdHash = UserManager::generateUserHash($row['user_id']);
$row['url'] = $url.'&hash='.$userIdHash;
$row['hash'] = $userIdHash;
$row['hash'] = $userIdHash;
$coaches[] = $row;
}

@ -138,7 +138,7 @@ class CourseRequestManager
$last_insert_id = Database::insert_id();
// E-mail notifications.
$email_language = $user_info['language'];
$email_language_admin = api_get_setting('platformLanguage');
@ -156,13 +156,13 @@ class CourseRequestManager
$email_body .= get_lang('Ln', null, $email_language).': '.$course_language."\n";
$email_body .= get_lang('FillWithExemplaryContent', null, $email_language).': '.($exemplary_content ? get_lang('Yes', null, $email_language) : get_lang('No', null, $email_language))."\n";
$email_body = nl2br($email_body);
// Sending an e-mail to the platform administrator.
$email_body_admin = $email_body;
$email_body_admin .= "\n".get_lang('CourseRequestPageForApproval', null, $email_language_admin).' '.api_get_path(WEB_CODE_PATH).'admin/course_request_edit.php?id='.$last_insert_id."\n";
$email_body_admin .= "\n".get_lang('CourseRequestLegalNote', null, $email_language_admin)."\n";
$email_body_admin = nl2br($email_body_admin);
$sender_name_teacher = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
$sender_email_teacher = $user_info['mail'];
$recipient_name_admin = api_get_person_name(
@ -212,7 +212,7 @@ class CourseRequestManager
$email_body_teacher .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
$email_body_teacher .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
$email_body_teacher = nl2br($email_body_teacher);
// Swap the sender and the recipient.
$sender_name_admin = $recipient_name_admin;
$sender_email_admin = $recipient_email_admin;
@ -532,7 +532,7 @@ class CourseRequestManager
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
$email_body = nl2br($email_body);
$sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
$sender_email = api_get_setting('emailAdministrator');
$recipient_name = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
@ -615,7 +615,7 @@ class CourseRequestManager
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
$email_body = nl2br($email_body);
$sender_name = api_get_person_name(
api_get_setting('administratorName'),
api_get_setting('administratorSurname'),
@ -704,7 +704,7 @@ class CourseRequestManager
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator')."\n";
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
$email_body = nl2br($email_body);
$sender_name = api_get_person_name(
api_get_setting('administratorName'),
api_get_setting('administratorSurname'),

@ -7552,6 +7552,7 @@ class DocumentManager
// If </body> tag not found, just append the script tag at the end
$content .= $scriptTag;
}
return $content;
}
}

@ -2390,7 +2390,7 @@ class Event
if (!empty($defaultExtraTime)) {
$loginDiff = time() - $defaultExtraTime;
$loginCourseDate = api_get_utc_datetime($loginDiff);
}
}
$ip = Database::escape_string(api_get_real_ip());
$sql = "INSERT INTO $tableCourseAccess (c_id, user_ip, user_id, login_course_date, logout_course_date, counter, session_id)
VALUES ($courseId, '$ip', $userId, '$loginCourseDate', '$currentDate', 1, $sessionId)";

@ -44,15 +44,15 @@ class Security
public const CHAR_DIGITS = '0123456789';
public const CHAR_SYMBOLS = '!"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~';
public static Array $clean = [];
public static array $clean = [];
/**
* Checks if the absolute path (directory) given is really under the
* checker path (directory).
*
* @param string $abs_path Absolute path to be checked (with trailing slash)
* @param string $checker_path Checker path under which the path
* should be (absolute path, with trailing slash, get it from api_get_path(SYS_COURSE_PATH))
* @param string $abs_path Absolute path to be checked (with trailing slash)
* @param string $checker_path Checker path under which the path
* should be (absolute path, with trailing slash, get it from api_get_path(SYS_COURSE_PATH))
*
* @return bool True if the path is under the checker, false otherwise
*/
@ -99,9 +99,9 @@ class Security
* Checks if the relative path (directory) given is really under the
* checker path (directory).
*
* @param string $rel_path Relative path to be checked (relative to the current directory) (with trailing slash)
* @param string $checker_path Checker path under which the path
* should be (absolute path, with trailing slash, get it from api_get_path(SYS_COURSE_PATH))
* @param string $rel_path Relative path to be checked (relative to the current directory) (with trailing slash)
* @param string $checker_path Checker path under which the path
* should be (absolute path, with trailing slash, get it from api_get_path(SYS_COURSE_PATH))
*
* @return bool True if the path is under the checker, false otherwise
*/
@ -131,17 +131,12 @@ class Security
* other languages' files extensions).
*
* @param string $filename Unfiltered filename
*
* @return string
*/
public static function filter_filename(string $filename): string
{
return disable_dangerous_file($filename);
}
/**
* @return string
*/
public static function getTokenFromSession(string $prefix = ''): string
{
$secTokenVariable = self::generateSecTokenVariable($prefix);
@ -153,9 +148,8 @@ class Security
* This function checks that the token generated in get_token() has been kept (prevents
* Cross-Site Request Forgeries attacks).
*
* @param string $requestType The array in which to get the token ('get' or 'post')
* @param string $requestType The array in which to get the token ('get' or 'post')
* @param ?FormValidator $form
* @param string $prefix
*
* @return bool True if it's the right token, false otherwise
*/
@ -266,9 +260,6 @@ class Security
return $token;
}
/**
* @return string
*/
public static function get_existing_token(string $prefix = ''): string
{
$secTokenVariable = self::generateSecTokenVariable($prefix);
@ -295,7 +286,7 @@ class Security
* This function returns a variable from the clean array. If the variable doesn't exist,
* it returns null.
*
* @param string $varname Variable name
* @param string $varname Variable name
*
* @return mixed Variable or NULL on error
*/
@ -313,9 +304,8 @@ class Security
* Filtering for XSS is very easily done by using the htmlentities() function.
* This kind of filtering prevents JavaScript snippets to be understood as such.
*
* @param string|array $var The variable to filter for XSS, this params can be a string or an array (example : array(x,y))
* @param ?int $user_status The user status,constant allowed (STUDENT, COURSEMANAGER, ANONYMOUS, COURSEMANAGERLOWSECURITY)
* @param bool $filter_terms
* @param string|array $var The variable to filter for XSS, this params can be a string or an array (example : array(x,y))
* @param ?int $user_status The user status,constant allowed (STUDENT, COURSEMANAGER, ANONYMOUS, COURSEMANAGERLOWSECURITY)
*
* @return mixed Filtered string or array
*/
@ -463,8 +453,6 @@ class Security
* Filter content.
*
* @param string $text to be filtered
*
* @return string
*/
public static function filter_terms(string $text): string
{
@ -553,8 +541,6 @@ class Security
* Get password requirements
* It checks config value 'password_requirements' or uses the "classic"
* Chamilo password requirements.
*
* @return array
*/
public static function getPasswordRequirements(): array
{

@ -491,7 +491,7 @@ class SessionManager
$userId = (int) $userId;
if (!api_is_platform_admin() && !api_is_session_admin() && !api_is_teacher()) {
if (!api_is_platform_admin() && !api_is_session_admin() && !api_is_teacher()) {
api_not_allowed(true);
}
@ -4905,12 +4905,6 @@ class SessionManager
}
/**
* @param int $courseId
* @param string|null $startDate
* @param string|null $endDate
*
* @return array
*
* @todo Add param to get only active sessions (not expires ones)
*/
public static function get_session_by_course(int $courseId, ?string $startDate = null, ?string $endDate = null): array

@ -1915,6 +1915,59 @@ class Statistics
return $table;
}
/**
* Exports a user report by course and session to an Excel file.
*/
public static function exportUserReportByCourseSession(int $courseId, ?string $startDate = null, ?string $endDate = null): void
{
$courseInfo = api_get_course_info_by_id($courseId);
$sessions = SessionManager::get_session_by_course($courseId, $startDate, $endDate);
$headers = [
get_lang('CourseName'),
get_lang('SessionName'),
get_lang('LastName'),
get_lang('FirstName'),
get_lang('UserName'),
get_lang('Email'),
get_lang('EndDate'),
get_lang('Score'),
get_lang('Progress'),
];
$exportData = [$headers];
foreach ($sessions as $session) {
$sessionId = (int) $session['id'];
$students = SessionManager::get_users_by_session($sessionId);
foreach ($students as $student) {
$studentId = $student['user_id'];
$studentInfo = api_get_user_info($studentId);
$courseCode = $courseInfo['code'];
$lastConnection = Tracking::getLastConnectionTimeInSessionCourseLp($studentId, $courseCode, $sessionId);
$lastConnectionFormatted = $lastConnection ? date('Y-m-d', $lastConnection) : '';
$averageScore = round(Tracking::getAverageStudentScore($studentId, $courseCode, [], $sessionId));
$averageProgress = round(Tracking::get_avg_student_progress($studentId, $courseCode, [], $sessionId));
$exportData[] = [
$courseInfo['name'],
$session['name'],
$studentInfo['lastname'],
$studentInfo['firstname'],
$studentInfo['username'],
$studentInfo['mail'],
$lastConnectionFormatted,
$averageScore,
$averageProgress,
];
}
}
Export::arrayToXls($exportData, 'session_report_'.$courseInfo['code'].'_'.date('Y-m-d'));
}
/**
* It gets lti learnpath results by date.
*
@ -2103,57 +2156,4 @@ class Statistics
return $usersInfo;
}
/**
* Exports a user report by course and session to an Excel file.
*/
public static function exportUserReportByCourseSession(int $courseId, ?string $startDate = null, ?string $endDate = null): void
{
$courseInfo = api_get_course_info_by_id($courseId);
$sessions = SessionManager::get_session_by_course($courseId, $startDate, $endDate);
$headers = [
get_lang('CourseName'),
get_lang('SessionName'),
get_lang('LastName'),
get_lang('FirstName'),
get_lang('UserName'),
get_lang('Email'),
get_lang('EndDate'),
get_lang('Score'),
get_lang('Progress')
];
$exportData = [$headers];
foreach ($sessions as $session) {
$sessionId = (int) $session['id'];
$students = SessionManager::get_users_by_session($sessionId);
foreach ($students as $student) {
$studentId = $student['user_id'];
$studentInfo = api_get_user_info($studentId);
$courseCode = $courseInfo['code'];
$lastConnection = Tracking::getLastConnectionTimeInSessionCourseLp($studentId, $courseCode, $sessionId);
$lastConnectionFormatted = $lastConnection ? date('Y-m-d', $lastConnection) : '';
$averageScore = round(Tracking::getAverageStudentScore($studentId, $courseCode, [], $sessionId));
$averageProgress = round(Tracking::get_avg_student_progress($studentId, $courseCode, [], $sessionId));
$exportData[] = [
$courseInfo['name'],
$session['name'],
$studentInfo['lastname'],
$studentInfo['firstname'],
$studentInfo['username'],
$studentInfo['mail'],
$lastConnectionFormatted,
$averageScore,
$averageProgress,
];
}
}
Export::arrayToXls($exportData, 'session_report_'.$courseInfo['code'].'_'.date('Y-m-d'));
}
}

@ -8623,6 +8623,116 @@ class Tracking
return $result;
}
/**
* Generates a report based on the specified type and selected users within a date range.
*
* @param string $reportType The type of report to generate ('time_report' or 'billing_report').
* @param array $selectedUserList An array of user IDs to include in the report.
* @param string $startDate The start date for the report in 'Y-m-d H:i:s' format.
* @param string $endDate The end date for the report in 'Y-m-d H:i:s' format.
*
* @throws Exception Throws an exception if an invalid report type is provided.
*
* @return array An array containing the report data. The first element is an array of headers,
* followed by the rows of data.
*/
public static function generateReport(string $reportType, array $selectedUserList, string $startDate, string $endDate): array
{
if (empty($selectedUserList)) {
return ['headers' => [], 'rows' => []];
}
$tblTrackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$tblLpView = Database::get_course_table(TABLE_LP_VIEW);
$tblLpItemView = Database::get_course_table(TABLE_LP_ITEM_VIEW);
$tblLpItem = Database::get_course_table(TABLE_LP_ITEM);
$tblLp = Database::get_course_table(TABLE_LP_MAIN);
switch ($reportType) {
case 'time_report':
$headers = [
get_lang('LastName'),
get_lang('FirstName'),
get_lang('SessionName'),
get_lang('CourseName'),
get_lang('StartingAccessDate'),
get_lang('EndingAccessDate'),
get_lang('TimeSpent'),
];
$sql = "SELECT user_id, session_id, c_id, login_course_date, logout_course_date, (UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) AS time
FROM $tblTrackCourseAccess
WHERE login_course_date >= '$startDate'
AND login_course_date <= '$endDate'
AND logout_course_date >= '$startDate'
AND logout_course_date <= '$endDate'
AND user_id IN (".implode(',', $selectedUserList).")
ORDER BY user_id, login_course_date";
break;
case 'billing_report':
$extraFieldVariable = api_get_configuration_value('billing_report_lp_extra_field');
$extraField = (new ExtraField('lp'))->get_handler_field_info_by_field_variable($extraFieldVariable);
$headers = [
get_lang('LastName'),
get_lang('FirstName'),
get_lang('SessionName'),
get_lang('CourseName'),
get_lang('LearningpathName'),
get_lang('ValidationDate'),
$extraField['display_text'],
];
$sql = "SELECT lv.user_id, lv.session_id, lv.c_id, lv.lp_id, liv.start_time, l.name AS lp_name
FROM $tblLpView lv
INNER JOIN $tblLpItemView liv ON lv.iid = liv.lp_view_id
INNER JOIN $tblLpItem li ON li.iid = liv.lp_item_id
INNER JOIN $tblLp l ON l.id = li.lp_id
WHERE lv.user_id IN (".implode(',', $selectedUserList).")
AND liv.start_time >= UNIX_TIMESTAMP('$startDate')
AND liv.start_time <= UNIX_TIMESTAMP('$endDate')
AND lv.progress = 100
AND li.item_type = '".TOOL_LP_FINAL_ITEM."'
ORDER BY lv.user_id, liv.start_time";
break;
default:
throw new Exception('Invalid report type');
}
$result = Database::query($sql);
$rows = [];
while ($row = Database::fetch_array($result, 'ASSOC')) {
$user = api_get_user_info($row['user_id']);
$session = api_get_session_info($row['session_id']);
$course = api_get_course_info_by_id($row['c_id']);
if ($reportType == 'time_report') {
$rows[] = [
$user['lastname'],
$user['firstname'],
$session['name'],
$course['title'],
api_get_local_time($row['login_course_date']),
api_get_local_time($row['logout_course_date']),
gmdate('H:i:s', $row['time']),
];
} elseif ($reportType == 'billing_report') {
$extraFieldValue = (new ExtraFieldValue('lp'))->get_values_by_handler_and_field_variable($row['lp_id'], $extraFieldVariable);
$rows[] = [
$user['lastname'],
$user['firstname'],
$session['name'],
$course['title'],
$row['lp_name'],
api_get_local_time(date('Y-m-d H:i:s', $row['start_time'])),
$extraFieldValue['value'] ?? '',
];
}
}
return ['headers' => $headers, 'rows' => $rows];
}
private static function generateQuizzesTable(array $courseInfo, int $sessionId = 0): string
{
if (empty($sessionId)) {
@ -9032,115 +9142,6 @@ class Tracking
return implode(PHP_EOL, $html);
}
/**
* Generates a report based on the specified type and selected users within a date range.
*
* @param string $reportType The type of report to generate ('time_report' or 'billing_report').
* @param array $selectedUserList An array of user IDs to include in the report.
* @param string $startDate The start date for the report in 'Y-m-d H:i:s' format.
* @param string $endDate The end date for the report in 'Y-m-d H:i:s' format.
*
* @return array An array containing the report data. The first element is an array of headers,
* followed by the rows of data.
* @throws Exception Throws an exception if an invalid report type is provided.
*/
public static function generateReport(string $reportType, array $selectedUserList, string $startDate, string $endDate): array
{
if (empty($selectedUserList)) {
return ['headers' => [], 'rows' => []];
}
$tblTrackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$tblLpView = Database::get_course_table(TABLE_LP_VIEW);
$tblLpItemView = Database::get_course_table(TABLE_LP_ITEM_VIEW);
$tblLpItem = Database::get_course_table(TABLE_LP_ITEM);
$tblLp = Database::get_course_table(TABLE_LP_MAIN);
switch ($reportType) {
case 'time_report':
$headers = [
get_lang('LastName'),
get_lang('FirstName'),
get_lang('SessionName'),
get_lang('CourseName'),
get_lang('StartingAccessDate'),
get_lang('EndingAccessDate'),
get_lang('TimeSpent')
];
$sql = "SELECT user_id, session_id, c_id, login_course_date, logout_course_date, (UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date)) AS time
FROM $tblTrackCourseAccess
WHERE login_course_date >= '$startDate'
AND login_course_date <= '$endDate'
AND logout_course_date >= '$startDate'
AND logout_course_date <= '$endDate'
AND user_id IN (" . implode(',', $selectedUserList) . ")
ORDER BY user_id, login_course_date";
break;
case 'billing_report':
$extraFieldVariable = api_get_configuration_value('billing_report_lp_extra_field');
$extraField = (new ExtraField('lp'))->get_handler_field_info_by_field_variable($extraFieldVariable);
$headers = [
get_lang('LastName'),
get_lang('FirstName'),
get_lang('SessionName'),
get_lang('CourseName'),
get_lang('LearningpathName'),
get_lang('ValidationDate'),
$extraField['display_text']
];
$sql = "SELECT lv.user_id, lv.session_id, lv.c_id, lv.lp_id, liv.start_time, l.name AS lp_name
FROM $tblLpView lv
INNER JOIN $tblLpItemView liv ON lv.iid = liv.lp_view_id
INNER JOIN $tblLpItem li ON li.iid = liv.lp_item_id
INNER JOIN $tblLp l ON l.id = li.lp_id
WHERE lv.user_id IN (" . implode(',', $selectedUserList) . ")
AND liv.start_time >= UNIX_TIMESTAMP('$startDate')
AND liv.start_time <= UNIX_TIMESTAMP('$endDate')
AND lv.progress = 100
AND li.item_type = '".TOOL_LP_FINAL_ITEM."'
ORDER BY lv.user_id, liv.start_time";
break;
default:
throw new Exception('Invalid report type');
}
$result = Database::query($sql);
$rows = [];
while ($row = Database::fetch_array($result, 'ASSOC')) {
$user = api_get_user_info($row['user_id']);
$session = api_get_session_info($row['session_id']);
$course = api_get_course_info_by_id($row['c_id']);
if ($reportType == 'time_report') {
$rows[] = [
$user['lastname'],
$user['firstname'],
$session['name'],
$course['title'],
api_get_local_time($row['login_course_date']),
api_get_local_time($row['logout_course_date']),
gmdate('H:i:s', $row['time']),
];
} else if ($reportType == 'billing_report') {
$extraFieldValue = (new ExtraFieldValue('lp'))->get_values_by_handler_and_field_variable($row['lp_id'], $extraFieldVariable);
$rows[] = [
$user['lastname'],
$user['firstname'],
$session['name'],
$course['title'],
$row['lp_name'],
api_get_local_time(date('Y-m-d H:i:s', $row['start_time'])),
$extraFieldValue['value'] ?? '',
];
}
}
return ['headers' => $headers, 'rows' => $rows];
}
private static function countSubscribedCoursesPerUser()
{
}

@ -829,8 +829,8 @@ class UserGroup extends Model
}
if (!empty($order)) {
$conditions['order'] = implode(', ', array_map(function($item) {
return $item . ' ASC';
$conditions['order'] = implode(', ', array_map(function ($item) {
return $item.' ASC';
}, $order));
}

@ -577,9 +577,9 @@ class UserManager
false,
false,
false
);
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
);
// the complete_name is not used in the default Chamilo template but used in a specific template -refs BT#21334
$tplSubject->assign('complete_name', stripslashes(api_get_person_name($firstName, $lastName)));
$layoutSubject = $tplSubject->get_template('mail/subject_registration_platform.tpl');
$emailSubject = $tplSubject->fetch($layoutSubject);
$sender_name = api_get_person_name(
@ -2407,10 +2407,9 @@ class UserManager
$sql_query .= ' WHERE 1 = 1 ';
if (count($conditions) > 0) {
$andActive = "";
if (isset($conditions['active'])) {
$andActive = " AND active = " . (int) $conditions['active'];
$andActive = " AND active = ".(int) $conditions['active'];
unset($conditions['active']);
}
@ -8131,6 +8130,44 @@ SQL;
return false;
}
/**
* return user hash based on user_id and loggedin user's salt.
*
* @param int user_id id of the user for whom we need the hash
*
* @return string containing the hash
*/
public static function generateUserHash(int $user_id): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return rawurlencode(api_encrypt_hash($user_id, $user->getSalt()));
}
/**
* return decrypted hash or false.
*
* @param string hash hash that is to be decrypted
*/
public static function decryptUserHash(string $hash): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return api_decrypt_hash(rawurldecode($hash), $user->getSalt());
}
/**
* @return EncoderFactory
*/
@ -8224,42 +8261,4 @@ SQL;
return $url;
}
/**
* return user hash based on user_id and loggedin user's salt
*
* @param int user_id id of the user for whom we need the hash
*
* @return string containing the hash
*/
public static function generateUserHash(int $user_id): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return rawurlencode(api_encrypt_hash($user_id, $user->getSalt()));
}
/**
* return decrypted hash or false
*
* @param string hash hash that is to be decrypted
*
* @return string
*/
public static function decryptUserHash(string $hash): string
{
$currentUserId = api_get_user_id();
$userManager = self::getManager();
/** @var User $user */
$user = self::getRepository()->find($currentUserId);
if (empty($user)) {
return false;
}
return api_decrypt_hash(rawurldecode($hash), $user->getSalt());
}
}

@ -1170,7 +1170,7 @@ class IndexManager
];
}
}
if (!api_is_student()) {
$items[] = [
'class' => 'time-report',

@ -2579,6 +2579,7 @@ class Rest extends WebService
* Updates a user identified by its login name.
*
* @throws Exception on failure
*
* @todo make a safe version for use by the final user on its account
*/
public function updateUserFromUserName(array $parameters): bool
@ -4235,27 +4236,9 @@ class Rest extends WebService
return [$userGroup->unsubscribeSessionsFromUserGroup($groupId, [$sessionId], false)];
}
/**
* Encode the given parameters (structured array) in JSON format
* @param array $additionalParams Optional
*
* @return string
*/
private function encodeParams(array $additionalParams = [])
{
$params = array_merge(
$additionalParams,
[
'api_key' => $this->apiKey,
'username' => $this->user->getUsername(),
]
);
return json_encode($params);
}
/**
* Get audit items from track_e_default.
*
* @throws Exception
*/
public function getAuditItems(
@ -4283,7 +4266,7 @@ class Rest extends WebService
}
/**
* Generate an API key for webservices access for the given user ID
* Generate an API key for webservices access for the given user ID.
*/
protected static function generateApiKeyForUser(int $userId): string
{
@ -4294,9 +4277,29 @@ class Rest extends WebService
return current($apiKeys);
}
/**
* Encode the given parameters (structured array) in JSON format.
*
* @param array $additionalParams Optional
*
* @return string
*/
private function encodeParams(array $additionalParams = [])
{
$params = array_merge(
$additionalParams,
[
'api_key' => $this->apiKey,
'username' => $this->user->getUsername(),
]
);
return json_encode($params);
}
/**
* Helper generating a query URL (to the current script) from an array of parameters
* (course, session, api_key and username) commonly used in webservice calls
* (course, session, api_key and username) commonly used in webservice calls.
*/
private function generateUrl(array $additionalParams = []): string
{

@ -128,7 +128,8 @@ class WebService
}
/**
* Prevent access to this webservice if the user is not a platform admin
* Prevent access to this webservice if the user is not a platform admin.
*
* @throws Exception
*/
protected static function protectAdminEndpoint()

@ -324,8 +324,8 @@ if ($skipData === false) {
// average assignments
$numberAssignments = $countAssignments / $numberStudents;
$avg_courses_per_student = $countCourses / $numberStudents;
$totalTimeSpent = Tracking::get_time_spent_on_the_platform($studentIds, 'ever');
$averageTimeSpentPerStudent = $totalTimeSpent / $numberStudents;
$totalTimeSpent = Tracking::get_time_spent_on_the_platform($studentIds, 'ever');
$averageTimeSpentPerStudent = $totalTimeSpent / $numberStudents;
$posts = Tracking::count_student_messages($studentIds);
$averageScore = Tracking::getAverageStudentScore($studentIds);
}

@ -42,7 +42,7 @@ foreach ($userList as $user) {
}
$formValidator->addElement('select', 'users', get_lang('SelectUsers'), $userOptions, [
'multiple' => 'multiple',
'id' => 'user_selector'
'id' => 'user_selector',
]);
$htmlHeadXtra[] = '
@ -52,7 +52,7 @@ $htmlHeadXtra[] = '
var userSelector = $("#user_selector");
userSelector.select2({
placeholder: "' . get_lang('SelectAnOption') . '",
placeholder: "'.get_lang('SelectAnOption').'",
allowClear: true,
width: "100%"
});
@ -79,7 +79,7 @@ $formValidator->addDatePicker('end_date', get_lang('EndDate'));
// Report type selector
$reportTypeValues = [
'time_report' => get_lang('TimeReport'),
'billing_report' => get_lang('BillingReport')
'billing_report' => get_lang('BillingReport'),
];
$formValidator->addElement('select', 'report_type', get_lang('ReportType'), $reportTypeValues);

@ -2511,7 +2511,7 @@ class Wiki
<!-- defines the headers/footers - this must occur before the headers/footers are set -->
<!--mpdf
<pageheader name="odds" content-left="'.htmlspecialchars($title_pdf,ENT_QUOTES).'" header-style-left="color: #880000; font-style: italic;" line="1" />
<pageheader name="odds" content-left="'.htmlspecialchars($title_pdf, ENT_QUOTES).'" header-style-left="color: #880000; font-style: italic;" line="1" />
<pagefooter name="odds" content-right="{PAGENO}/{nb}" line="1" />
<!-- set the headers/footers - they will occur from here on in the document -->

@ -394,13 +394,13 @@ class CourseSelectForm
'warning'
);
if ($enableScormSelection) {
echo Display::return_message(
echo Display::return_message(
get_lang(
'IfYourLPsAreScormsYouShouldSelectThemFromTheScorms'
),
'warning'
);
}
}
}
if ($type == RESOURCE_DOCUMENT) {

Loading…
Cancel
Save