Actualización
This commit is contained in:
90
main/cron/add_gradebook_certificates.php
Normal file
90
main/cron/add_gradebook_certificates.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
exit;
|
||||
|
||||
/**
|
||||
* Adds gradebook certificates to gradebook_certificate table from users
|
||||
* who have achieved the requirements but have not reviewed them yet.
|
||||
*
|
||||
* @author Imanol Losada <imanol.losada@beeznest.com>
|
||||
*/
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Get all categories and users ids from gradebook.
|
||||
*
|
||||
* @return array Categories and users ids
|
||||
*/
|
||||
function getAllCategoriesAndUsers()
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
|
||||
$jointable = Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
|
||||
$joinStatement = ' JOIN '.$jointable.' ON '.$table.'.evaluation_id = '.$jointable.'.id';
|
||||
|
||||
return Database::select(
|
||||
'DISTINCT '.$jointable.'.category_id,'.$table.'.user_id',
|
||||
$table.$joinStatement
|
||||
);
|
||||
}
|
||||
|
||||
if ($categoriesAndUsers = getAllCategoriesAndUsers()) {
|
||||
foreach ($categoriesAndUsers as $categoryAndUser) {
|
||||
Category::generateUserCertificate(
|
||||
$categoryAndUser['category_id'],
|
||||
$categoryAndUser['user_id'],
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$urlList = [1];
|
||||
foreach ($urlList as $urlId) {
|
||||
$_configuration['access_url'] = $urlId;
|
||||
$sql = "SELECT gc.*
|
||||
FROM gradebook_category gc
|
||||
INNER JOIN course c
|
||||
ON (c.code = gc.course_code)
|
||||
INNER JOIN access_url_rel_course a
|
||||
ON (a.c_id = c.id)
|
||||
WHERE
|
||||
generate_certificates = 1 AND
|
||||
parent_id = 0 AND
|
||||
access_url_id = $urlId
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
$categories = Database::store_result($result);
|
||||
$total = count($categories);
|
||||
$counter = 1;
|
||||
foreach ($categories as $category) {
|
||||
$courseCode = $category['course_code'];
|
||||
$sessionId = (int) $category['session_id'];
|
||||
$filter = STUDENT;
|
||||
if (!empty($sessionId)) {
|
||||
$filter = 0;
|
||||
}
|
||||
$users = CourseManager::get_user_list_from_course_code(
|
||||
$courseCode,
|
||||
$sessionId,
|
||||
null,
|
||||
null,
|
||||
$filter
|
||||
);
|
||||
|
||||
$_SESSION['id_session'] = $sessionId;
|
||||
|
||||
echo "Category: ".$category['id']." Course: ".$courseCode." Session: $sessionId - Processing: $counter/".$total.PHP_EOL;
|
||||
foreach ($users as $user) {
|
||||
echo "Generating certificate user #".$user['user_id'].PHP_EOL;
|
||||
Category::generateUserCertificate(
|
||||
$category['id'],
|
||||
$user['user_id'],
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
206
main/cron/agenda_reminders.php
Normal file
206
main/cron/agenda_reminders.php
Normal file
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script send notification messages to users that have reminders from an event in their agenda.
|
||||
*/
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||
|
||||
exit;
|
||||
|
||||
if (false === api_get_configuration_value('agenda_reminders')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$batchCounter = 0;
|
||||
$batchSize = 100;
|
||||
|
||||
$agendaCollectiveInvitations = api_get_configuration_value('agenda_collective_invitations');
|
||||
|
||||
$now = new DateTime('now', new DateTimeZone('UTC'));
|
||||
|
||||
$em = Database::getManager();
|
||||
$remindersRepo = $em->getRepository('ChamiloCoreBundle:AgendaReminder');
|
||||
|
||||
$reminders = $remindersRepo->findBySent(false);
|
||||
|
||||
$senderId = api_get_configuration_value('agenda_reminders_sender_id');
|
||||
|
||||
if (empty($senderId)) {
|
||||
$firstAdmin = current(UserManager::get_all_administrators());
|
||||
$senderId = $firstAdmin['user_id'];
|
||||
}
|
||||
|
||||
foreach ($reminders as $reminder) {
|
||||
if ('personal' === $reminder->getType()) {
|
||||
$event = $em->find('ChamiloCoreBundle:PersonalAgenda', $reminder->getEventId());
|
||||
|
||||
if (null === $event) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$notificationDate = clone $event->getDate();
|
||||
$notificationDate->sub($reminder->getDateInterval());
|
||||
|
||||
if ($notificationDate > $now) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$eventDetails = [];
|
||||
$eventDetails[] = '<p><strong>'.$event->getTitle().'</strong></p>';
|
||||
|
||||
if ($event->getAllDay()) {
|
||||
$eventDetails[] = '<p class="small">'.get_lang('AllDay').'</p>';
|
||||
} else {
|
||||
$eventDetails[] = sprintf(
|
||||
'<p class="small">'.get_lang('FromDateX').'</p>',
|
||||
api_get_local_time($event->getDate(), null, null, false, true, true)
|
||||
);
|
||||
|
||||
if (!empty($event->getEnddate())) {
|
||||
$eventDetails[] = sprintf(
|
||||
'<p class="small">'.get_lang('UntilDateX').'</p>',
|
||||
api_get_local_time($event->getEnddate(), null, null, false, true, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($event->getText())) {
|
||||
$eventDetails[] = $event->getText();
|
||||
}
|
||||
|
||||
$messageSubject = sprintf(get_lang('ReminderXEvent'), $event->getTitle());
|
||||
$messageContent = implode(PHP_EOL, $eventDetails);
|
||||
|
||||
MessageManager::send_message_simple(
|
||||
$event->getUser(),
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
$event->getUser()
|
||||
);
|
||||
|
||||
if ($agendaCollectiveInvitations) {
|
||||
$invitees = Agenda::getInviteesForPersonalEvent($reminder->getEventId());
|
||||
$inviteesIdList = array_column($invitees, 'id');
|
||||
|
||||
foreach ($inviteesIdList as $userId) {
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
$event->getUser()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('course' === $reminder->getType()) {
|
||||
$event = $em->find('ChamiloCourseBundle:CCalendarEvent', $reminder->getEventId());
|
||||
|
||||
if (null === $event) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$agenda = new Agenda('course');
|
||||
|
||||
$notificationDate = clone $event->getStartDate();
|
||||
$notificationDate->sub($reminder->getDateInterval());
|
||||
|
||||
if ($notificationDate > $now) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$eventDetails = [];
|
||||
$eventDetails[] = '<p><strong>'.$event->getTitle().'</strong></p>';
|
||||
|
||||
if ($event->getAllDay()) {
|
||||
$eventDetails[] = '<p class="small">'.get_lang('AllDay').'</p>';
|
||||
} else {
|
||||
$eventDetails[] = sprintf(
|
||||
'<p class="small">'.get_lang('FromDateX').'</p>',
|
||||
api_get_local_time($event->getStartDate(), null, null, false, true, true)
|
||||
);
|
||||
|
||||
if (!empty($event->getEndDate())) {
|
||||
$eventDetails[] = sprintf(
|
||||
'<p class="small">'.get_lang('UntilDateX').'</p>',
|
||||
api_get_local_time($event->getEndDate(), null, null, false, true, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($event->getContent())) {
|
||||
$eventDetails[] = $event->getContent();
|
||||
}
|
||||
|
||||
if (!empty($event->getComment())) {
|
||||
$eventDetails[] = '<p class="small">'.$event->getComment().'</p>';
|
||||
}
|
||||
|
||||
$messageSubject = sprintf(get_lang('ReminderXEvent'), $event->getTitle());
|
||||
$messageContent = implode(PHP_EOL, $eventDetails);
|
||||
|
||||
$courseInfo = api_get_course_info_by_id($event->getCId());
|
||||
|
||||
$sendTo = $agenda->getUsersAndGroupSubscribedToEvent(
|
||||
$event->getIid(),
|
||||
$event->getCId(),
|
||||
$event->getSessionId()
|
||||
);
|
||||
|
||||
if ($sendTo['everyone']) {
|
||||
$users = CourseManager::get_user_list_from_course_code($courseInfo['code'], $event->getSessionId());
|
||||
$userIdList = array_keys($users);
|
||||
|
||||
if ($event->getSessionId()) {
|
||||
$coaches = SessionManager::getCoachesByCourseSession($event->getSessionId(), $event->getCId());
|
||||
$userIdList += $coaches;
|
||||
}
|
||||
|
||||
foreach ($userIdList as $userId) {
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
$senderId
|
||||
);
|
||||
}
|
||||
} else {
|
||||
foreach ($sendTo['groups'] as $groupId) {
|
||||
$groupUserList = GroupManager::get_users($groupId, false, null, null, false, $event->getSessionId());
|
||||
|
||||
foreach ($groupUserList as $groupUserId) {
|
||||
MessageManager::send_message_simple(
|
||||
$groupUserId,
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
$senderId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($sendTo['users'] as $userId) {
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
$senderId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$reminder->setSent(true);
|
||||
|
||||
$em->persist($reminder);
|
||||
|
||||
$batchCounter++;
|
||||
|
||||
if (($batchCounter % $batchSize) === 0) {
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
161
main/cron/archive_table_records.php
Normal file
161
main/cron/archive_table_records.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script cleans old records in (mostly) track_e_* and saves them to a
|
||||
* separate track_e_*_[YYYY] table, with the name of the year in which this
|
||||
* script is run as a suffix.
|
||||
* Because we don't know the column that reflects the date of the record in the
|
||||
* corresponding table (it varies from table to table), we use the time of
|
||||
* running the script as the suffix to the archive table.
|
||||
* This script uses the primary key to calculate the ID up to which we want to
|
||||
* archive records, so if many records have previously been deleted, the
|
||||
* number of moved records might be considerable inferior to $archiveNumber.
|
||||
* This script does the following:
|
||||
* - run through the list of programmed tables to archive
|
||||
* - check if the archive table exists, otherwise create it
|
||||
* - gets the lower ID of the original table, adds the threshold and proceeds
|
||||
* to move all first [$threshold] records to an archive table
|
||||
* - removes the moved records from the original table
|
||||
* - writes a log in a local file (see $logFile below)
|
||||
* To fine-tune it, change the $tables, $threshold and $archiveNumber variables
|
||||
* below.
|
||||
*
|
||||
* @author Yannick Warnier <yannick.warnier@beeznest.com>
|
||||
*/
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
exit("This script must be run from the command-line. Goodbye.\n");
|
||||
}
|
||||
require __DIR__.'/../../main/inc/global.inc.php';
|
||||
ini_set('max_execution_time', 0);
|
||||
$logFile = __DIR__.'/archive_track_tables_records.log';
|
||||
// List of tables to be "archived"
|
||||
$tables = [
|
||||
'track_e_downloads',
|
||||
];
|
||||
// The threshold (number under which nothing must be done). Defaults to 10M
|
||||
$threshold = 10000000;
|
||||
// The number of records to be archived
|
||||
$archiveNumber = 5000000;
|
||||
// Browse tables and archive some data
|
||||
foreach ($tables as $table) {
|
||||
$tableArchive = $table.'_'.date('Y');
|
||||
if (!checkAndCreateTable($tableArchive, $table)) {
|
||||
exit("Could not create table $tableArchive. Please check your database user has the CREATE TABLE permission.\n");
|
||||
}
|
||||
$sql = "SELECT count(*) FROM $table";
|
||||
$res = Database::query($sql);
|
||||
$row = Database::fetch_row($res);
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Checking current records in $table (".date('Y-m-d H:i:s').")\n===\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
// If more than 10M registers, move the 10M first registers to a, history table
|
||||
if ($row[0] > $threshold) {
|
||||
$pk = getPKFromTable($table);
|
||||
$sql = "SELECT min($pk) FROM $table";
|
||||
$res = Database::query($sql);
|
||||
$row = Database::fetch_row($res);
|
||||
$min = $row[0];
|
||||
$max = $min + $archiveNumber;
|
||||
$sql = "INSERT INTO $tableArchive SELECT * FROM $table WHERE $pk >= $min AND $pk < $max";
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Moving rows $min to ".($max - 1)." to $tableArchive. Starting at ".date('Y-m-d H:i:s')."\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
$res = Database::query($sql);
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Done moving at ".date('Y-m-d H:i:s')."\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
if ($res !== false) {
|
||||
$sql = "DELETE FROM $table WHERE $pk < $max";
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Deleting rows < $max from $table. Starting at ".date('Y-m-d H:i:s')."\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
$res = Database::query($sql);
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Done cleaning up at ".date('Y-m-d H:i:s')."\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
} else {
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"There was an issue copying the rows to $tableArchive\n[Query: $sql ].\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
}
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Table process finished at ".date('Y-m-d H:i:s').".\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
} else {
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"There are no more than $threshold transactions in $table table. No action taken.\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
}
|
||||
}
|
||||
file_put_contents(
|
||||
$logFile,
|
||||
"Archiving finished at ".date('Y-m-d H:i:s').". No action taken.\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the name of the primary key column for the given table.
|
||||
*
|
||||
* @param string $table The name of the table
|
||||
*
|
||||
* @return string The column name of the primary key
|
||||
*/
|
||||
function getPKFromTable($table)
|
||||
{
|
||||
$sql = "SELECT k.column_name
|
||||
FROM information_schema.table_constraints t
|
||||
JOIN information_schema.key_column_usage k
|
||||
USING(constraint_name, table_schema, table_name)
|
||||
WHERE t.constraint_type = 'PRIMARY KEY'
|
||||
AND t.table_schema='".api_get_configuration_value('main_database')."'
|
||||
AND t.table_name='$table'";
|
||||
$res = Database::query($sql);
|
||||
if (Database::num_rows($res) > 0) {
|
||||
$row = Database::fetch_assoc($res);
|
||||
|
||||
return $row['column_name'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a table exists and create it if it doesn't.
|
||||
*
|
||||
* @param string $table The table to check/create
|
||||
* @param string $templateTable The model from which this table should be created
|
||||
*
|
||||
* @return bool True if it exists *or* it could be created, false if there was an error at create time
|
||||
*/
|
||||
function checkAndCreateTable($table, $templateTable)
|
||||
{
|
||||
$sqlCheck = "SHOW TABLES LIKE '$table'";
|
||||
$res = Database::query($sqlCheck);
|
||||
if (Database::num_rows($res) > 0) {
|
||||
// The table already exists
|
||||
return true;
|
||||
} else {
|
||||
$sqlCreate = "CREATE TABLE $table like $templateTable";
|
||||
$res = Database::query($sqlCreate);
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
156
main/cron/check_lp_total_time.php
Normal file
156
main/cron/check_lp_total_time.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script checks and propose a query fix for LP items with high time values
|
||||
* Only if the total LP time is bigger than the total course time.
|
||||
*/
|
||||
exit;
|
||||
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||
|
||||
api_protect_admin_script();
|
||||
|
||||
opcache_reset();
|
||||
|
||||
$testSessionId = 182;
|
||||
$testCourseId = 97;
|
||||
$max = 10;
|
||||
$counter = 0;
|
||||
// Check Sessions
|
||||
$_configuration['access_url'] = 6;
|
||||
$sessions = SessionManager::formatSessionsAdminForGrid();
|
||||
foreach ($sessions as $session) {
|
||||
$sessionId = $session['id'];
|
||||
if (!empty($testSessionId)) {
|
||||
if ($sessionId != $testSessionId) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$courses = SessionManager::getCoursesInSession($sessionId);
|
||||
|
||||
foreach ($courses as $courseId) {
|
||||
if (!empty($testCourseId)) {
|
||||
if ($testCourseId != $courseId) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$courseInfo = api_get_course_info_by_id($courseId);
|
||||
$courseCode = $courseInfo['code'];
|
||||
|
||||
$users = CourseManager::get_user_list_from_course_code(
|
||||
$courseCode,
|
||||
$sessionId,
|
||||
null,
|
||||
null,
|
||||
0
|
||||
);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$result = compareLpTimeAndCourseTime($user, $courseInfo, $sessionId);
|
||||
if ($result) {
|
||||
$counter++;
|
||||
}
|
||||
|
||||
if ($counter > $max) {
|
||||
break 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Courses
|
||||
/*$courses = CourseManager::get_courses_list();
|
||||
foreach($courses as $courseInfo) {
|
||||
$courseCode = $courseInfo['code'];
|
||||
$courseInfo['real_id'] = $courseInfo['id'];
|
||||
$users = CourseManager::get_user_list_from_course_code($courseCode);
|
||||
foreach ($users as $user) {
|
||||
$userId = $user['id'];
|
||||
compareLpTimeAndCourseTime($userId, $courseInfo);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @param array $user
|
||||
* @param array $courseInfo
|
||||
* @param int $sessionId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function compareLpTimeAndCourseTime($user, $courseInfo, $sessionId = 0)
|
||||
{
|
||||
$userId = $user['user_id'];
|
||||
$defaultValue = 600; // 10 min
|
||||
$courseCode = $courseInfo['code'];
|
||||
$courseId = $courseInfo['real_id'];
|
||||
|
||||
$totalLpTime = Tracking::get_time_spent_in_lp(
|
||||
$userId,
|
||||
$courseCode,
|
||||
[],
|
||||
$sessionId
|
||||
);
|
||||
|
||||
if (empty($totalLpTime)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$totalCourseTime = Tracking::get_time_spent_on_the_course(
|
||||
$userId,
|
||||
$courseId,
|
||||
$sessionId
|
||||
);
|
||||
$content = '';
|
||||
if ($totalLpTime > $totalCourseTime) {
|
||||
$totalCourseTimeFormatted = api_time_to_hms($totalCourseTime);
|
||||
$totalLpTimeFormatted = api_time_to_hms($totalLpTime);
|
||||
$diff = $totalLpTime - $totalCourseTime;
|
||||
|
||||
$content = PHP_EOL."User: ".$user['user_id']." - Total course: $totalCourseTimeFormatted / Total LP: $totalLpTimeFormatted".PHP_EOL;
|
||||
$content .= PHP_EOL."Diff: ".api_time_to_hms($diff).PHP_EOL;
|
||||
$url = api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?student='.$userId.'&course='.$courseCode.'&id_session='.$sessionId;
|
||||
$content .= Display::url('Check', $url, ['target' => '_blank']);
|
||||
$content .= PHP_EOL;
|
||||
|
||||
// Check possible records with high values
|
||||
$sql = "SELECT iv.iid, lp_id, total_time
|
||||
FROM c_lp_view v
|
||||
INNER JOIN c_lp_item_view iv
|
||||
ON (iv.c_id = v.c_id AND v.id = iv.lp_view_id)
|
||||
WHERE
|
||||
user_id = $userId AND
|
||||
v.c_id = $courseId AND
|
||||
session_id = $sessionId
|
||||
ORDER BY total_time desc
|
||||
LIMIT 1
|
||||
";
|
||||
echo $sql.PHP_EOL;
|
||||
$result = Database::query($sql);
|
||||
$results = Database::store_result($result, 'ASSOC');
|
||||
if (!empty($results)) {
|
||||
$content .= 'Top 1 high lp item times'.PHP_EOL.PHP_EOL;
|
||||
foreach ($results as $item) {
|
||||
$lpId = $item['lp_id'];
|
||||
$link = api_get_path(WEB_CODE_PATH).'mySpace/lp_tracking.php?cidReq='.$courseCode.
|
||||
'&course='.$courseCode.'&origin=&lp_id='.$lpId.'&student_id='.$userId.'&id_session='.$sessionId;
|
||||
$content .= "total_time to be reduced = ".api_time_to_hms($item['total_time']).PHP_EOL;
|
||||
$content .= Display::url('See report before update', $link, ['target' => '_blank']).PHP_EOL;
|
||||
$content .= "SQL with possible fix:".PHP_EOL;
|
||||
|
||||
if ($item['total_time'] < $defaultValue) {
|
||||
$content .= "Skip because total_time is too short. total_time: ".$item['total_time'].' value to rest'.$defaultValue.PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
$content .= "UPDATE c_lp_item_view SET total_time = total_time - '$defaultValue' WHERE iid = ".$item['iid'].";".PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo nl2br($content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
exit;
|
||||
55
main/cron/check_user_careers.php
Normal file
55
main/cron/check_user_careers.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
$file = 'all_session_careers_with_users.csv';
|
||||
$data = Import::csvToArray($file);
|
||||
|
||||
$extraFieldValue = new ExtraFieldValue('session');
|
||||
$count = 1;
|
||||
$careerValue = new ExtraFieldValue('career');
|
||||
foreach ($data as $row) {
|
||||
echo "Line $count ".PHP_EOL;
|
||||
$count++;
|
||||
$users = explode('|', $row['Users']);
|
||||
$externalCareerIdList = $row['extra_careerid'];
|
||||
|
||||
if (substr($externalCareerIdList, 0, 1) === '[') {
|
||||
$externalCareerIdList = substr($externalCareerIdList, 1, -1);
|
||||
$externalCareerIds = preg_split('/,/', $externalCareerIdList);
|
||||
} else {
|
||||
$externalCareerIds = [$externalCareerIdList];
|
||||
}
|
||||
|
||||
$chamiloCareerList = [];
|
||||
foreach ($externalCareerIds as $careerId) {
|
||||
$careerFound = $careerValue->get_item_id_from_field_variable_and_field_value('external_career_id', $careerId);
|
||||
if ($careerFound && isset($careerFound['item_id'])) {
|
||||
$chamiloCareerList[] = $careerFound['item_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($chamiloCareerList)) {
|
||||
echo "No career found ".PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($users as $username) {
|
||||
$userInfo = api_get_user_info_from_username($username);
|
||||
if ($userInfo) {
|
||||
$userId = $userInfo['user_id'];
|
||||
foreach ($chamiloCareerList as $careerId) {
|
||||
if (UserManager::userHasCareer($userId, $careerId)) {
|
||||
echo "User $username (#$userId) has already the chamilo career # $careerId ".PHP_EOL;
|
||||
continue;
|
||||
} else {
|
||||
//UserManager::addUserCareer($userId, $careerId);
|
||||
echo "Save career #$careerId to user $username (#$userId) ".PHP_EOL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "Username not found: $username ".PHP_EOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
94
main/cron/course_announcement.php
Normal file
94
main/cron/course_announcement.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Entity\Session;
|
||||
use Chamilo\CourseBundle\Entity\CItemProperty;
|
||||
|
||||
require __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
if (php_sapi_name() != 'cli') {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
if (!api_get_configuration_value('course_announcement_scheduled_by_date')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get all pending (visible) announcements where e-mail sent is empty
|
||||
$dql = "SELECT a
|
||||
FROM ChamiloCourseBundle:CAnnouncement a
|
||||
JOIN ChamiloCourseBundle:CItemProperty ip
|
||||
WITH a.id = ip.ref AND a.cId = ip.course
|
||||
WHERE
|
||||
(a.emailSent != 1 OR
|
||||
a.emailSent IS NULL) AND
|
||||
ip.tool = '".TOOL_ANNOUNCEMENT."' AND
|
||||
ip.visibility = 1
|
||||
ORDER BY a.displayOrder DESC";
|
||||
|
||||
$qb = Database::getManager()->createQuery($dql);
|
||||
$result = $qb->execute();
|
||||
|
||||
if (!$result) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$extraFieldValue = new ExtraFieldValue('course_announcement');
|
||||
$today = date('Y-m-d');
|
||||
|
||||
// For each announcement, check rules about sending the notification at a
|
||||
// specific date
|
||||
foreach ($result as $announcement) {
|
||||
$sendNotification = $extraFieldValue->get_values_by_handler_and_field_variable($announcement->getId(), 'send_notification_at_a_specific_date');
|
||||
|
||||
if ($sendNotification['value'] == 1) {
|
||||
$dateToSend = $extraFieldValue->get_values_by_handler_and_field_variable($announcement->getId(), 'date_to_send_notification');
|
||||
|
||||
if ($today >= $dateToSend['value']) {
|
||||
$query = "SELECT ip FROM ChamiloCourseBundle:CItemProperty ip
|
||||
WHERE ip.ref = :announcementId
|
||||
AND ip.course = :courseId
|
||||
AND ip.tool = '".TOOL_ANNOUNCEMENT."'
|
||||
ORDER BY ip.iid DESC";
|
||||
|
||||
$sql = Database::getManager()->createQuery($query);
|
||||
$itemProperty = $sql->execute(['announcementId' => $announcement->getId(), 'courseId' => $announcement->getCId()]);
|
||||
if (empty($itemProperty) or !isset($itemProperty[0])) {
|
||||
continue;
|
||||
}
|
||||
/* @var CItemProperty $itemPropertyObject */
|
||||
$itemPropertyObject = $itemProperty[0];
|
||||
// Check if the last record for this announcement was not a removal
|
||||
if ($itemPropertyObject->getLastEditType() == 'AnnouncementDeleted' or $itemPropertyObject->getVisibility() == 2) {
|
||||
continue;
|
||||
}
|
||||
/* @var Session $sessionObject */
|
||||
$sessionObject = $itemPropertyObject->getSession();
|
||||
if (!empty($sessionObject)) {
|
||||
$sessionId = $sessionObject->getId();
|
||||
} else {
|
||||
$sessionId = null;
|
||||
}
|
||||
$courseInfo = api_get_course_info_by_id($announcement->getCId());
|
||||
$senderId = $itemPropertyObject->getInsertUser()->getId();
|
||||
// Check if we need to send it to all users of all sessions that
|
||||
// include this course.
|
||||
$sendToUsersInSession = (int) $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$announcement->getId(),
|
||||
'send_to_users_in_session'
|
||||
)['value'];
|
||||
|
||||
$messageSentTo = AnnouncementManager::sendEmail(
|
||||
$courseInfo,
|
||||
$sessionId,
|
||||
$announcement->getId(),
|
||||
$sendToUsersInSession,
|
||||
false,
|
||||
null,
|
||||
$senderId,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
main/cron/course_finished.php
Normal file
89
main/cron/course_finished.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Entity\Session;
|
||||
|
||||
/**
|
||||
* Cron for send a email when the course are finished.
|
||||
*
|
||||
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||
*/
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
$isActive = api_get_setting('cron_remind_course_expiration_activate') === 'true';
|
||||
|
||||
if (!$isActive) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$endDate = new DateTime('now', new DateTimeZone('UTC'));
|
||||
$endDate = $endDate->format('Y-m-d');
|
||||
|
||||
$entityManager = Database::getManager();
|
||||
$sessionRepo = $entityManager->getRepository('ChamiloCoreBundle:Session');
|
||||
$accessUrlRepo = $entityManager->getRepository('ChamiloCoreBundle:AccessUrl');
|
||||
|
||||
/** @var Session[] $sessions */
|
||||
$sessions = $sessionRepo->createQueryBuilder('s')
|
||||
->where('s.accessEndDate LIKE :date')
|
||||
->setParameter('date', "$endDate%")
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
if (empty($sessions)) {
|
||||
echo "No sessions finishing today $endDate".PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
|
||||
$administrator = [
|
||||
'complete_name' => api_get_person_name(
|
||||
api_get_setting('administratorName'),
|
||||
api_get_setting('administratorSurname'),
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
),
|
||||
'email' => api_get_setting('emailAdministrator'),
|
||||
];
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
$sessionUsers = $session->getUsers();
|
||||
|
||||
if (empty($sessionUsers)) {
|
||||
echo 'No users to send mail'.PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
|
||||
foreach ($sessionUsers as $sessionUser) {
|
||||
$user = $sessionUser->getUser();
|
||||
|
||||
$subjectTemplate = new Template(null, false, false, false, false, false);
|
||||
$subjectTemplate->assign('session_name', $session->getName());
|
||||
|
||||
$subjectLayout = $subjectTemplate->get_template('mail/cron_course_finished_subject.tpl');
|
||||
|
||||
$bodyTemplate = new Template(null, false, false, false, false, false);
|
||||
$bodyTemplate->assign('complete_user_name', UserManager::formatUserFullName($user));
|
||||
$bodyTemplate->assign('session_name', $session->getName());
|
||||
|
||||
$bodyLayout = $bodyTemplate->get_template('mail/cron_course_finished_body.tpl');
|
||||
|
||||
api_mail_html(
|
||||
UserManager::formatUserFullName($user),
|
||||
$user->getEmail(),
|
||||
$subjectTemplate->fetch($subjectLayout),
|
||||
$bodyTemplate->fetch($bodyLayout),
|
||||
$administrator['complete_name'],
|
||||
$administrator['email']
|
||||
);
|
||||
|
||||
echo '============'.PHP_EOL;
|
||||
echo "Email sent to: ".UserManager::formatUserFullName($user)." ({$user->getEmail()})".PHP_EOL;
|
||||
echo "Session: {$session->getName()}".PHP_EOL;
|
||||
echo "End date: {$session->getAccessEndDate()->format('Y-m-d h:i')}".PHP_EOL;
|
||||
}
|
||||
}
|
||||
214
main/cron/create_course_sessions.php
Normal file
214
main/cron/create_course_sessions.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Create course sessions procedure. It creates sessions for courses that haven't it yet.
|
||||
* If today is greater than OFFSET, it will create them also for the next quarter.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*
|
||||
* @author Imanol Losada <imanol.losada@beeznest.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
if (php_sapi_name() != 'cli') {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
require_once __DIR__."/../inc/global.inc.php";
|
||||
|
||||
// First day of the current month to create sessions and add courses for the next month (e.g. "07")
|
||||
define("OFFSET", "15");
|
||||
/**
|
||||
* If no $initialDate is supplied, returns an array with the first and last days of the current
|
||||
* month. Otherwise, returns an array with the first and last days of the $initialDate month .
|
||||
*
|
||||
* @param array $initialDate First day of the month
|
||||
*
|
||||
* @return array First and last days of the month
|
||||
*/
|
||||
function getMonthFirstAndLastDates($initialDate = null)
|
||||
{
|
||||
$startDate = $initialDate ? $initialDate : date("Y-m-01");
|
||||
$nextMonthStartDate = date("Y-m-d", api_strtotime($startDate." + 1 month"));
|
||||
$endDate = date("Y-m-d", api_strtotime($nextMonthStartDate." - 1 minute"));
|
||||
|
||||
return ['startDate' => $startDate, 'endDate' => $endDate];
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as month, but for quarters.
|
||||
*
|
||||
* @param array $initialDate First day of the quarter
|
||||
*
|
||||
* @return array First and last days of the quarter
|
||||
*/
|
||||
function getQuarterFirstAndLastDates($initialDate = null)
|
||||
{
|
||||
$startDate = $initialDate ? $initialDate : date("Y-m-01");
|
||||
$month = getQuarterFirstMonth(getQuarter(date('m', $startDate)));
|
||||
$startDate = substr($startDate, 0, 5).$month.'-01';
|
||||
$nextQuarterStartDate = date('Y-m-d', api_strtotime($startDate.' + 3 month'));
|
||||
$endDate = date('Y-m-d', api_strtotime($nextQuarterStartDate.' - 1 minute'));
|
||||
|
||||
return ['startDate' => $startDate, 'endDate' => $endDate];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a quarter from a month.
|
||||
*
|
||||
* @param string The month (digit), with or without leading 0
|
||||
* @param string $month
|
||||
*
|
||||
* @return int The yearly quarter (1, 2, 3 or 4) in which this month lies
|
||||
*/
|
||||
function getQuarter($month)
|
||||
{
|
||||
$quarter = 1;
|
||||
// Remove the leading 0 if any
|
||||
if (substr($month, 0, 1) == '0') {
|
||||
$month = substr($month, 1);
|
||||
}
|
||||
// reduce to 4 quarters: 1..3=1; 4..6=2
|
||||
switch ($month) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
$quarter = 1;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
$quarter = 2;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
$quarter = 3;
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
$quarter = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
return $quarter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first month of the quarter.
|
||||
*
|
||||
* @param int Quarter
|
||||
* @param int $quarter
|
||||
*
|
||||
* @return string Number of the month, with leading 0
|
||||
*/
|
||||
function getQuarterFirstMonth($quarter)
|
||||
{
|
||||
switch ($quarter) {
|
||||
case 1:
|
||||
return '01';
|
||||
case 2:
|
||||
return '04';
|
||||
case 3:
|
||||
return '07';
|
||||
case 4:
|
||||
return '10';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quarter in Roman letters.
|
||||
*
|
||||
* @param int Quarter
|
||||
* @param int $quarter
|
||||
*
|
||||
* @return string Roman letters
|
||||
*/
|
||||
function getQuarterRoman($quarter)
|
||||
{
|
||||
switch ($quarter) {
|
||||
case 1:
|
||||
return 'I';
|
||||
case 2:
|
||||
return 'II';
|
||||
case 3:
|
||||
return 'III';
|
||||
case 4:
|
||||
return 'IV';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates one session per course with $administratorId as the creator and
|
||||
* adds it to the session starting on $startDate and finishing on $endDate.
|
||||
*
|
||||
* @param array $courses Courses
|
||||
* @param int $administratorId Administrator id
|
||||
* @param date $startDate First day of the month
|
||||
* @param date $endDate Last day of the month
|
||||
*/
|
||||
function createCourseSessions($courses, $administratorId, $startDate, $endDate)
|
||||
{
|
||||
echo "\n";
|
||||
echo $courses ?
|
||||
"Creating sessions and adding courses for the period between ".$startDate." and ".$endDate : "Every course is already in session for the period between ".$startDate." and ".$endDate;
|
||||
echo "\n=====================================================================================\n\n";
|
||||
// Loop through courses creating one session per each and adding them
|
||||
foreach ($courses as $course) {
|
||||
//$period = date("m/Y", api_strtotime($startDate));
|
||||
$month = date("m", api_strtotime($startDate));
|
||||
$year = date("Y", api_strtotime($startDate));
|
||||
$quarter = getQuarter($month);
|
||||
$quarter = getQuarterRoman($quarter);
|
||||
$period = $year.'-'.$quarter;
|
||||
$sessionName = '['.$period.'] '.$course['title'];
|
||||
$sessionId = SessionManager::create_session(
|
||||
$sessionName,
|
||||
$startDate,
|
||||
$endDate,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$administratorId,
|
||||
0,
|
||||
SESSION_INVISIBLE
|
||||
);
|
||||
SessionManager::add_courses_to_session($sessionId, [$course['id']]);
|
||||
echo "Session '".$sessionName."' created.\nCourse '".$course['title']."' added.\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Starts the script
|
||||
echo "Starting process...".PHP_EOL;
|
||||
// Get first active administrator
|
||||
$administrators = array_reverse(UserManager::get_all_administrators());
|
||||
$lastingAdministrators = count($administrators);
|
||||
while (!$administrators[$lastingAdministrators - 1]['active'] && $lastingAdministrators > 0) {
|
||||
$lastingAdministrators--;
|
||||
}
|
||||
if (!$lastingAdministrators) {
|
||||
echo "There are no active administrators. Process halted.\n";
|
||||
exit;
|
||||
}
|
||||
$administratorId = intval($administrators[$lastingAdministrators - 1]['user_id']);
|
||||
|
||||
// Creates course sessions for the current month
|
||||
$dates = getQuarterFirstAndLastDates(date('Y-m-').'01');
|
||||
// Get courses that don't have any session
|
||||
$courses = CourseManager::getCoursesWithoutSession($dates['startDate'], $dates['endDate']);
|
||||
createCourseSessions($courses, $administratorId, $dates['startDate'], $dates['endDate']);
|
||||
|
||||
// Creates course sessions for the following month
|
||||
$offsetDay = intval(substr($dates['endDate'], 8, 2)) - OFFSET;
|
||||
if (date("Y-m-d") >= date(substr($dates['endDate'], 0, 8).$offsetDay)) {
|
||||
$dates = getQuarterFirstAndLastDates(date("Y-m-d", api_strtotime(date("Y-m-01")." + 3 month")));
|
||||
// Get courses that don't have any session the next month
|
||||
$courses = CourseManager::getCoursesWithoutSession($dates['startDate'], $dates['endDate']);
|
||||
createCourseSessions($courses, $administratorId, $dates['startDate'], $dates['endDate']);
|
||||
}
|
||||
26
main/cron/document/finddoc.php
Normal file
26
main/cron/document/finddoc.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Script to find a document with a specific title or path in all courses.
|
||||
*/
|
||||
/**
|
||||
* Code init - comment die() call to enable.
|
||||
*/
|
||||
exit();
|
||||
require '../../inc/global.inc.php';
|
||||
if (empty($_GET['doc'])) {
|
||||
echo "To add a document name to search, add ?doc=abc to the URL";
|
||||
} else {
|
||||
echo "Received param ".Security::remove_XSS($_GET['doc'])."<br />";
|
||||
}
|
||||
$courses_list = CourseManager::get_courses_list();
|
||||
foreach ($courses_list as $course) {
|
||||
$title = Database::escape_string($_GET['doc']);
|
||||
$td = Database::get_course_table(TABLE_DOCUMENT);
|
||||
$sql = "SELECT id, path FROM $td WHERE c_id = ".$course['id']." AND path LIKE '%$title%' OR title LIKE '%$title%'";
|
||||
$res = Database::query($sql);
|
||||
if (Database::num_rows($res) > 0) {
|
||||
while ($row = Database::fetch_array($res)) {
|
||||
echo "Found doc ".$row['id']."-> ".$row['path']." in course ".$course['code']."<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
69
main/cron/document/index_all_docs.php
Normal file
69
main/cron/document/index_all_docs.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Script to find a document with a specific title or path in all courses.
|
||||
*/
|
||||
/**
|
||||
* Code init - comment die() call to enable.
|
||||
*/
|
||||
exit();
|
||||
require '../../inc/global.inc.php';
|
||||
if (empty($_GET['doc'])) {
|
||||
echo "To add a document name to search, add ?doc=abc to the URL\n";
|
||||
} else {
|
||||
echo "Received param ".$_GET['doc']."<br />\n";
|
||||
}
|
||||
$allowed_mime_types = DocumentManager::file_get_mime_type(true);
|
||||
$allowed_extensions = [
|
||||
'doc',
|
||||
'docx',
|
||||
'ppt',
|
||||
'pptx',
|
||||
'pps',
|
||||
'ppsx',
|
||||
'xls',
|
||||
'xlsx',
|
||||
'odt',
|
||||
'odp',
|
||||
'ods',
|
||||
'pdf',
|
||||
'txt',
|
||||
'rtf',
|
||||
'msg',
|
||||
'csv',
|
||||
'html',
|
||||
'htm',
|
||||
];
|
||||
$courses_list = CourseManager::get_courses_list();
|
||||
|
||||
// Simulating empty specific fields (this is necessary for indexing)
|
||||
require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
|
||||
$specific_fields = get_specific_field_list();
|
||||
$specific_fields_values = [];
|
||||
foreach ($specific_fields as $sf) {
|
||||
$specific_fields_values[$sf['code']] = '';
|
||||
}
|
||||
$td = Database::get_course_table(TABLE_DOCUMENT);
|
||||
|
||||
foreach ($courses_list as $course) {
|
||||
$course_dir = $course['directory'].'/document';
|
||||
$title = Database::escape_string($_GET['doc']);
|
||||
$sql = "SELECT id, path, session_id FROM $td WHERE c_id = ".$course['id']." AND path LIKE '%$title%' or title LIKE '%$title%'";
|
||||
$res = Database::query($sql);
|
||||
if (Database::num_rows($res) > 0) {
|
||||
while ($row = Database::fetch_array($res)) {
|
||||
$doc_path = api_get_path(SYS_COURSE_PATH).$course_dir.$row['path'];
|
||||
$extensions = preg_split("/[\/\\.]/", $doc_path);
|
||||
$doc_ext = strtolower($extensions[count($extensions) - 1]);
|
||||
if (in_array($doc_ext, $allowed_extensions) && !is_dir($doc_path)) {
|
||||
$doc_mime = mime_content_type($doc_path);
|
||||
echo "Indexing doc ".$row['id']." (".$row['path'].") in course ".$course['code']."\n";
|
||||
$residx = DocumentManager::index_document($row['id'], $course['code'], $row['session_id'], $course['course_language'], $specific_fields_values);
|
||||
if ($residx) {
|
||||
echo "Success\n";
|
||||
} else {
|
||||
echo "Failure\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
main/cron/fix_course_spent_time.php
Normal file
75
main/cron/fix_course_spent_time.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script checks and updates (if you uncomment the query)
|
||||
* the records in track_e_course_access that is used to calculate the
|
||||
* total course time.
|
||||
*/
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||
|
||||
exit;
|
||||
|
||||
opcache_reset();
|
||||
|
||||
$maxSeconds = 10 * 60 * 60; // Check records higher than 7 hours
|
||||
$addSecondsToLogin = 2 * 60 * 60; // Update this abusive records with 3 hours
|
||||
$limit = 10; // Only fix first 10
|
||||
$sendMessage = true;
|
||||
$userId = 868; // User id that will receive a report
|
||||
$update = false;
|
||||
|
||||
$sql = "SELECT
|
||||
course_access_id,
|
||||
counter,
|
||||
UNIX_TIMESTAMP(logout_course_date) - UNIX_TIMESTAMP(login_course_date) diff,
|
||||
login_course_date,
|
||||
logout_course_date
|
||||
FROM track_e_course_access
|
||||
WHERE UNIX_TIMESTAMP(logout_course_date) > UNIX_TIMESTAMP(login_course_date)
|
||||
ORDER by diff DESC
|
||||
LIMIT $limit
|
||||
";
|
||||
|
||||
$result = Database::query($sql);
|
||||
$log = '';
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
if ($row['diff'] >= $maxSeconds) {
|
||||
$id = $row['course_access_id'];
|
||||
$loginDate = $row['login_course_date'];
|
||||
$logoutDate = $row['logout_course_date'];
|
||||
$diff = round($row['diff'] / 60 / 60);
|
||||
|
||||
$login = api_strtotime($row['login_course_date'], 'UTC') + $addSecondsToLogin;
|
||||
$newLogout = api_get_utc_datetime($login);
|
||||
$sql = "UPDATE track_e_course_access
|
||||
SET logout_course_date = '$newLogout'
|
||||
WHERE course_access_id = $id ;
|
||||
";
|
||||
|
||||
// Uncomment to fix
|
||||
if ($update) {
|
||||
Database::query($sql);
|
||||
}
|
||||
|
||||
$report = "Login : $loginDate ";
|
||||
$report .= PHP_EOL;
|
||||
$report .= "Logout: $logoutDate Diff in hours: $diff";
|
||||
$report .= PHP_EOL;
|
||||
$report .= $sql;
|
||||
$report .= PHP_EOL;
|
||||
$report .= PHP_EOL;
|
||||
$log .= $report;
|
||||
echo $report;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendMessage && !empty($log)) {
|
||||
$log = nl2br($log);
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
'Course time spent fixes',
|
||||
$log,
|
||||
1
|
||||
);
|
||||
}
|
||||
79
main/cron/fix_fill_blank.php
Normal file
79
main/cron/fix_fill_blank.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
api_protect_admin_script();
|
||||
|
||||
$table = Database::get_course_table(TABLE_QUIZ_ANSWER);
|
||||
|
||||
$execute = isset($_GET['execute']) ? $_GET['execute'] : null;
|
||||
$courseId = isset($_GET['c_id']) ? $_GET['c_id'] : null;
|
||||
$questionId = isset($_GET['question_id']) ? $_GET['question_id'] : null;
|
||||
|
||||
$sql2 = "SELECT * FROM $table WHERE answer LIKE '%[%]%'";
|
||||
|
||||
if (!empty($courseId)) {
|
||||
$courseId = intval($courseId);
|
||||
$sql2 .= " AND c_id = $courseId";
|
||||
if (!empty($questionId)) {
|
||||
$questionId = intval($questionId);
|
||||
$sql2 .= " AND question_id = $questionId";
|
||||
}
|
||||
}
|
||||
|
||||
var_dump($sql2);
|
||||
|
||||
$res2 = Database::query($sql2);
|
||||
|
||||
while ($row = Database::fetch_array($res2)) {
|
||||
$id = $row['iid'];
|
||||
$courseId = $row['c_id'];
|
||||
$idAuto = $row['id_auto'];
|
||||
$answerOriginal = $row['answer'];
|
||||
|
||||
$answer = $row['answer'];
|
||||
|
||||
$answer = str_replace('â', 'â', $answer);
|
||||
$answer = str_replace('à', 'à', $answer);
|
||||
$answer = str_replace('é', 'é', $answer);
|
||||
$answer = str_replace('ê', 'ê', $answer);
|
||||
$answer = str_replace('è', 'è', $answer);
|
||||
$answer = str_replace('í', 'í', $answer);
|
||||
$answer = str_replace('ì', 'ì', $answer);
|
||||
$answer = str_replace('ó', 'ó', $answer);
|
||||
$answer = str_replace('ò', 'ò', $answer);
|
||||
$answer = str_replace('ù', 'ù', $answer);
|
||||
$answer = str_replace('ú', 'ú', $answer);
|
||||
$answer = str_replace('ç', 'ç', $answer);
|
||||
$answer = str_replace('À', 'À', $answer);
|
||||
$answer = str_replace('Ç', 'Ç', $answer);
|
||||
|
||||
$answerFixedNotEscape = $answer;
|
||||
|
||||
$answer = Database::escape_string($answer);
|
||||
|
||||
$sql4 = "UPDATE c_quiz_answer SET
|
||||
answer = '$answer'
|
||||
WHERE id = $id AND c_id = $courseId AND id_auto = $idAuto ";
|
||||
|
||||
if ($answerOriginal != $answerFixedNotEscape) {
|
||||
if (!empty($execute) && $execute == 1) {
|
||||
Database::query($sql4);
|
||||
echo '<pre>';
|
||||
var_dump($sql4);
|
||||
echo '</pre>';
|
||||
var_dump('executed');
|
||||
} else {
|
||||
echo "to be executed";
|
||||
echo '<pre>';
|
||||
var_dump($sql4);
|
||||
echo 'Original:<br />';
|
||||
echo $answerOriginal;
|
||||
echo 'Fixed:<br />';
|
||||
echo $answerFixedNotEscape;
|
||||
echo '</pre>';
|
||||
echo '----------<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
58
main/cron/fix_lp_total_time.php
Normal file
58
main/cron/fix_lp_total_time.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script checks that the c_lp_item_view.total_time field
|
||||
* doesn't have big values. The scripts updates it or send a message to the admin (depending the settings).
|
||||
*/
|
||||
exit;
|
||||
|
||||
require_once __DIR__.'/../../main/inc/global.inc.php';
|
||||
|
||||
opcache_reset();
|
||||
|
||||
$maxSeconds = 5 * 60 * 60; // Check records higher than 5 hours
|
||||
$valueToUpdate = 1 * 60 * 60; // Update this abusive records with 1 hours
|
||||
$limit = 10; // Only fix first 10
|
||||
$sendMessage = true;
|
||||
$userId = 1; // User id that will receive a report
|
||||
$update = false;
|
||||
|
||||
$sql = "SELECT iid, total_time FROM c_lp_item_view
|
||||
WHERE total_time > $maxSeconds
|
||||
order by total_time desc
|
||||
LIMIT $limit
|
||||
";
|
||||
|
||||
$result = Database::query($sql);
|
||||
$log = '';
|
||||
while ($row = Database::fetch_array($result, 'ASSOC')) {
|
||||
$id = $row['iid'];
|
||||
$oldTotalTime = $row['total_time'];
|
||||
$sql = "UPDATE c_lp_item_view SET total_time = '$valueToUpdate' WHERE iid = $id;";
|
||||
// Uncomment to fix
|
||||
if ($update) {
|
||||
Database::query($sql);
|
||||
}
|
||||
|
||||
$oldTotalTime = round($oldTotalTime / 3600, 2);
|
||||
$report = "Previous total_time : ".$oldTotalTime." hours";
|
||||
$report .= PHP_EOL;
|
||||
$report .= "New total_time: $valueToUpdate";
|
||||
$report .= PHP_EOL;
|
||||
$report .= $sql;
|
||||
$report .= PHP_EOL;
|
||||
$report .= PHP_EOL;
|
||||
$log .= $report;
|
||||
echo $report;
|
||||
}
|
||||
|
||||
if ($sendMessage && !empty($log)) {
|
||||
$log = nl2br($log);
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
'LP time abusive fixes',
|
||||
$log,
|
||||
1
|
||||
);
|
||||
}
|
||||
151
main/cron/fix_online_time.php
Normal file
151
main/cron/fix_online_time.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Automatic fix online time procedure. If a user has been idle for $timeLimit
|
||||
* or more then the procedure adds $extraTime to his logout_course_date.
|
||||
*
|
||||
* How to use it:
|
||||
*
|
||||
* By default the script will fix only users with teacher status (COURSEMANAGER)
|
||||
*
|
||||
* php main/cron/fix_online_time.php
|
||||
*
|
||||
* If you want to add an specific status you can call the file with:
|
||||
*
|
||||
* php main/cron/fix_online_time.php status=5
|
||||
*
|
||||
* Where "5" is the value of the 'STUDENT' constant.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*
|
||||
* @author Imanol Losada <imanol.losada@beeznest.com>
|
||||
* @author Julio Montoya
|
||||
*/
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
if (php_sapi_name() != 'cli') {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ids of users that are inside a course right now.
|
||||
*
|
||||
* @param int $status COURSEMANAGER|STUDENT constants
|
||||
*
|
||||
* @return array user id
|
||||
*/
|
||||
function getUsersInCourseIds($status)
|
||||
{
|
||||
$status = (int) $status;
|
||||
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
|
||||
$joinStatement = ' JOIN '.Database::get_main_table(TABLE_MAIN_USER).' ON login_user_id = user_id';
|
||||
|
||||
return Database::select(
|
||||
'login_user_id',
|
||||
$table.$joinStatement,
|
||||
[
|
||||
'where' => [
|
||||
'c_id IS NOT NULL AND status = ?' => [
|
||||
$status,
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a user has been idle for $timeLimit or more then
|
||||
* the procedure adds $extraTime to his logout_course_date.
|
||||
*
|
||||
* @param array $users user id list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function updateUsersInCourseIdleForTimeLimit($users)
|
||||
{
|
||||
$timeLimit = '- 30 minute';
|
||||
$extraTime = '+ 5 minute';
|
||||
$utcResult = Database::fetch_array(Database::query('SELECT UTC_TIMESTAMP'));
|
||||
$dataBaseCurrentHour = array_shift($utcResult);
|
||||
$maximumIdleTimeInCourse = date(
|
||||
'Y-m-d H:i:s',
|
||||
strtotime($dataBaseCurrentHour.' '.$timeLimit)
|
||||
);
|
||||
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
|
||||
$onLineTrackTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
|
||||
$count = 1;
|
||||
foreach ($users as $key => $value) {
|
||||
$value = array_shift($value);
|
||||
$logResult = Database::select(
|
||||
'course_access_id, logout_course_date',
|
||||
$table,
|
||||
[
|
||||
'where' => [
|
||||
'user_id = ?' => [
|
||||
$value,
|
||||
],
|
||||
],
|
||||
'order' => 'course_access_id DESC',
|
||||
'limit' => '1',
|
||||
]
|
||||
);
|
||||
$currentTeacherData = array_shift($logResult);
|
||||
Database::update(
|
||||
$table,
|
||||
[
|
||||
'logout_course_date' => date(
|
||||
'Y-m-d H:i:s',
|
||||
strtotime($currentTeacherData['logout_course_date'].' '.$extraTime)
|
||||
),
|
||||
],
|
||||
[
|
||||
'user_id = ? AND logout_course_date < ? AND course_access_id = ?' => [
|
||||
$value,
|
||||
$maximumIdleTimeInCourse,
|
||||
$currentTeacherData['course_access_id'],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
/*
|
||||
* (Avoid multiple updates)
|
||||
* When the user enters a course, this field is updated with the course code.
|
||||
* And when the user goes to another tool, returns to NULL
|
||||
*/
|
||||
$userId = intval($value);
|
||||
$sql = "UPDATE $onLineTrackTable
|
||||
SET c_id = NULL
|
||||
WHERE login_user_id = $userId";
|
||||
Database::query($sql);
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
// Default status when running script
|
||||
$status = COURSEMANAGER;
|
||||
if (!empty($argv) && isset($argv[1])) {
|
||||
// Get status from parameter
|
||||
parse_str($argv[1], $params);
|
||||
if (isset($params['status'])) {
|
||||
$status = (int) $params['status'];
|
||||
}
|
||||
}
|
||||
|
||||
$statusToString = api_get_status_langvars();
|
||||
if (isset($statusToString[$status])) {
|
||||
echo "Fixing users with status: '$status' = ".$statusToString[$status].PHP_EOL;
|
||||
} else {
|
||||
echo "User status not '$status' not found. Try with status=1 or status=5";
|
||||
exit;
|
||||
}
|
||||
|
||||
$users = getUsersInCourseIds($status);
|
||||
if (!empty($users)) {
|
||||
$result = updateUsersInCourseIdleForTimeLimit($users);
|
||||
echo "# users updated: $result".PHP_EOL;
|
||||
} else {
|
||||
echo "Nothing to update. No users found to be fixed.".PHP_EOL;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Script to send notification to course's teachers when there are activities in a thread of a forum in his courses in the last X days
|
||||
* The number of days is defined at the begining of the script with the variable
|
||||
* It will send one sigle mail per user to notify with a line for each thread including thread's title, thread link and number of new post.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*/
|
||||
|
||||
//This variable define the number of days in the past to look for activies in the forums
|
||||
//This variable should be the same as the periodicity of the cron (if the cron is every day, then the variable should be equal to 1)
|
||||
$numberOfDaysForLastActivy = 1;
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
if ('cli' != php_sapi_name()) {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
$date = new DateTime('now', new DateTimeZone('UTC'));
|
||||
$date->modify("-$numberOfDaysForLastActivy day");
|
||||
$startDate = $date->format('Y-m-d H:i:s');
|
||||
|
||||
$tablePost = Database::get_course_table(TABLE_FORUM_POST);
|
||||
$tableThread = Database::get_course_table(TABLE_FORUM_THREAD);
|
||||
$UpdatedThreads = [];
|
||||
$sql = "SELECT * FROM $tableThread WHERE thread_date > '".$startDate."'";
|
||||
$result = Database::query($sql);
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$courseInfo = api_get_course_info_by_id($row['c_id']);
|
||||
$updatedThreads[$row['c_id']]['courseName'] = $courseInfo['name'];
|
||||
$sqlNbPost = "SELECT count(*) as nbPost FROM $tablePost WHERE thread_id = '".$row['iid']."' and post_date > '".$startDate."'";
|
||||
$resultNbPost = Database::query($sqlNbPost);
|
||||
$rowNbPost = Database::fetch_array($resultNbPost);
|
||||
$updatedThreads[$row['c_id']][$row['session_id']][$row['iid']] = [
|
||||
'threadTitle' => $row['thread_title'],
|
||||
'threadNbPost' => $rowNbPost['nbPost'],
|
||||
'threadLink' => api_get_path(WEB_PATH).'main/forum/viewthread.php?cidReq='.$courseInfo['code'].'&id_session='.$row['session_id'].'&gidReq=0&gradebook=0&origin=&forum='.$row['forum_id'].'&thread='.$row['iid'],
|
||||
];
|
||||
}
|
||||
foreach ($updatedThreads as $courseId => $sessions) {
|
||||
foreach ($sessions as $sessionId => $threads) {
|
||||
if ($sessionId === 0) {
|
||||
$teacherList = CourseManager::getTeachersFromCourse($courseId, false);
|
||||
foreach ($teacherList as $teacher) {
|
||||
$usersToNotify[$teacher['id']][$courseId]['courseName'] = $sessions['courseName'];
|
||||
$usersToNotify[$teacher['id']][$courseId][$sessionId] = $threads;
|
||||
}
|
||||
} else {
|
||||
$courseCoachs = CourseManager::get_coachs_from_course(
|
||||
$sessionId,
|
||||
$courseId,
|
||||
false
|
||||
);
|
||||
foreach ($courseCoachs as $coach) {
|
||||
$usersToNotify[$coach['user_id']][$courseId]['courseName'] = $sessions['courseName'];
|
||||
$usersToNotify[$coach['user_id']][$courseId][$sessionId] = $threads;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($usersToNotify as $userId => $notifyInfo) {
|
||||
sendMessage($userId, $notifyInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message to notify the specific user for all its courses and threads that have been updated,
|
||||
* manage the corresponding template and send through MessageManager::send_message_simple.
|
||||
*
|
||||
* @param $toUserId
|
||||
* @param $notifyInfo
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
function sendMessage(
|
||||
$toUserId,
|
||||
$notifyInfo
|
||||
) {
|
||||
$userInfo = api_get_user_info($toUserId);
|
||||
$language = $userInfo['language'];
|
||||
$subject = getUserLang('ForumBulkNotificationMailSubject', $language);
|
||||
|
||||
$bodyTemplate = new Template(
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
$userFullName = api_get_person_name($userInfo['firstname'], $userInfo['lastname']);
|
||||
$bodyTemplate->assign('HelloX', sprintf(getUserLang('HelloX', $language), $userFullName));
|
||||
$bodyTemplate->assign('NotificationInYouForums', sprintf(getUserLang('NotificationInYouForums', $language)));
|
||||
$bodyTemplate->assign('SignatureFormula', sprintf(getUserLang('SignatureFormula', $language)));
|
||||
$bodyTemplate->assign('notifyInfo', $notifyInfo);
|
||||
|
||||
$bodyLayout = $bodyTemplate->get_template(
|
||||
'mail/cron_forum_update_bulk_notification_body.tpl'
|
||||
);
|
||||
|
||||
$content = $bodyTemplate->fetch($bodyLayout);
|
||||
|
||||
return MessageManager::send_message_simple(
|
||||
$toUserId,
|
||||
$subject,
|
||||
$content,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translated (localized) string by user language.
|
||||
*
|
||||
* @param $variable
|
||||
* @param $language
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getUserLang($variable, $language)
|
||||
{
|
||||
$languageFilesToLoad = api_get_language_files_to_load($language);
|
||||
foreach ($languageFilesToLoad as $languageFile) {
|
||||
include $languageFile;
|
||||
}
|
||||
|
||||
$translate = $variable;
|
||||
if (isset($$variable)) {
|
||||
$langVariable = $$variable;
|
||||
$translate = $langVariable;
|
||||
}
|
||||
|
||||
return $translate;
|
||||
}
|
||||
|
||||
exit();
|
||||
119
main/cron/hosting_total_size_limit.php
Normal file
119
main/cron/hosting_total_size_limit.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Checks total platform size.
|
||||
*
|
||||
* @param bool $debug
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function isTotalPortalSizeBiggerThanLimit($debug = true)
|
||||
{
|
||||
$sizeLimit = api_get_configuration_value('hosting_total_size_limit');
|
||||
if (empty($sizeLimit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$updateFile = true;
|
||||
$file = api_get_path(SYS_COURSE_PATH).'hosting_total_size.php';
|
||||
|
||||
// Default data
|
||||
$hostingData = [
|
||||
'frequency' => 86400,
|
||||
];
|
||||
|
||||
$log = null;
|
||||
|
||||
// Check if file exists and if it is updated
|
||||
if (file_exists($file)) {
|
||||
$hostingDataFromFile = require $file;
|
||||
|
||||
// Check time() is UTC
|
||||
if (isset($hostingDataFromFile['updated_at']) &&
|
||||
isset($hostingDataFromFile['frequency']) &&
|
||||
isset($hostingDataFromFile['size'])
|
||||
) {
|
||||
$hostingData = $hostingDataFromFile;
|
||||
|
||||
$time = $hostingData['updated_at'] + $hostingData['frequency'];
|
||||
$diff = $time - time();
|
||||
|
||||
if ($time > time()) {
|
||||
$log .= "You need to wait $diff seconds to update the file \n";
|
||||
$updateFile = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now get values for total portal size
|
||||
$log .= "Frequency loaded: ".$hostingData['frequency']."\n";
|
||||
|
||||
if ($updateFile) {
|
||||
$log .= "Updating total size ... \n";
|
||||
$totalSize = calculateTotalPortalSize($debug);
|
||||
$log .= "Total size calculated: $totalSize \n";
|
||||
|
||||
$hostingData['updated_at'] = time();
|
||||
$hostingData['size'] = $totalSize;
|
||||
|
||||
$writer = new Zend\Config\Writer\PhpArray();
|
||||
$phpCode = $writer->toString($hostingData);
|
||||
file_put_contents($file, $phpCode);
|
||||
$log .= "File saved in $file \n";
|
||||
} else {
|
||||
$log .= "Total size not updated \n";
|
||||
$totalSize = $hostingData['size'];
|
||||
}
|
||||
|
||||
$result = true;
|
||||
|
||||
if ($totalSize > $sizeLimit) {
|
||||
$log .= "Current total size of $totalSize MB is bigger than limit: $sizeLimit MB \n";
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
echo $log;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $debug
|
||||
*
|
||||
* @return int total size in MB
|
||||
*/
|
||||
function calculateTotalPortalSize($debug)
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_DOCUMENT);
|
||||
// Documents
|
||||
$sql = "SELECT SUM(size) total FROM $table
|
||||
WHERE filetype = 'file' AND c_id <> ''";
|
||||
$result = Database::query($sql);
|
||||
$row = Database::fetch_array($result, 'ASSOC');
|
||||
$totalSize = $row['total'];
|
||||
|
||||
if ($debug) {
|
||||
echo "Total size in table $table ".(round($totalSize / 1024))." MB \n";
|
||||
}
|
||||
|
||||
$table = Database::get_course_table(TABLE_FORUM_ATTACHMENT);
|
||||
$sql = "SELECT SUM(size) total FROM $table WHERE c_id <> ''";
|
||||
$result = Database::query($sql);
|
||||
$row = Database::fetch_array($result, 'ASSOC');
|
||||
$subTotal = $row['total'];
|
||||
$totalSize += $subTotal;
|
||||
if ($debug) {
|
||||
echo "Total size in table $table ".(round($subTotal / 1024))." MB \n";
|
||||
}
|
||||
|
||||
$totalSize = $totalSize / 1024;
|
||||
|
||||
return $totalSize;
|
||||
}
|
||||
|
||||
isTotalPortalSizeBiggerThanLimit(true);
|
||||
3729
main/cron/import_csv.php
Normal file
3729
main/cron/import_csv.php
Normal file
File diff suppressed because it is too large
Load Diff
5
main/cron/index.html
Normal file
5
main/cron/index.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
43
main/cron/lang/check_parse_lang.php
Normal file
43
main/cron/lang/check_parse_lang.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Script to check that no language file has parse errors.
|
||||
*
|
||||
* @package chamilo.cron.lang
|
||||
*/
|
||||
/**
|
||||
* Includes and declarations.
|
||||
*/
|
||||
//die();
|
||||
require_once '../../inc/global.inc.php';
|
||||
$path = api_get_path(SYS_LANG_PATH).'english';
|
||||
ini_set('memory_limit', '128M');
|
||||
/**
|
||||
* Main code.
|
||||
*/
|
||||
$terms = [];
|
||||
$list = SubLanguageManager::get_lang_folder_files_list($path);
|
||||
$langs = scandir(api_get_path(SYS_LANG_PATH));
|
||||
foreach ($langs as $lang) {
|
||||
$dir = api_get_path(SYS_LANG_PATH).$lang;
|
||||
if (is_dir($dir) && substr($lang, 0, 1) != '.' && !empty($lang)) {
|
||||
echo "$lang...";
|
||||
$ok = true;
|
||||
foreach ($list as $entry) {
|
||||
$file = $dir.'/'.$entry;
|
||||
$out = [];
|
||||
if (is_file($file)) {
|
||||
//$terms = array_merge($terms,SubLanguageManager::get_all_language_variable_in_file($file,true));
|
||||
@exec('php -l '.$file, $out);
|
||||
if (substr($out[0], 0, 2) != 'No') {
|
||||
echo $out[0]."\n";
|
||||
$ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($ok) {
|
||||
echo "OK\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "Done\n";
|
||||
217
main/cron/lang/langstats.class.php
Normal file
217
main/cron/lang/langstats.class.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This class takes the creation and querying of an SQLite DB in charge. The
|
||||
* goal of this DB is to get stats on the usage of language vars for a common
|
||||
* user.
|
||||
*
|
||||
* @package chamilo.cron.lang
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class takes the creation and querying of an SQLite DB in charge. The
|
||||
* goal of this DB is to get stats on the usage of language vars for a common
|
||||
* user. This class requires the SQLite extension of PHP to be installed. The
|
||||
* check for the availability of sqlite_open() should be made before calling
|
||||
* the constructor (preferably).
|
||||
*/
|
||||
class langstats
|
||||
{
|
||||
public $db; //database connector
|
||||
public $error; //stored errors
|
||||
public $db_type = 'sqlite';
|
||||
|
||||
public function __construct($file = '')
|
||||
{
|
||||
switch ($this->db_type) {
|
||||
case 'sqlite':
|
||||
if (!class_exists('SQLite3')) {
|
||||
$this->error = 'SQLiteNotAvailable';
|
||||
|
||||
return false; //cannot use if sqlite not installed
|
||||
}
|
||||
if (empty($file)) {
|
||||
$file = api_get_path(SYS_ARCHIVE_PATH).'/langstasdb';
|
||||
}
|
||||
if (is_file($file) && is_writeable($file)) {
|
||||
$this->db = new SQLite3($file, SQLITE3_OPEN_READWRITE);
|
||||
} else {
|
||||
try {
|
||||
$this->db = new SQLite3($file);
|
||||
} catch (Exception $e) {
|
||||
$this->error = 'DatabaseCreateError';
|
||||
error_log('Exception: '.$e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
$err = $this->db->exec(
|
||||
'CREATE TABLE lang_freq ('
|
||||
.' id integer PRIMARY KEY AUTOINCREMENT, ' //autoincrement in SQLITE
|
||||
.' term_name text, term_file text, term_count integer default 0)'
|
||||
);
|
||||
if ($err === false) {
|
||||
$this->error = 'CouldNotCreateTable';
|
||||
|
||||
return false;
|
||||
}
|
||||
$err = $this->db->exec(
|
||||
'CREATE INDEX lang_freq_terms_idx ON lang_freq(term_name, term_file)'
|
||||
);
|
||||
if ($err === false) {
|
||||
$this->error = 'CouldNotCreateIndex';
|
||||
|
||||
return false;
|
||||
}
|
||||
// Table and index created, move on.
|
||||
}
|
||||
break;
|
||||
case 'mysql': //implementation not finished
|
||||
if (!function_exists('mysql_connect')) {
|
||||
$this->error = 'SQLiteNotAvailable';
|
||||
|
||||
return false; //cannot use if sqlite not installed
|
||||
}
|
||||
$err = Database::query('SELECT * FROM lang_freq');
|
||||
if ($err === false) { //the database probably does not exist, create it
|
||||
$err = Database::query(
|
||||
'CREATE TABLE lang_freq ('
|
||||
.' id int PRIMARY KEY AUTO_INCREMENT, '
|
||||
.' term_name text, term_file text default \'\', term_count int default 0)'
|
||||
);
|
||||
if ($err === false) {
|
||||
$this->error = 'CouldNotCreateTable';
|
||||
|
||||
return false;
|
||||
}
|
||||
} // if no error, we assume the table exists
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a count for a specific term.
|
||||
*
|
||||
* @param string The language term used
|
||||
* @param string The file from which the language term came from
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function add_use($term, $term_file = '')
|
||||
{
|
||||
$term = $this->db->escapeString($term);
|
||||
$term_file = $this->db->escapeString($term_file);
|
||||
$sql = "SELECT id, term_name, term_file, term_count FROM lang_freq WHERE term_name='$term' and term_file='$term_file'";
|
||||
$ress = $this->db->query($sql);
|
||||
if ($ress === false) {
|
||||
$this->error = 'CouldNotQueryTermFromTable';
|
||||
|
||||
return false;
|
||||
}
|
||||
$i = 0;
|
||||
while ($row = $ress->fetchArray(SQLITE3_BOTH)) {
|
||||
$num = $row[3];
|
||||
$num++;
|
||||
$i++;
|
||||
$res = $this->db->query(
|
||||
'UPDATE lang_freq SET term_count = '.$num.' WHERE id = '.$row[0]
|
||||
);
|
||||
if ($res === false) {
|
||||
$this->error = 'CouldNotUpdateTerm';
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return $row[0];
|
||||
}
|
||||
}
|
||||
if ($i == 0) {
|
||||
//No term found in the table, register as new term
|
||||
$resi = $this->db->query(
|
||||
"INSERT INTO lang_freq(term_name, term_file, term_count) VALUES ('$term', '$term_file', 1)"
|
||||
);
|
||||
if ($resi === false) {
|
||||
$this->error = 'CouldNotInsertRow';
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return $this->db->lastInsertRowID();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get a list of the X most-requested terms.
|
||||
*
|
||||
* @param int Limit of terms to show
|
||||
*
|
||||
* @return array List of most requested terms
|
||||
*/
|
||||
public function get_popular_terms($num = 1000)
|
||||
{
|
||||
$num = (int) $num;
|
||||
$res = $this->db->query(
|
||||
'SELECT * FROM lang_freq
|
||||
ORDER BY term_count DESC LIMIT '.$num
|
||||
);
|
||||
$list = [];
|
||||
while ($row = $res->fetchArray()) {
|
||||
$list[] = $row;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all records in lang_freq.
|
||||
*
|
||||
* @return resource true
|
||||
*/
|
||||
public function clear_all()
|
||||
{
|
||||
$res = sqlite_query($this->db, 'DELETE FROM lang_freq WHERE 1=1');
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the language variables with their corresponding
|
||||
* file of origin. This function tolerates a certain rate of error due to
|
||||
* the duplication of variables in language files.
|
||||
*
|
||||
* @return array variable => origin file
|
||||
*/
|
||||
public function get_variables_origin()
|
||||
{
|
||||
$path = api_get_path(SYS_LANG_PATH).'english/';
|
||||
$vars = [];
|
||||
$priority = ['trad4all'];
|
||||
foreach ($priority as $file) {
|
||||
$list = SubLanguageManager::get_all_language_variable_in_file(
|
||||
$path.$file.'.inc.php',
|
||||
true
|
||||
);
|
||||
foreach ($list as $var => $trad) {
|
||||
$vars[$var] = $file.'.inc.php';
|
||||
}
|
||||
}
|
||||
$files = scandir($path);
|
||||
foreach ($files as $file) {
|
||||
if (substr($file, 0, 1) == '.' or in_array($file, $priority)) {
|
||||
continue;
|
||||
}
|
||||
$list = SubLanguageManager::get_all_language_variable_in_file(
|
||||
$path.$file,
|
||||
true
|
||||
);
|
||||
foreach ($list as $var => $trad) {
|
||||
$vars[$var] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
}
|
||||
84
main/cron/lang/langstats.php
Normal file
84
main/cron/lang/langstats.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* This script prints a list of most used language terms. The registration of
|
||||
* frequency for language variables is a very heavy operation.
|
||||
* To enable, add "$_configuration['language_measure_frequency' ] = 1;" at the
|
||||
* end of main/inc/conf/configuration.php. Remove when done.
|
||||
* Add ?output=1 to the URL to generate languag files in /tmp/lang/ with just
|
||||
* the number of terms you want.
|
||||
*/
|
||||
/**
|
||||
* Requires.
|
||||
*/
|
||||
exit();
|
||||
require_once '../../inc/global.inc.php';
|
||||
require_once 'langstats.class.php';
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
$terms_limit = 10000 + 50;
|
||||
$x_most_popular = 2000;
|
||||
$output = false;
|
||||
$ls = new langstats();
|
||||
if ($ls === false) {
|
||||
exit($ls->error);
|
||||
}
|
||||
$list = $ls->get_popular_terms($x_most_popular);
|
||||
if ($_GET['output'] == 1) {
|
||||
$output = true;
|
||||
$variables_origin = $ls->get_variables_origin();
|
||||
}
|
||||
/**
|
||||
* Display.
|
||||
*/
|
||||
if (count($list) == 0) {
|
||||
echo 'No terms loaded so far';
|
||||
}
|
||||
if (count($list) > 0) {
|
||||
$i = 1;
|
||||
$j = 1;
|
||||
$k = 0;
|
||||
$files = [];
|
||||
$trans = [];
|
||||
echo 'Number of records: '.count($list).'<br />';
|
||||
echo '<table><tr><th>Index</th><th>Registration order</th><th>Term</th>'.($output == 1 ? '<th>Origin</th>' : '').'<th>Count</th></tr>';
|
||||
foreach ($list as $elem) {
|
||||
if ($k > $terms_limit) {
|
||||
break;
|
||||
}
|
||||
$fixed_elem = $elem;
|
||||
if ($output) {
|
||||
if (empty($variables_origin[$elem['term_name']]) && !empty($variables_origin['lang'.$elem['term_name']])) {
|
||||
$fixed_elem = ['id' => $elem['id'], 'term_name' => 'lang'.$elem['term_name'], 'term_count' => $elem['term_count']];
|
||||
}
|
||||
if (empty($variables_origin[$fixed_elem['term_name']])) {
|
||||
continue;
|
||||
}
|
||||
$files[$variables_origin[$fixed_elem['term_name']]][] = $fixed_elem['term_name'];
|
||||
$translation = get_lang($fixed_elem['term_name']);
|
||||
$k += str_word_count($translation);
|
||||
$trans[$fixed_elem['term_name']] = $translation;
|
||||
$j++;
|
||||
}
|
||||
echo '<tr><td>', $i,
|
||||
'</td><td>', $fixed_elem['id'],
|
||||
'</td><td>', $fixed_elem['term_name'];
|
||||
if ($output) {
|
||||
echo '</td><td>'.$variables_origin[$fixed_elem['term_name']];
|
||||
}
|
||||
echo '</td><td>', $fixed_elem['term_count'], '</td></tr>';
|
||||
$i++;
|
||||
}
|
||||
echo '</table>';
|
||||
if ($output) {
|
||||
@mkdir('/tmp/lang');
|
||||
foreach ($files as $file => $terms) {
|
||||
@touch('/tmp/lang/'.$file);
|
||||
file_put_contents('/tmp/lang/'.$file, "<?php".PHP_EOL);
|
||||
foreach ($terms as $term) {
|
||||
file_put_contents('/tmp/lang/'.$file, '$'.$term.' = "'.str_replace('"', '\"', $trans[$term]).'";'.PHP_EOL, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
104
main/cron/lang/langstats_file_builder.php
Normal file
104
main/cron/lang/langstats_file_builder.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This script generates a directory based on the English language variables
|
||||
* but only composed of the 10,000 (can be configured) most frequent words
|
||||
* used in Chamilo. This implies first using the langstats.php script, which
|
||||
* in turn implies configuring an additional variable in configuration.php
|
||||
* (see langstats.php for more info).
|
||||
* When running the language_builder, please make sure this parameter is
|
||||
* set to 0 in the configuration.php file, otherwise it will take *ages*.
|
||||
*/
|
||||
require_once '../../inc/global.inc.php';
|
||||
require_once 'langstats.class.php';
|
||||
global $_configuration;
|
||||
$_configuration['language_measure_frequency'] = 0;
|
||||
$langstats = new langstats();
|
||||
$orig_lang = 'english';
|
||||
/**
|
||||
* Init.
|
||||
*/
|
||||
$words_limit = 10000; //change this if you want more words
|
||||
$terms_limit = 3000; //change this if you think you'll need more terms
|
||||
$terms = $langstats->get_popular_terms($terms_limit);
|
||||
$words_counter = 0;
|
||||
$i = 0;
|
||||
$terms_in_limit = [];
|
||||
$lang_dir = api_get_path(SYS_LANG_PATH);
|
||||
$arch_dir = api_get_path(SYS_ARCHIVE_PATH);
|
||||
/**
|
||||
* Code run.
|
||||
*/
|
||||
foreach ($terms as $row) {
|
||||
if ($words_counter > 10000) {
|
||||
break;
|
||||
}
|
||||
$words = str_word_count(get_lang($row['term_name'], null, $orig_lang));
|
||||
$words_counter += $words;
|
||||
$terms_in_limit[$row['term_name']] = $i;
|
||||
//echo "Term <b>".$row['term_name']."</b> is <b>'".get_lang($row['term_name'],null,$orig_lang)."'</b> which means $words words<br /><br />\n";
|
||||
//if ($words_counter%1000 >= 0) {
|
||||
//echo "Reached $words_counter words at term $i (".$row['term_name']." used ".$row['term_count']." times)...<br />\n";
|
||||
//}
|
||||
$i++;
|
||||
}
|
||||
//echo $words_counter.'<br />';
|
||||
|
||||
echo "Reached ".count($terms_in_limit)." terms for the $words_counter most-used words<br /><br />\n";
|
||||
|
||||
echo "Scanning English files, trying to find these terms...<br />\n";
|
||||
if (!is_dir($arch_dir.'/langstats')) {
|
||||
mkdir($arch_dir.'/langstats');
|
||||
mkdir($arch_dir.'/langstats/'.$orig_lang);
|
||||
}
|
||||
$list_files = scandir($lang_dir.'/'.$orig_lang);
|
||||
$j = 1;
|
||||
$terms_found = [];
|
||||
$words_found = 0;
|
||||
$global_var = []; //keep the combination of all vars
|
||||
$terms_in_limit = array_flip($terms_in_limit);
|
||||
foreach ($list_files as $file) {
|
||||
if (substr($file, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
//echo "'".substr($file,0,-8)."',<br />"; //print in a PHP array format
|
||||
$vars = file($lang_dir.'/'.$orig_lang.'/'.$file);
|
||||
$local_var = [];
|
||||
$file_string = '<?php'."\n";
|
||||
foreach ($vars as $line) {
|
||||
$var = [];
|
||||
$res = preg_match('/^(\$\w*)/', $line, $var);
|
||||
if ($res > 0) {
|
||||
//echo $var[1]."<br />";
|
||||
|
||||
if (in_array(substr($var[1], 1), $terms_in_limit)) {
|
||||
//echo "Var ".$var[1]." was in the limit<br />";
|
||||
$local_var[$var[1]] = $line;
|
||||
$file_string .= $line;
|
||||
$terms_found[] = substr($var[1], 1); //e.g. store Tools
|
||||
$words_found += str_word_count(get_lang($var[1], null, $orig_lang));
|
||||
} elseif (in_array(substr($var[1], 5), $terms_in_limit)) {
|
||||
//echo "Var ".$var[1]." was in the limit<br />";
|
||||
$local_var[$var[1]] = $line;
|
||||
$file_string .= $line;
|
||||
$terms_found[] = substr($var[1], 5); //e.g. store langTools
|
||||
$words_found += str_word_count(get_lang(substr($var[1], 5), null, $orig_lang));
|
||||
} //else do not care
|
||||
}
|
||||
}
|
||||
echo "Writing ".$arch_dir.'/langstats/'.$orig_lang.'/'.$file."<br />\n";
|
||||
file_put_contents($arch_dir.'/langstats/'.$orig_lang.'/'.$file, $file_string);
|
||||
$global_var += $local_var;
|
||||
}
|
||||
$terms_diff = count($global_var) - count($terms_in_limit);
|
||||
echo count(
|
||||
$global_var
|
||||
)." terms found in English files (summing up to $words_found words). Some terms ($terms_diff in this case) might have appeared in two different files<br />";
|
||||
/**
|
||||
* Display results.
|
||||
*/
|
||||
echo "Difference between filtered and found in English:<br />";
|
||||
//print_r($terms_found);
|
||||
echo "<pre>".print_r(array_diff($terms_in_limit, $terms_found), 1)."</pre>";
|
||||
echo "#";
|
||||
85
main/cron/lang/list_undefined_langvars.php
Normal file
85
main/cron/lang/list_undefined_langvars.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Cron script to list used, but undefined, language variables.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*/
|
||||
/**
|
||||
* Includes and declarations.
|
||||
*/
|
||||
exit();
|
||||
require_once __DIR__.'/../../inc/global.inc.php';
|
||||
$path = api_get_path(SYS_LANG_PATH).'english';
|
||||
ini_set('memory_limit', '128M');
|
||||
/**
|
||||
* Main code.
|
||||
*/
|
||||
$terms = [];
|
||||
$list = SubLanguageManager::get_lang_folder_files_list($path);
|
||||
foreach ($list as $entry) {
|
||||
$file = $path.'/'.$entry;
|
||||
if (is_file($file)) {
|
||||
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
|
||||
}
|
||||
}
|
||||
// get only the array keys (the language variables defined in language files)
|
||||
$defined_terms = array_flip(array_keys($terms));
|
||||
$terms = null;
|
||||
$hidePlugins = !empty($_GET['hidePlugins']);
|
||||
|
||||
// now get all terms found in all PHP files of Chamilo (this takes some time and memory)
|
||||
$undefined_terms = [];
|
||||
$l = strlen(api_get_path(SYS_PATH));
|
||||
$files = getAllPhpFiles(api_get_path(SYS_PATH));
|
||||
foreach ($files as $file) {
|
||||
$isPlugin = preg_match('#/plugin/#', $file);
|
||||
if ($isPlugin && $hidePlugins) {
|
||||
continue;
|
||||
}
|
||||
//echo 'Analyzing '.$file."<br />";
|
||||
$shortfile = substr($file, $l);
|
||||
$lines = file($file);
|
||||
foreach ($lines as $line) {
|
||||
$myterms = [];
|
||||
// Find terms but ignore those starting with ->get_lang(), which are
|
||||
// for plugins
|
||||
$res = preg_match_all('/(?<!-\>)get_lang\(\'(\\w*)\'\)/', $line, $myterms);
|
||||
if ($res > 0) {
|
||||
foreach ($myterms[1] as $term) {
|
||||
if (!isset($defined_terms[$term]) && !isset($defined_terms['lang'.$term])) {
|
||||
$undefined_terms[$term] = $shortfile;
|
||||
//echo "Undefined: $term<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
$res = 0;
|
||||
$res = preg_match_all('/\{[\'"](\\w*)[\'"]\|get_lang\}/', $line, $myterms);
|
||||
if ($res > 0) {
|
||||
foreach ($myterms[1] as $term) {
|
||||
if (!isset($defined_terms[$term]) && !isset($defined_terms['lang'.$term])) {
|
||||
$undefined_terms[$term] = $shortfile;
|
||||
//echo "Undefined: $term<br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
//$undefined_terms = array_flip($undefined_terms);
|
||||
if (count($undefined_terms) < 1) {
|
||||
exit("No missing terms<br />\n");
|
||||
} else {
|
||||
echo "The following terms were nowhere to be found: <br />\n<table>";
|
||||
}
|
||||
$i = 1;
|
||||
foreach ($undefined_terms as $term => $file) {
|
||||
$isPlugin = substr($file, 0, 7) == 'plugin/';
|
||||
echo "<tr><td>$i</td><td>$term</td><td>in $file";
|
||||
if ($isPlugin) {
|
||||
echo " <span style=\"color: #00ff00;\">(this one should be taken care of by the plugin's language files)</span>";
|
||||
}
|
||||
echo "</td></tr>\n";
|
||||
$i++;
|
||||
}
|
||||
echo "</table>\n";
|
||||
129
main/cron/lang/list_unused_langvars.php
Normal file
129
main/cron/lang/list_unused_langvars.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Cron script to list unused, but defined, language variables.
|
||||
*
|
||||
* @package chamilo.cron.lang
|
||||
*/
|
||||
/**
|
||||
* Includes and declarations.
|
||||
*/
|
||||
exit();
|
||||
require_once __DIR__.'/../../inc/global.inc.php';
|
||||
$path = api_get_path(SYS_LANG_PATH).'english';
|
||||
ini_set('memory_limit', '128M');
|
||||
/**
|
||||
* Main code.
|
||||
*/
|
||||
$terms = [];
|
||||
$list = SubLanguageManager::get_lang_folder_files_list($path);
|
||||
foreach ($list as $entry) {
|
||||
$file = $path.'/'.$entry;
|
||||
if (is_file($file)) {
|
||||
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
|
||||
}
|
||||
}
|
||||
// get only the array keys (the language variables defined in language files)
|
||||
$defined_terms = array_flip(array_keys($terms));
|
||||
$terms = null;
|
||||
echo count($defined_terms)." terms were found in language files<br />";
|
||||
|
||||
// now get all terms found in all PHP files of Chamilo (this takes some
|
||||
// time and memory)
|
||||
$usedTerms = [];
|
||||
$l = strlen(api_get_path(SYS_PATH));
|
||||
$files = getAllPhpFiles(api_get_path(SYS_PATH));
|
||||
$files[] = api_get_path(SYS_PATH).'main/install/data.sql';
|
||||
// Browse files
|
||||
foreach ($files as $file) {
|
||||
//echo 'Analyzing '.$file."<br />";
|
||||
$shortFile = substr($file, $l);
|
||||
//echo 'Analyzing '.$shortFile."<br />";
|
||||
$lines = file($file);
|
||||
$isDataSQL = false;
|
||||
if (substr($file, -21) === 'main/install/data.sql') {
|
||||
$isDataSQL = true;
|
||||
}
|
||||
// Browse lines inside file $file
|
||||
foreach ($lines as $line) {
|
||||
if ($isDataSQL) {
|
||||
// Check main/install/data.sql
|
||||
// Should recognize stuff like
|
||||
// INSERT INTO settings_current (variable, type, category, selected_value, title, comment) VALUES ('enable_profile_user_address_geolocalization', 'radio', 'User', 'false', 'EnableProfileUsersAddressGeolocalizationTitle', 'EnableProfileUsersAddressGeolocalizationComment');
|
||||
// INSERT INTO settings_options (variable, value, display_text) VALUES ('enable_profile_user_address_geolocalization', 'true', 'Yes');
|
||||
// ('show_teacher_data',NULL,'radio','Platform','true','ShowTeacherDataTitle','ShowTeacherDataComment',NULL,NULL, 1),
|
||||
$res = 0;
|
||||
$myTerms = [];
|
||||
$res = preg_match_all('/\'(\w*)\',/', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[1] as $term) {
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
$usedTerms[$term] = $shortFile;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$myTerms = [];
|
||||
$res = preg_match_all('/get_lang\(\'(\\w*)\'\)/', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[1] as $term) {
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
$usedTerms[$term] = $shortFile;
|
||||
}
|
||||
} else {
|
||||
$res = 0;
|
||||
$myTerms = [];
|
||||
// Should catch:
|
||||
// {{ 'CopyTextToClipboard' | get_lang }}
|
||||
// {{ "HelloX" | get_lang | format(show_user_info.user_info.complete_name) }}
|
||||
// {{ "StudentCourseProgressX" | get_lang | format(item.student_info.progress) }}
|
||||
$res = preg_match_all('/\{\s*[\'"](\w*)[\'"]\s*\|\s*get_lang\s*(\|\s*\w*(\s*\([\w_\.,\s]*\))?\s*)?\}/', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[1] as $term) {
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
$usedTerms[$term] = $shortFile;
|
||||
}
|
||||
}
|
||||
// {{ display.panel('PersonalDataResponsibleOrganizationTitle' | get_lang , personal_data.responsible ) }}
|
||||
// {{ display.panel('PersonalDataIntroductionTitle' | get_lang , 'PersonalDataIntroductionText' | get_lang) }}
|
||||
$myTerms = [];
|
||||
$res = preg_match_all('/\{\s*[\w\.]*\([\'"](\w*)[\'"]\s*\|\s*get_lang\s*(,\s*[\w_\.,\s\|\'"]*\s*)?\)\s*\}/', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[1] as $term) {
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
$usedTerms[$term] = $shortFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
// Compare defined terms VS used terms. Used terms should be smaller than
|
||||
// defined terms, and this should prove the concept that there are much
|
||||
// more variables than what we really use
|
||||
if (count($usedTerms) < 1) {
|
||||
exit("No used terms<br />\n");
|
||||
} else {
|
||||
echo "The following terms were defined but never used: <br />\n<table>";
|
||||
}
|
||||
$i = 1;
|
||||
foreach ($defined_terms as $term => $file) {
|
||||
// remove "lang" prefix just in case
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
if (!isset($usedTerms[$term])) {
|
||||
echo "<tr><td>$i</td><td>$term</td></tr>\n";
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
echo "</table>\n";
|
||||
92
main/cron/lang/switch_files_to_gettext.php
Normal file
92
main/cron/lang/switch_files_to_gettext.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Script to switch all PHP files in Chamilo to a more Gettext-like syntax.
|
||||
*
|
||||
* @package chamilo.cron.lang
|
||||
*/
|
||||
/**
|
||||
* Includes and declarations.
|
||||
*/
|
||||
exit();
|
||||
require_once __DIR__.'/../../inc/global.inc.php';
|
||||
$path = api_get_path(SYS_LANG_PATH).'english';
|
||||
ini_set('memory_limit', '128M');
|
||||
/**
|
||||
* Main code.
|
||||
*/
|
||||
$terms = [];
|
||||
$list = SubLanguageManager::get_lang_folder_files_list($path);
|
||||
foreach ($list as $entry) {
|
||||
$file = $path.'/'.$entry;
|
||||
if (is_file($file)) {
|
||||
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
|
||||
}
|
||||
}
|
||||
foreach ($terms as $index => $translation) {
|
||||
$terms[$index] = trim(rtrim($translation, ';'), '"');
|
||||
}
|
||||
// get only the array keys (the language variables defined in language files)
|
||||
$defined_terms = array_flip(array_keys($terms));
|
||||
echo count($defined_terms)." terms were found in language files".PHP_EOL;
|
||||
|
||||
// now get all terms found in all PHP files of Chamilo (this takes some
|
||||
// time and memory)
|
||||
$usedTerms = [];
|
||||
$l = strlen(api_get_path(SYS_PATH));
|
||||
$files = getAllPhpFiles(api_get_path(SYS_PATH));
|
||||
$rootLength = strlen(api_get_path(SYS_PATH));
|
||||
$countFiles = 0;
|
||||
$countReplaces = 0;
|
||||
// Browse files
|
||||
foreach ($files as $file) {
|
||||
if (substr($file, $rootLength, 6) === 'vendor' || substr($file, $rootLength, 3) === 'web') {
|
||||
continue;
|
||||
}
|
||||
//echo 'Analyzing '.$file.PHP_EOL;
|
||||
$shortFile = substr($file, $l);
|
||||
//echo 'Analyzing '.$shortFile.PHP_EOL;
|
||||
$lines = file($file);
|
||||
// Browse lines inside file $file
|
||||
foreach ($lines as $line) {
|
||||
$myTerms = [];
|
||||
$res = preg_match_all('/get_lang\(([\'"](\\w*)[\'"])\)/m', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[2] as $term) {
|
||||
echo "Found term $term - ".print_r($myTerms, 1).PHP_EOL;
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
if (!empty($terms[$term])) {
|
||||
$translation = $terms[$term];
|
||||
$quotedTerm = $myTerms[1][0];
|
||||
//echo "Would do sed -i \"s#$quotedTerm#'$translation'#g\" $file here\n";
|
||||
system("sed -i \"s#$term#'$translation'#g\" $file");
|
||||
$countReplaces++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$res = 0;
|
||||
$res = preg_match_all('/\{\s*([\'"](\\w*)[\'"])\s*\|get_lang\}/m', $line, $myTerms);
|
||||
if ($res > 0) {
|
||||
foreach ($myTerms[2] as $term) {
|
||||
echo "Found term $term".PHP_EOL;
|
||||
if (substr($term, 0, 4) == 'lang') {
|
||||
$term = substr($term, 4);
|
||||
}
|
||||
if (!empty($terms[$term])) {
|
||||
$translation = $terms[$term];
|
||||
$quotedTerm = $myTerms[1][0];
|
||||
//echo "Would do sed -i \"s#$quotedTerm#'$translation'#g\" $file here\n";
|
||||
system("sed -i \"s#$term#'$translation'#g\" $file");
|
||||
$countReplaces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$countFiles++;
|
||||
flush();
|
||||
}
|
||||
|
||||
echo "Done analyzing $countFiles files, with $countReplaces replacements!\n";
|
||||
476
main/cron/learning_path_reminder.php
Normal file
476
main/cron/learning_path_reminder.php
Normal file
@@ -0,0 +1,476 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* New lp reminder.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*
|
||||
* @author Carlos Alvarado <carlos.alvarado@beeznest.com>
|
||||
*/
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
// 24-hour format of an hour without leading zeros (in UTC timezone) to execute and search learning paths
|
||||
$timeSlots = [
|
||||
7,
|
||||
16,
|
||||
20,
|
||||
];
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
if ('cli' != php_sapi_name()) {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
$field = new ExtraField('lp');
|
||||
$activeMessageNewlp = $field->get_handler_field_info_by_field_variable('notify_student_and_hrm_when_available');
|
||||
|
||||
if ($activeMessageNewlp == false) {
|
||||
// field doesnt exist
|
||||
exit();
|
||||
}
|
||||
if (!isset($activeMessageNewlp['default_value'])) {
|
||||
// field dont have default value
|
||||
exit();
|
||||
}
|
||||
|
||||
$currentHour = (int) api_get_utc_datetime(null, false, true)->format('G');
|
||||
|
||||
if (!in_array($currentHour, $timeSlots)) {
|
||||
exit("Execution nor allowed in this hour ($currentHour).");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message to the intended user, manage the corresponding template and send through
|
||||
* MessageManager::send_message_simple, using this for the option of human resources managers.
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
function sendMessage(array $toUser, int $fromUser, string $courseName, string $lpName, string $link)
|
||||
{
|
||||
$toUserId = $toUser['user_id'];
|
||||
$subjectTemplate = new Template(
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
$subjectLayout = $subjectTemplate->get_template(
|
||||
'mail/learning_path_reminder_subject.tpl'
|
||||
);
|
||||
|
||||
$bodyTemplate = new Template(
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
$bodyTemplate->assign('courseName', $courseName);
|
||||
$bodyTemplate->assign('lpName', $lpName);
|
||||
$bodyTemplate->assign('link', $link);
|
||||
|
||||
$bodyLayout = $bodyTemplate->get_template(
|
||||
'mail/learning_path_reminder_body.tpl'
|
||||
);
|
||||
$tittle = $subjectTemplate->fetch($subjectLayout);
|
||||
$content = $bodyTemplate->fetch($bodyLayout);
|
||||
|
||||
return MessageManager::send_message_simple(
|
||||
$toUserId,
|
||||
$tittle,
|
||||
$content,
|
||||
$fromUser,
|
||||
true
|
||||
);
|
||||
// $drhList = UserManager::getDrhListFromUser($receiverUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the data of the learning path and course searched by the id of the LP.
|
||||
*/
|
||||
function getLpDataByArrayId(array $lpid = []): array
|
||||
{
|
||||
if (count($lpid) == 0) {
|
||||
return [];
|
||||
}
|
||||
$tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$lpTable = Database::get_course_table(TABLE_LP_MAIN);
|
||||
$sql = "SELECT
|
||||
tblCourse.title AS course_name,
|
||||
tblCourse.code AS code,
|
||||
tblLp.id AS lp_id,
|
||||
tblLp.c_id AS c_id,
|
||||
tblLp.name AS name
|
||||
FROM
|
||||
$lpTable AS tblLp
|
||||
INNER JOIN $tblCourse AS tblCourse ON tblLp.c_id = tblCourse.id
|
||||
WHERE
|
||||
tblLp.iid IN ( ".implode(',', $lpid)." )";
|
||||
$result = Database::query($sql);
|
||||
$return = [];
|
||||
while ($element = Database::fetch_array($result)) {
|
||||
$return[$element['lp_id']] = $element;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the LPs that have the notification option active through the extra
|
||||
* field 'notify_student_and_hrm_when_available'.
|
||||
*/
|
||||
function getLpIdWithNotify(): array
|
||||
{
|
||||
$extraFieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
|
||||
$extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
|
||||
$sql = "SELECT
|
||||
tblExtraFieldValues.item_id as lp_id
|
||||
FROM
|
||||
$extraFieldValuesTable AS tblExtraFieldValues
|
||||
INNER JOIN $extraFieldTable AS tblExtraField ON (
|
||||
tblExtraFieldValues.field_id = tblExtraField.id AND
|
||||
tblExtraField.variable = 'notify_student_and_hrm_when_available'
|
||||
)
|
||||
where
|
||||
tblExtraFieldValues.value = 1";
|
||||
$result = Database::query($sql);
|
||||
$return = [];
|
||||
while ($element = Database::fetch_array($result)) {
|
||||
$return[] = $element['lp_id'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
function getTutorIdFromCourseRelUser($cId = 0, $lpId = 0): int
|
||||
{
|
||||
$lpTable = Database::get_course_table(TABLE_LP_MAIN);
|
||||
$tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$sql = "SELECT DISTINCT
|
||||
tblCourseRelUser.user_id AS user_id
|
||||
FROM
|
||||
$lpTable AS tblLp
|
||||
INNER JOIN $tblCourseRelUser AS tblCourseRelUser ON ( tblCourseRelUser.c_id = tblLp.c_id)
|
||||
WHERE
|
||||
tblCourseRelUser.user_id IS NOT NULL AND
|
||||
tblCourseRelUser.status = 1 AND
|
||||
tblLp.id = $lpId AND
|
||||
tblLp.c_id = $cId";
|
||||
$result = Database::query($sql);
|
||||
$data = Database::fetch_assoc($result);
|
||||
|
||||
return (isset($data['user_id'])) ? (int) $data['user_id'] : 0;
|
||||
}
|
||||
|
||||
function sendToArray(&$data, &$type, &$message, $lpId = 0)
|
||||
{
|
||||
foreach ($data as $user) {
|
||||
$userName = $user['userInfo']['complete_name'];
|
||||
$userId = $user['userInfo']['user_id'];
|
||||
$fromUser = $user['fromUser'];
|
||||
$courseName = $user['courseName'];
|
||||
$lpName = $user['lpName'];
|
||||
$send = sendMessage(
|
||||
$user['userInfo'],
|
||||
$fromUser,
|
||||
$courseName,
|
||||
$lpName,
|
||||
$user['link']
|
||||
);
|
||||
$message .= "\n$type - Lp Id '$lpId' User Id '$userId' Sent to '$userName' Message id '$send' Lp name '$lpName'";
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentTimeSlot(int $currentHour, array $timeSlots = []): ?array
|
||||
{
|
||||
$index = array_search($currentHour, $timeSlots);
|
||||
$yesterday = false;
|
||||
|
||||
if (false === $index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (0 === $index) {
|
||||
$index = count($timeSlots) - 1;
|
||||
$yesterday = true;
|
||||
} else {
|
||||
$index--;
|
||||
}
|
||||
|
||||
$startHour = $timeSlots[$index];
|
||||
|
||||
if ($yesterday) {
|
||||
$startDate = api_get_utc_datetime(null, false, true)->modify("yesterday $startHour:00");
|
||||
} else {
|
||||
$startDate = api_get_utc_datetime(null, false, true)->modify("today $startHour:00");
|
||||
}
|
||||
$endDate = api_get_utc_datetime(null, false, true)->modify("today $currentHour:00");
|
||||
|
||||
return [$startDate, $endDate];
|
||||
}
|
||||
|
||||
function learningPaths(int $currentHour, array $timeSlots = [])
|
||||
{
|
||||
$lpItems = getLpIdWithNotify();
|
||||
if (count($lpItems) == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
[$startDate, $endDate] = getCurrentTimeSlot($currentHour, $timeSlots);
|
||||
|
||||
$tutors = [];
|
||||
$lpItemsString = implode(',', $lpItems);
|
||||
$lpsData = getLpDataByArrayId($lpItems);
|
||||
$itemProcessed = [];
|
||||
$lpTable = Database::get_course_table(TABLE_LP_MAIN);
|
||||
$tblCourseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
|
||||
$tblItempProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
|
||||
/* Gets subscribed users individually in lp's by LearnpathSubscription */
|
||||
$sql = "SELECT DISTINCT
|
||||
tblItemProperty.session_id as session_id,
|
||||
tblItemProperty.to_user_id as user_id,
|
||||
tblItemProperty.insert_user_id as from_user_id,
|
||||
tblLp.id AS lp_id,
|
||||
tblItemProperty.lastedit_type
|
||||
FROM
|
||||
$tblItempProperty as tblItemProperty
|
||||
INNER JOIN $lpTable as tblLp ON
|
||||
(
|
||||
tblLp.iid = tblItemProperty.ref AND
|
||||
tblItemProperty.lastedit_type = 'LearnpathSubscription'
|
||||
)
|
||||
WHERE
|
||||
publicated_on < '".$endDate->format('Y-m-d H:i:s')."' AND
|
||||
publicated_on >= '".$startDate->format('Y-m-d H:i:s')."' AND
|
||||
tblItemProperty.to_user_id IS NOT NULL AND
|
||||
tblLp.id in ($lpItemsString)";
|
||||
$result = Database::query($sql);
|
||||
$groupUsers = [];
|
||||
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$lpId = (int) $row['lp_id'];
|
||||
$lpData = [];
|
||||
if (isset($lpsData[$lpId])) {
|
||||
$lpData = $lpsData[$lpId];
|
||||
}
|
||||
$courseName = $lpData['course_name'] ?? null;
|
||||
$courseCode = $lpData['code'] ?? null;
|
||||
$lpName = $lpData['name'] ?? null;
|
||||
|
||||
$sessionId = (int) $row['session_id'];
|
||||
$toUser = (int) $row['user_id'];
|
||||
$fromUser = (int) $row['from_user_id'];
|
||||
$userInfo = api_get_user_info($toUser);
|
||||
$href = api_get_path(WEB_CODE_PATH).
|
||||
'lp/lp_controller.php?cidReq='.htmlspecialchars($courseCode).
|
||||
"&id_session=$sessionId &action=view&lp_id=$lpId&gidReq=0&gradebook=0&origin=";
|
||||
$link = "<a href='$href'>$href</a>";
|
||||
$groupUsers[$lpId][$sessionId][$toUser] = [
|
||||
'userInfo' => $userInfo,
|
||||
'fromUser' => $fromUser,
|
||||
'courseName' => $courseName,
|
||||
'lpName' => $lpName,
|
||||
'link' => $link,
|
||||
];
|
||||
$itemProcessed[$lpId][$sessionId]['LearnpathSubscription'][$toUser] = $groupUsers[$lpId][$sessionId][$toUser];
|
||||
}
|
||||
/* Gets subscribed users by classes in lp's by LearnpathSubscription */
|
||||
$sql = "SELECT DISTINCT
|
||||
tblItemProperty.session_id as session_id,
|
||||
tblItemProperty.to_group_id as group_id,
|
||||
tblUsergroupRelUser.user_id as user_id,
|
||||
tblItemProperty.insert_user_id as from_user_id,
|
||||
tblLp.id AS lp_id,
|
||||
tblItemProperty.lastedit_type
|
||||
FROM
|
||||
$tblItempProperty as tblItemProperty
|
||||
INNER JOIN $lpTable as tblLp ON
|
||||
(
|
||||
tblLp.iid = tblItemProperty.ref AND
|
||||
tblItemProperty.lastedit_type = 'LearnpathSubscription'
|
||||
)
|
||||
INNER JOIN usergroup_rel_user as tblUsergroupRelUser on (
|
||||
tblItemProperty.to_group_id = tblUsergroupRelUser.usergroup_id
|
||||
)
|
||||
WHERE
|
||||
publicated_on < '".$endDate->format('Y-m-d H:i:s')."' AND
|
||||
publicated_on >= '".$startDate->format('Y-m-d H:i:s')."' AND
|
||||
tblItemProperty.to_group_id IS NOT NULL AND
|
||||
tblLp.id in ($lpItemsString)";
|
||||
$result = Database::query($sql);
|
||||
$groupUsers = [];
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$lpId = (int) $row['lp_id'];
|
||||
$lpData = [];
|
||||
if (isset($lpsData[$lpId])) {
|
||||
$lpData = $lpsData[$lpId];
|
||||
}
|
||||
$courseName = $lpData['course_name'] ?? null;
|
||||
$courseCode = $lpData['code'] ?? null;
|
||||
$lpName = $lpData['name'] ?? null;
|
||||
|
||||
$sessionId = (int) $row['session_id'];
|
||||
$toUser = (int) $row['user_id'];
|
||||
$fromUser = (int) $row['from_user_id'];
|
||||
$userInfo = api_get_user_info($toUser);
|
||||
$href = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'
|
||||
.api_get_cidreq_params($courseCode, $sessionId).'&'
|
||||
.http_build_query(
|
||||
[
|
||||
'gradebook' => '0',
|
||||
'origin' => '',
|
||||
'lp_id' => $lpId,
|
||||
'action' => 'view',
|
||||
]
|
||||
);
|
||||
$link = "<a href='$href'>$href</a>";
|
||||
$groupUsers[$lpId][$sessionId][$toUser] = [
|
||||
'userInfo' => $userInfo,
|
||||
'fromUser' => $fromUser,
|
||||
'courseName' => $courseName,
|
||||
'lpName' => $lpName,
|
||||
'link' => $link,
|
||||
];
|
||||
$itemProcessed[$lpId][$sessionId]['LearnpathSubscription'][$toUser] = $groupUsers[$lpId][$sessionId][$toUser];
|
||||
}
|
||||
/* Get users who are enrolled in the course */
|
||||
|
||||
$sql = "SELECT DISTINCT
|
||||
tblCourseRelUser.user_id AS user_id,
|
||||
tblLp.id AS lp_id,
|
||||
tblLp.c_id AS c_id
|
||||
FROM
|
||||
$lpTable AS tblLp
|
||||
INNER JOIN $tblCourseRelUser AS tblCourseRelUser ON ( tblCourseRelUser.c_id = tblLp.c_id)
|
||||
WHERE
|
||||
publicated_on < '".$endDate->format('Y-m-d H:i:s')."' AND
|
||||
publicated_on >= '".$startDate->format('Y-m-d H:i:s')."' AND
|
||||
tblCourseRelUser.user_id IS NOT NULL AND
|
||||
tblCourseRelUser.status = 5 AND
|
||||
tblLp.id in ($lpItemsString)";
|
||||
|
||||
$result = Database::query($sql);
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$lpId = (int) $row['lp_id'];
|
||||
$sessionId = 0;
|
||||
if (isset($lpsData[$lpId])) {
|
||||
$lpData = $lpsData[$lpId];
|
||||
}
|
||||
if (!isset($tutors[$row['c_id']][$row['lp_id']])) {
|
||||
$tutors[$row['c_id']][$row['lp_id']] = getTutorIdFromCourseRelUser($row['c_id'], $row['lp_id']);
|
||||
}
|
||||
$courseName = $lpData['course_name'] ?? null;
|
||||
$courseCode = $lpData['code'] ?? null;
|
||||
$lpName = $lpData['name'] ?? null;
|
||||
$toUser = (int) $row['user_id'];
|
||||
$fromUser = $tutors[$row['c_id']][$row['lp_id']];
|
||||
$userInfo = api_get_user_info($toUser);
|
||||
$href = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'
|
||||
.api_get_cidreq_params($courseCode, $sessionId).'&'
|
||||
.http_build_query(
|
||||
[
|
||||
'gradebook' => '0',
|
||||
'origin' => '',
|
||||
'lp_id' => $lpId,
|
||||
'action' => 'view',
|
||||
]
|
||||
);
|
||||
$link = "<a href='$href'>$href</a>";
|
||||
if (!isset($itemProcessed[$lpId][$sessionId]['LearnpathSubscription'])) {
|
||||
$groupUsers[$lpId][$sessionId][$toUser] = [
|
||||
'userInfo' => $userInfo,
|
||||
'fromUser' => $fromUser,
|
||||
'courseName' => $courseName,
|
||||
'lpName' => $lpName,
|
||||
'link' => $link,
|
||||
];
|
||||
$itemProcessed[$lpId][$sessionId]['NoLpSubscription'][$toUser] = $groupUsers[$lpId][$sessionId][$toUser];
|
||||
}
|
||||
}
|
||||
/** Get the users who are registered in the sessions */
|
||||
$sql = "SELECT DISTINCT
|
||||
tblSessionRelCourseRelUser.user_id AS user_id,
|
||||
tblLp.id AS lp_id,
|
||||
tblSessionRelCourseRelUser.session_id AS session_id,
|
||||
tblLp.c_id AS c_id,
|
||||
tblSessionRelCourseRelUser.status AS status
|
||||
FROM
|
||||
$lpTable AS tblLp
|
||||
INNER JOIN $tblSessionCourseUser AS tblSessionRelCourseRelUser ON (
|
||||
tblSessionRelCourseRelUser.c_id = tblLp.c_id)
|
||||
WHERE
|
||||
publicated_on < '".$endDate->format('Y-m-d H:i:s')."' AND
|
||||
publicated_on >= '".$startDate->format('Y-m-d H:i:s')."' AND
|
||||
tblSessionRelCourseRelUser.user_id IS NOT NULL AND
|
||||
tblLp.id in ($lpItemsString) AND
|
||||
tblSessionRelCourseRelUser.status = 0
|
||||
ORDER BY tblSessionRelCourseRelUser.status";
|
||||
$result = Database::query($sql);
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$lpId = (int) $row['lp_id'];
|
||||
$sessionId = 0;
|
||||
if (isset($lpsData[$lpId])) {
|
||||
$lpData = $lpsData[$lpId];
|
||||
}
|
||||
$courseName = $lpData['course_name'] ?? null;
|
||||
$courseCode = $lpData['code'] ?? null;
|
||||
$lpName = $lpData['name'] ?? null;
|
||||
$toUser = (int) $row['user_id'];
|
||||
if (!isset($tutors[$row['c_id']][$row['lp_id']])) {
|
||||
$tutors[$row['c_id']][$row['lp_id']] = getTutorIdFromCourseRelUser($row['c_id'], $row['lp_id']);
|
||||
}
|
||||
$fromUser = $tutors[$row['c_id']][$row['lp_id']];
|
||||
$userInfo = api_get_user_info($toUser);
|
||||
$href = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'
|
||||
.api_get_cidreq_params($courseCode, $sessionId).'&'
|
||||
.http_build_query(
|
||||
[
|
||||
'gradebook' => '0',
|
||||
'origin' => '',
|
||||
'lp_id' => $lpId,
|
||||
'action' => 'view',
|
||||
]
|
||||
);
|
||||
$link = "<a href='$href'>$href</a>";
|
||||
if (!isset($itemProcessed[$lpId][$sessionId]['LearnpathSubscription'])) {
|
||||
$groupUsers[$lpId][$sessionId][$toUser] = [
|
||||
'userInfo' => $userInfo,
|
||||
'fromUser' => $fromUser,
|
||||
'courseName' => $courseName,
|
||||
'lpName' => $lpName,
|
||||
'link' => $link,
|
||||
];
|
||||
$itemProcessed[$lpId][$sessionId]['NoLpSubscription'][$toUser] = $groupUsers[$lpId][$sessionId][$toUser];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the emails to the corresponding students and their DRHs, Bearing in mind that if they exist through
|
||||
* LearnpathSubscription, it will not send anything in the other elements.
|
||||
*/
|
||||
$message = '';
|
||||
foreach ($itemProcessed as $lpId => $sessions) {
|
||||
foreach ($sessions as $sessionId => $types) {
|
||||
foreach ($types as $type => $users) {
|
||||
if ('LearnpathSubscription' == $type) {
|
||||
sendToArray($users, $type, $message, $lpId);
|
||||
} elseif (!isset($itemProcessed[$lpId][$sessionId]['LearnpathSubscription'])) {
|
||||
sendToArray($users, $type, $message, $lpId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "$message\n\n";
|
||||
}
|
||||
|
||||
learningPaths($currentHour, $timeSlots);
|
||||
|
||||
exit();
|
||||
360
main/cron/lp_progress_reminder.php
Normal file
360
main/cron/lp_progress_reminder.php
Normal file
@@ -0,0 +1,360 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* New lp reminder.
|
||||
*
|
||||
* To add this extra field for lp option number_of_days_for_completion
|
||||
* INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES
|
||||
* (6, 1, 'number_of_days_for_completion', 'NumberOfDaysForCompletion', '', 0, 1, 0, 1, 0, NOW());
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*/
|
||||
define('NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION', 3);
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
if ('cli' != php_sapi_name()) {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
notifyUsersForCheckingLpCompletion();
|
||||
|
||||
/**
|
||||
* Send the message to the intended user, manage the corresponding template and send through
|
||||
* MessageManager::send_message_simple, using this for the option of human resources managers.
|
||||
*
|
||||
* @param $toUserId
|
||||
* @param $courseId
|
||||
* @param $lpProgress
|
||||
* @param $registrationDate
|
||||
* @param $nbRemind
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
function sendMessage(
|
||||
$toUserId,
|
||||
$courseId,
|
||||
$lpProgress,
|
||||
$registrationDate,
|
||||
$nbRemind
|
||||
) {
|
||||
$subjectTemplate = new Template(
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
$courseInfo = api_get_course_info_by_id($courseId);
|
||||
$courseName = $courseInfo['title'];
|
||||
$userInfo = api_get_user_info($toUserId);
|
||||
$language = $userInfo['language'];
|
||||
|
||||
$subjectTemplate->assign('RemindXLpCourseX', sprintf(getUserLang('RemindXLpCourseX', $language), $nbRemind, $courseName));
|
||||
|
||||
$subjectLayout = $subjectTemplate->get_template(
|
||||
'mail/lp_progress_reminder_subject.tpl'
|
||||
);
|
||||
|
||||
$bodyTemplate = new Template(
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
$teachersListString = '';
|
||||
$teachers = CourseManager::getTeachersFromCourse($courseId);
|
||||
if (!empty($teachers)) {
|
||||
$teachersList = [];
|
||||
foreach ($teachers as $value) {
|
||||
$teacherName = api_get_person_name($value['firstname'], $value['lastname']);
|
||||
$teachersList[] = strtoupper($teacherName).': '.$value['email'];
|
||||
}
|
||||
$teachersListString = implode('<br/>', $teachersList);
|
||||
}
|
||||
|
||||
$userFullName = api_get_person_name($userInfo['firstname'], $userInfo['lastname']);
|
||||
$urlChamilo = api_get_path(WEB_CODE_PATH);
|
||||
$urlLostPw = api_get_path(WEB_CODE_PATH).'auth/lostPassword.php';
|
||||
$logoPortal = return_logo();
|
||||
$bodyTemplate->assign('HelloX', sprintf(getUserLang('HelloX', $language), $userFullName));
|
||||
$bodyTemplate->assign('YouAreRegCourseXFromDateX', sprintf(getUserLang('YouAreRegCourseXFromDateX', $language), $courseName, $registrationDate));
|
||||
$bodyTemplate->assign('ThisMessageIsAboutX', sprintf(getUserLang('ThisMessageIsAboutX', $language), $lpProgress));
|
||||
$bodyTemplate->assign('StepsToRemindX', sprintf(getUserLang('StepsToRemindX', $language), $urlChamilo, $userInfo['username'], $urlLostPw));
|
||||
$bodyTemplate->assign('LpRemindFooterX', sprintf(getUserLang('LpRemindFooterX', $language), $logoPortal, $teachersListString));
|
||||
|
||||
$bodyLayout = $bodyTemplate->get_template(
|
||||
'mail/lp_progress_reminder_body.tpl'
|
||||
);
|
||||
|
||||
$title = $subjectTemplate->fetch($subjectLayout);
|
||||
$content = $bodyTemplate->fetch($bodyLayout);
|
||||
|
||||
return MessageManager::send_message_simple(
|
||||
$toUserId,
|
||||
$title,
|
||||
$content,
|
||||
1,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translated (localized) string by user language.
|
||||
*
|
||||
* @param $variable
|
||||
* @param $language
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function getUserLang($variable, $language)
|
||||
{
|
||||
$languageFilesToLoad = api_get_language_files_to_load($language);
|
||||
foreach ($languageFilesToLoad as $languageFile) {
|
||||
include $languageFile;
|
||||
}
|
||||
|
||||
$translate = $variable;
|
||||
if (isset($$variable)) {
|
||||
$langVariable = $$variable;
|
||||
$translate = $langVariable;
|
||||
}
|
||||
|
||||
return $translate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of reminder checking the frequency from NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION.
|
||||
*
|
||||
* @param $registrationDate
|
||||
* @param $nbDaysForLpCompletion
|
||||
*
|
||||
* @return false|float|int
|
||||
*/
|
||||
function getNbReminder($registrationDate, $nbDaysForLpCompletion): int
|
||||
{
|
||||
$date1 = new DateTime($registrationDate);
|
||||
$date1->modify("+$nbDaysForLpCompletion day");
|
||||
|
||||
$date2 = new DateTime('now', new DateTimeZone('UTC'));
|
||||
|
||||
$interval = $date1->diff($date2);
|
||||
$diffDays = (int) $interval->format('%a');
|
||||
|
||||
$nbRemind = ceil($diffDays / NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION) + 1;
|
||||
|
||||
return $nbRemind;
|
||||
}
|
||||
|
||||
/**
|
||||
* It checks if user has to be notified checking the current registration date and nbDaysForLpCompletion value.
|
||||
*
|
||||
* @param $registrationDate
|
||||
* @param $nbDaysForLpCompletion
|
||||
*/
|
||||
function isTimeToRemindUser($registrationDate, $nbDaysForLpCompletion): bool
|
||||
{
|
||||
$date1 = new DateTime($registrationDate);
|
||||
$date1->modify("+$nbDaysForLpCompletion day");
|
||||
$startDate = $date1->format('Y-m-d');
|
||||
|
||||
$date2 = new DateTime('now', new DateTimeZone('UTC'));
|
||||
$now = $date2->format('Y-m-d');
|
||||
|
||||
$reminder = false;
|
||||
if ($startDate < $now) {
|
||||
$interval = $date1->diff($date2);
|
||||
$diffDays = (int) $interval->format('%a');
|
||||
$reminder = (0 === $diffDays % NUMBER_OF_DAYS_TO_RESEND_NOTIFICATION);
|
||||
} else {
|
||||
$reminder = $startDate === $now;
|
||||
}
|
||||
|
||||
return $reminder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify users for checking Learning path completion.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function notifyUsersForCheckingLpCompletion()
|
||||
{
|
||||
$lpItems = getLpIdWithDaysForCompletion();
|
||||
if (count($lpItems) == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tblCourse = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
|
||||
$sql = "SELECT id FROM $tblCourse";
|
||||
$rs = Database::query($sql);
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
while ($row = Database::fetch_array($rs)) {
|
||||
$courseId = $row['id'];
|
||||
|
||||
// It checks users in main course
|
||||
$courseUsers = getCourseUsers($courseId);
|
||||
if (!empty($courseUsers)) {
|
||||
foreach ($courseUsers as $user) {
|
||||
$toUserId = $user['user_id'];
|
||||
$lpProgress = (int) $user['progress'];
|
||||
$nbDaysForLpCompletion = $lpItems[$user['lp_id']];
|
||||
$registrationDate = getUserCourseRegistrationAt($courseId, $toUserId);
|
||||
$notify = isTimeToRemindUser($registrationDate, $nbDaysForLpCompletion);
|
||||
if ($notify) {
|
||||
$nbRemind = getNbReminder($registrationDate, $nbDaysForLpCompletion);
|
||||
sendMessage($toUserId, $courseId, $lpProgress, $registrationDate, $nbRemind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It checks users in session course
|
||||
$sessionCourseUsers = getCourseUsers($courseId, true);
|
||||
if (!empty($sessionCourseUsers)) {
|
||||
foreach ($sessionCourseUsers as $user) {
|
||||
$toUserId = $user['user_id'];
|
||||
$lpProgress = (int) $user['progress'];
|
||||
$nbDaysForLpCompletion = $lpItems[$user['lp_id']];
|
||||
$registrationDate = getUserCourseRegistrationAt($courseId, $toUserId, $user['session_id']);
|
||||
$notify = isTimeToRemindUser($registrationDate, $nbDaysForLpCompletion);
|
||||
if ($notify) {
|
||||
$nbRemind = getNbReminder($registrationDate, $nbDaysForLpCompletion);
|
||||
sendMessage($toUserId, $courseId, $lpProgress, $registrationDate, $nbRemind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users in a course also checking the session.
|
||||
*
|
||||
* @param int $courseId
|
||||
* @param false $checkSession
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getCourseUsers($courseId, $checkSession = false)
|
||||
{
|
||||
$lpItems = getLpIdWithDaysForCompletion();
|
||||
if (count($lpItems) == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tblCourseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$tblSessionCourseUser = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
|
||||
$tblLp = Database::get_course_table(TABLE_LP_MAIN);
|
||||
$tblLpView = Database::get_course_table(TABLE_LP_VIEW);
|
||||
|
||||
$lpItemsString = implode(',', array_keys($lpItems));
|
||||
|
||||
if ($checkSession) {
|
||||
$sql = "SELECT
|
||||
scu.user_id,
|
||||
scu.c_id,
|
||||
lp.id as lp_id,
|
||||
lpv.progress,
|
||||
scu.session_id
|
||||
FROM
|
||||
$tblSessionCourseUser scu
|
||||
INNER JOIN $tblLp lp ON lp.c_id = scu.c_id
|
||||
LEFT JOIN $tblLpView lpv ON lpv.lp_id = lp.id AND lpv.user_id = scu.user_id
|
||||
WHERE
|
||||
scu.c_id = $courseId AND
|
||||
(lpv.progress < 100 OR lpv.progress is null) AND
|
||||
lp.id IN($lpItemsString)";
|
||||
} else {
|
||||
$sql = "SELECT
|
||||
cu.user_id,
|
||||
cu.c_id,
|
||||
lp.id as lp_id,
|
||||
lpv.progress
|
||||
FROM
|
||||
$tblCourseUser cu
|
||||
INNER JOIN $tblLp lp ON (lp.c_id = cu.c_id)
|
||||
LEFT JOIN $tblLpView lpv ON (lpv.lp_id = lp.id AND lpv.user_id = cu.user_id)
|
||||
WHERE
|
||||
cu.c_id = $courseId AND
|
||||
(lpv.progress < 100 OR lpv.progress is null) AND
|
||||
lp.id IN($lpItemsString)";
|
||||
}
|
||||
|
||||
$rs = Database::query($sql);
|
||||
$users = [];
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
while ($row = Database::fetch_assoc($rs)) {
|
||||
$users[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns the register date of a user in a course or session from track_e_default.
|
||||
*
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
* @param int $sessionId
|
||||
*
|
||||
* @return false|mixed|string|null
|
||||
*/
|
||||
function getUserCourseRegistrationAt($courseId, $userId, $sessionId = 0)
|
||||
{
|
||||
$tblTrackDefault = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT);
|
||||
$sql = "SELECT
|
||||
default_date
|
||||
FROM $tblTrackDefault
|
||||
WHERE c_id = $courseId AND
|
||||
default_value_type = 'user_object' AND
|
||||
default_event_type = '".LOG_SUBSCRIBE_USER_TO_COURSE."' AND
|
||||
default_value LIKE CONCAT('%s:2:\\\\\\\\\"id\\\\\\\\\";i:', $userId, ';%') AND
|
||||
session_id = $sessionId";
|
||||
$rs = Database::query($sql);
|
||||
$registerDate = '';
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
$registerDate = Database::result($rs, 0, 0);
|
||||
}
|
||||
|
||||
return $registerDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the LPs that have days for completion the progress through the extra
|
||||
* field 'number_of_days_for_completion'.
|
||||
*/
|
||||
function getLpIdWithDaysForCompletion(): array
|
||||
{
|
||||
$extraFieldValuesTable = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
|
||||
$extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD);
|
||||
$sql = "SELECT
|
||||
tblExtraFieldValues.item_id as lp_id,
|
||||
tblExtraFieldValues.value as ndays
|
||||
FROM
|
||||
$extraFieldValuesTable AS tblExtraFieldValues
|
||||
INNER JOIN $extraFieldTable AS tblExtraField ON (
|
||||
tblExtraFieldValues.field_id = tblExtraField.id AND
|
||||
tblExtraField.variable = 'number_of_days_for_completion'
|
||||
)
|
||||
where
|
||||
tblExtraFieldValues.value > 0";
|
||||
$result = Database::query($sql);
|
||||
$return = [];
|
||||
while ($element = Database::fetch_array($result)) {
|
||||
$return[$element['lp_id']] = $element['ndays'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
exit();
|
||||
18
main/cron/notification.php
Normal file
18
main/cron/notification.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* @author Julio Montoya <gugli100@gmail.com>
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
exit('Run this script through the command line or comment this line in the code');
|
||||
}
|
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Notification sending.
|
||||
*/
|
||||
$notify = new Notification();
|
||||
$notify->send();
|
||||
170
main/cron/remind_course_expiration.php
Normal file
170
main/cron/remind_course_expiration.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Course expiration reminder.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*
|
||||
* @author Imanol Losada <imanol.losada@beeznest.com>
|
||||
*/
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
if (php_sapi_name() != 'cli') {
|
||||
exit; //do not run from browser
|
||||
}
|
||||
|
||||
$isActive = api_get_setting('cron_remind_course_expiration_activate') === 'true';
|
||||
|
||||
if (!$isActive) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$frequency = api_get_setting('cron_remind_course_expiration_frequency');
|
||||
|
||||
// Days before expiration date to send reminders
|
||||
$today = gmdate("Y-m-d");
|
||||
$expirationDate = gmdate("Y-m-d", strtotime("$today + $frequency day"));
|
||||
|
||||
$gradebookTable = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
|
||||
$certificateTable = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
|
||||
$sessionTable = Database::get_main_table(TABLE_MAIN_SESSION);
|
||||
$sessionUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER);
|
||||
|
||||
$query = "
|
||||
SELECT DISTINCT category.session_id, certificate.user_id
|
||||
FROM $gradebookTable AS category
|
||||
LEFT JOIN $certificateTable AS certificate
|
||||
ON category.id = certificate.cat_id
|
||||
INNER JOIN $sessionTable AS session
|
||||
ON category.session_id = session.id
|
||||
WHERE
|
||||
session.access_end_date BETWEEN '$today' AND
|
||||
'$expirationDate' AND
|
||||
category.session_id IS NOT NULL";
|
||||
$sessionId = 0;
|
||||
$userIds = [];
|
||||
$sessions = [];
|
||||
$result = Database::query($query);
|
||||
$urlSessionTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
|
||||
$urlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
|
||||
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
if ($sessionId != $row['session_id']) {
|
||||
$sessionId = $row['session_id'];
|
||||
$userIds = [];
|
||||
}
|
||||
if (!is_null($row['user_id'])) {
|
||||
array_push($userIds, $row['user_id']);
|
||||
}
|
||||
$sessions[$sessionId] = $userIds;
|
||||
}
|
||||
|
||||
$usersToBeReminded = [];
|
||||
|
||||
foreach ($sessions as $sessionId => $userIds) {
|
||||
$userId = 0;
|
||||
$userIds = $userIds ? " AND sessionUser.user_id NOT IN (".implode(", ", $userIds).")" : null;
|
||||
$query = "
|
||||
SELECT sessionUser.session_id, sessionUser.user_id, session.name, session.access_end_date
|
||||
FROM $sessionUserTable AS sessionUser
|
||||
INNER JOIN $sessionTable AS session
|
||||
ON sessionUser.session_id = session.id
|
||||
WHERE
|
||||
session_id = $sessionId$userIds";
|
||||
$result = Database::query($query);
|
||||
while ($row = Database::fetch_array($result)) {
|
||||
$usersToBeReminded[$row['user_id']][$row['session_id']] = [
|
||||
'name' => $row['name'],
|
||||
'access_end_date' => $row['access_end_date'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($usersToBeReminded) {
|
||||
$today = date_create($today);
|
||||
$administrator = [
|
||||
'completeName' => api_get_person_name(
|
||||
api_get_setting("administratorName"),
|
||||
api_get_setting("administratorSurname"),
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
),
|
||||
'email' => api_get_setting("emailAdministrator"),
|
||||
];
|
||||
echo "\n======================================================================\n\n";
|
||||
foreach ($usersToBeReminded as $userId => $sessions) {
|
||||
$user = api_get_user_info($userId);
|
||||
$userCompleteName = api_get_person_name(
|
||||
$user['firstname'],
|
||||
$user['lastname'],
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
foreach ($sessions as $sessionId => $session) {
|
||||
$daysRemaining = date_diff($today, date_create($session['access_end_date']));
|
||||
$join = " INNER JOIN $urlSessionTable ON id = access_url_id";
|
||||
$result = Database::select(
|
||||
'url',
|
||||
"$urlTable $join",
|
||||
[
|
||||
'where' => [
|
||||
'session_id = ?' => [
|
||||
$sessionId,
|
||||
],
|
||||
],
|
||||
'limit' => '1',
|
||||
]
|
||||
);
|
||||
|
||||
$subjectTemplate = new Template(null, false, false, false, false, false);
|
||||
$subjectTemplate->assign('session_name', $session['name']);
|
||||
$subjectTemplate->assign(
|
||||
'session_access_end_date',
|
||||
$session['access_end_date']
|
||||
);
|
||||
$subjectTemplate->assign(
|
||||
'remaining_days',
|
||||
$daysRemaining->format("%d")
|
||||
);
|
||||
|
||||
$subjectLayout = $subjectTemplate->get_template(
|
||||
'mail/cron_remind_course_expiration_subject.tpl'
|
||||
);
|
||||
|
||||
$bodyTemplate = new Template(null, false, false, false, false, false);
|
||||
$bodyTemplate->assign('complete_user_name', $userCompleteName);
|
||||
$bodyTemplate->assign('session_name', $session['name']);
|
||||
$bodyTemplate->assign(
|
||||
'session_access_end_date',
|
||||
$session['access_end_date']
|
||||
);
|
||||
$bodyTemplate->assign(
|
||||
'remaining_days',
|
||||
$daysRemaining->format("%d")
|
||||
);
|
||||
|
||||
$bodyLayout = $bodyTemplate->get_template(
|
||||
'mail/cron_remind_course_expiration_body.tpl'
|
||||
);
|
||||
|
||||
api_mail_html(
|
||||
$userCompleteName,
|
||||
$user['email'],
|
||||
$subjectTemplate->fetch($subjectLayout),
|
||||
$bodyTemplate->fetch($bodyLayout),
|
||||
$administrator['completeName'],
|
||||
$administrator['email']
|
||||
);
|
||||
echo "Email sent to $userCompleteName (".$user['email'].")\n";
|
||||
echo "Session: ".$session['name']."\n";
|
||||
echo "Date end: ".$session['access_end_date']."\n";
|
||||
echo "Days remaining: ".$daysRemaining->format("%d")."\n\n";
|
||||
}
|
||||
echo "======================================================================\n\n";
|
||||
}
|
||||
} else {
|
||||
echo "No users to be reminded\n";
|
||||
}
|
||||
86
main/cron/request_removal_reminder.php
Normal file
86
main/cron/request_removal_reminder.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require_once __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
if (PHP_SAPI != 'cli') {
|
||||
exit('Run this script through the command line or comment this line in the code');
|
||||
}
|
||||
|
||||
$urlList = UrlManager::get_url_data();
|
||||
|
||||
$defaultSenderId = 1;
|
||||
|
||||
// Loop all portals
|
||||
foreach ($urlList as $url) {
|
||||
// Set access_url in order to get the correct url links and admins
|
||||
$_configuration['access_url'] = $url['id'];
|
||||
|
||||
$sql = '';
|
||||
$user_table = Database::get_main_table(TABLE_MAIN_USER);
|
||||
$admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
|
||||
|
||||
$sql .= "SELECT u.id, v.updated_at FROM $user_table u";
|
||||
|
||||
// adding the filter to see the user's only of the current access_url
|
||||
if (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 = UserManager::createDataPrivacyExtraFields();
|
||||
$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
|
||||
) ";
|
||||
|
||||
$sql .= " WHERE 1 = 1 ";
|
||||
|
||||
if (api_get_multiple_access_url()) {
|
||||
$sql .= " AND url_rel_user.access_url_id = ".api_get_current_access_url_id();
|
||||
}
|
||||
|
||||
$numberOfDays = 7;
|
||||
$date = new DateTime();
|
||||
$date->sub(new \DateInterval('P'.$numberOfDays.'D'));
|
||||
$dateToString = $date->format('Y-m-d h:i:s');
|
||||
$sql .= " AND v.updated_at < '$dateToString'";
|
||||
|
||||
$url = api_get_path(WEB_CODE_PATH).'admin/user_list_consent.php';
|
||||
$link = Display::url($url, $url);
|
||||
$subject = get_lang('UserRequestWaitingForAction');
|
||||
|
||||
$email = api_get_configuration_value('data_protection_officer_email');
|
||||
|
||||
$message = 'Checking requests from '.strip_tags(Display::dateToStringAgoAndLongDate($dateToString))."\n";
|
||||
|
||||
$result = Database::query($sql);
|
||||
while ($user = Database::fetch_array($result, 'ASSOC')) {
|
||||
$userId = $user['id'];
|
||||
$userInfo = api_get_user_info($userId);
|
||||
if ($userInfo) {
|
||||
$content = sprintf(
|
||||
get_lang('TheUserXIsWaitingForAnActionGoHereX'),
|
||||
$userInfo['complete_name'],
|
||||
$link
|
||||
);
|
||||
|
||||
if (!empty($email)) {
|
||||
api_mail_html('', $email, $subject, $content);
|
||||
} else {
|
||||
MessageManager::sendMessageToAllAdminUsers($defaultSenderId, $subject, $content);
|
||||
}
|
||||
|
||||
$date = strip_tags(Display::dateToStringAgoAndLongDate($user['updated_at']));
|
||||
$message .= "User ".$userInfo['complete_name_with_username']." is waiting for an action since $date \n";
|
||||
}
|
||||
}
|
||||
echo $message;
|
||||
}
|
||||
21
main/cron/run.php
Normal file
21
main/cron/run.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* This script should be called by a properly set cron process on your server.
|
||||
* For more information, check the installation guide in the documentation
|
||||
* folder.
|
||||
* Add your own executable scripts below the inclusion of notification.php.
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*/
|
||||
/**
|
||||
* Settings that will influence the execution of the cron tasks.
|
||||
*/
|
||||
//ini_set('max_execution_time',300); //authorize execution for up to 5 minutes
|
||||
//ini_set('memory_limit','100M'); //authorize script to use up to 100M RAM
|
||||
/**
|
||||
* Included cron-ed tasks. You might want to turn error-logging off by
|
||||
* commenting the first and last line of this section.
|
||||
*/
|
||||
error_log('[chamilo][cronjob] Starting cron jobs as process '.getmypid());
|
||||
require_once 'notification.php';
|
||||
error_log('[chamilo][cronjob] Ending cron jobs of process '.getmypid());
|
||||
14
main/cron/scheduled_announcement.php
Normal file
14
main/cron/scheduled_announcement.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require __DIR__.'/../inc/global.inc.php';
|
||||
|
||||
$urlList = UrlManager::get_url_data();
|
||||
foreach ($urlList as $url) {
|
||||
$urlId = $url['id'];
|
||||
$_configuration['access_url'] = $urlId;
|
||||
echo "Portal: # ".$urlId." - ".$url['url'].'-'.api_get_path(WEB_CODE_PATH).PHP_EOL;
|
||||
$object = new ScheduledAnnouncement();
|
||||
$messagesSent = $object->sendPendingMessages($urlId);
|
||||
echo "Messages sent $messagesSent".PHP_EOL;
|
||||
}
|
||||
77
main/cron/update_ldap_users.php
Normal file
77
main/cron/update_ldap_users.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
exit;
|
||||
|
||||
require_once __DIR__.'/../../app/config/auth.conf.php';
|
||||
require_once __DIR__.'/../auth/external_login/ldap.inc.php';
|
||||
require_once __DIR__.'/../auth/external_login/functions.inc.php';
|
||||
|
||||
global $extldap_config;
|
||||
|
||||
if (empty($extldap_config)) {
|
||||
echo "$extldap_config not found";
|
||||
exit;
|
||||
}
|
||||
|
||||
$ds = extldap_connect();
|
||||
if (!$ds) {
|
||||
echo 'ldap not connected';
|
||||
exit;
|
||||
}
|
||||
|
||||
if (api_get_configuration_value('ldap_encrypt_admin_password')) {
|
||||
$ldap_pass = api_decrypt_ldap_password($extldap_config['admin_password']);
|
||||
} else {
|
||||
$ldap_pass = $extldap_config['admin_password'];
|
||||
}
|
||||
$ldapbind = @ldap_bind($ds, $extldap_config['admin_dn'], $ldap_pass);
|
||||
if ($ldapbind === false) {
|
||||
echo 'EXTLDAP ERROR : cannot connect with admin login/password';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_USER);
|
||||
$sql = "SELECT * FROM $table WHERE auth_source = 'ldap' ";
|
||||
$result = Database::query($sql);
|
||||
while ($user = Database::fetch_array($result, 'ASSOC')) {
|
||||
$userId = $user['id'];
|
||||
$username = $user['username'];
|
||||
$user_search = extldap_get_user_search_string($username);
|
||||
$sr = ldap_search($ds, $extldap_config['base_dn'], $user_search);
|
||||
if (!$sr) {
|
||||
echo "Username not found in LDAP: ".$username.PHP_EOL;
|
||||
continue;
|
||||
}
|
||||
$users = ldap_get_entries($ds, $sr);
|
||||
$extraFieldUser = new ExtraFieldValue('user');
|
||||
if (!empty($users)) {
|
||||
echo "Updating user #".$userId.PHP_EOL;
|
||||
for ($key = 0; $key < $users['count']; $key++) {
|
||||
$ldapUser = $users[$key];
|
||||
//print_r($ldapUser).PHP_EOL;
|
||||
$params = [
|
||||
'firstname' => $ldapUser['givenname'][0],
|
||||
'lastname' => $ldapUser['sn'][0],
|
||||
'email' => $ldapUser['mail'][0],
|
||||
];
|
||||
print_r($params).PHP_EOL;
|
||||
Database::update($table, $params, ['id = ?' => $userId]);
|
||||
|
||||
$extraFields = [
|
||||
'company' => $ldapUser['department'][0],
|
||||
];
|
||||
foreach ($extraFields as $variable => $value) {
|
||||
$params = [
|
||||
'item_id' => $userId,
|
||||
'variable' => $variable,
|
||||
'value' => $value,
|
||||
];
|
||||
print_r($params).PHP_EOL;
|
||||
$extraFieldUser->save($params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
main/cron/user_import/client.php
Normal file
36
main/cron/user_import/client.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/* See license terms in /license.txt */
|
||||
|
||||
/**
|
||||
* This is a script used to automatically import a list of users from
|
||||
* a CSV file into Dokeos.
|
||||
* It is triggered by a cron task configured on the server.
|
||||
*
|
||||
* @uses /main/webservices/user_import/
|
||||
*
|
||||
* @author Eric Marguin <eric.marguin@dokeos.com>
|
||||
*
|
||||
* @package chamilo.cron
|
||||
*/
|
||||
/**
|
||||
* Global cycle: init, execute, output.
|
||||
*/
|
||||
require_once __DIR__.'/../../inc/global.inc.php';
|
||||
// check if this client has been called by php_cli (command line or cron)
|
||||
if (php_sapi_name() != 'cli') {
|
||||
echo 'You can\'t call this service through a browser';
|
||||
exit();
|
||||
}
|
||||
|
||||
// create client
|
||||
$client = new nusoap_client(api_get_path(WEB_CODE_PATH).'cron/user_import/service.php');
|
||||
|
||||
// call import_user method
|
||||
$response = $client->call(
|
||||
'import_users',
|
||||
[
|
||||
'filepath' => api_get_path(SYS_UPLOAD_PATH)."users_import.csv",
|
||||
'security_key' => api_get_configuration_value('security_key'),
|
||||
]
|
||||
);
|
||||
echo $response;
|
||||
35
main/cron/user_import/get_data_from_mail.php
Normal file
35
main/cron/user_import/get_data_from_mail.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* This script gets users details of a given list of users
|
||||
* (given by e-mail) and prints the details in /tmp/list.txt
|
||||
* To enable script, prefix the first die(); with //.
|
||||
*
|
||||
* @package chamilo.cron.user_import
|
||||
*/
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
/* Example of input file:
|
||||
sam@example.com
|
||||
Matthew@example.com
|
||||
HERMAN@example.com
|
||||
*/
|
||||
exit();
|
||||
//change filename depending on file containing mails list
|
||||
$list = file('input.txt');
|
||||
require_once '../../inc/global.inc.php';
|
||||
$users = Database::get_main_table(TABLE_MAIN_USER);
|
||||
$string = '';
|
||||
foreach ($list as $mail) {
|
||||
$mail = trim($mail);
|
||||
$sql = "SELECT user_id, official_code, firstname, lastname, email FROM $users WHERE email = '$mail'\n";
|
||||
$res = Database::query($sql);
|
||||
if (Database::num_rows($res) == 0) {
|
||||
$string .= 'No encontrado;'.$row['email'];
|
||||
} else {
|
||||
$row = Database::fetch_assoc($res);
|
||||
$string .= $row['user_id'].';'.$row['email'].';'.$row['firstname'].';'.$row['lastname'].';'.$row['official_code']."\r\n";
|
||||
}
|
||||
}
|
||||
echo $string;
|
||||
file_put_contents('/tmp/list.txt', $string);
|
||||
88
main/cron/user_import/resend_email_with_new_password.php
Normal file
88
main/cron/user_import/resend_email_with_new_password.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This script updates the passwords of a given list of users
|
||||
* (given by e-mail) and resends them their account creation
|
||||
* confirmation e-mail.
|
||||
* Note that the password generation has been simplified, which
|
||||
* means the password below is not really "safe"
|
||||
* To enable script, prefix the first die(); with //.
|
||||
*
|
||||
* @package chamilo.cron.user_import
|
||||
*/
|
||||
/**
|
||||
* Initialization.
|
||||
*/
|
||||
/* Example of input file:
|
||||
sam@example.com
|
||||
Matthew@example.com
|
||||
HERMAN@example.com
|
||||
*/
|
||||
exit();
|
||||
//change filename depending on file containing mails list, with one e-mail per line.
|
||||
$list = file('input.txt');
|
||||
require_once '../../inc/global.inc.php';
|
||||
$users = Database::get_main_table(TABLE_MAIN_USER);
|
||||
$userManager = UserManager::getManager();
|
||||
$repository = UserManager::getRepository();
|
||||
|
||||
/**
|
||||
* E-mails list loop.
|
||||
*/
|
||||
foreach ($list as $mail) {
|
||||
$mail = trim($mail);
|
||||
$sql = "SELECT user_id, official_code, firstname, lastname, email, username, language
|
||||
FROM $users WHERE email = '$mail'\n";
|
||||
$res = Database::query($sql);
|
||||
if ($res === false) {
|
||||
echo 'Error in database with email '.$mail."\n";
|
||||
}
|
||||
if (Database::num_rows($res) == 0) {
|
||||
echo '[Error] Email not found in database: '.$row['email']."\n";
|
||||
} else {
|
||||
$row = Database::fetch_assoc($res);
|
||||
$pass = api_substr($row['username'], 0, 4).rand(0, 9).rand(0, 9);
|
||||
|
||||
if ($user) {
|
||||
/** @var User $user */
|
||||
$user = $repository->find($row['user_id']);
|
||||
$user->setPlainPassword($pass);
|
||||
$userManager->updateUser($user, true);
|
||||
} else {
|
||||
echo "[Error] Error updating password. Skipping $mail\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$user = [
|
||||
'FirstName' => $row['firstname'],
|
||||
'LastName' => $row['lastname'],
|
||||
'UserName' => $row['username'],
|
||||
'Password' => $pass,
|
||||
'Email' => $mail,
|
||||
];
|
||||
$l = api_get_interface_language();
|
||||
if (!empty($row['language'])) {
|
||||
$l = $row['language'];
|
||||
}
|
||||
//This comes from main/admin/user_import.php::save_data() slightly modified
|
||||
$recipient_name = api_get_person_name(
|
||||
$user['FirstName'],
|
||||
$user['LastName'],
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg', null, $l).' '.api_get_setting('siteName');
|
||||
$emailbody = get_lang('Dear', null, $l).' '.api_get_person_name($user['FirstName'], $user['LastName']).",\n\n".get_lang('YouAreReg', null, $l)." ".api_get_setting('siteName')." ".get_lang('WithTheFollowingSettings', null, $l)."\n\n".get_lang('Username', null, $l)." : ".$user['UserName']."\n".get_lang('Pass', null, $l)." : ".$user['Password']."\n\n".get_lang('Address', null, $l)." ".api_get_setting('siteName')." ".get_lang('Is', null, $l)." : ".api_get_path(WEB_PATH)." \n\n".get_lang('Problem', null, $l)."\n\n".get_lang('Formula', null, $l).",\n\n".api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n".get_lang('Manager', null, $l)." ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n".get_lang('Email', null, $l)." : ".api_get_setting('emailAdministrator')."";
|
||||
$sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
|
||||
$email_admin = api_get_setting('emailAdministrator');
|
||||
@api_mail_html(
|
||||
$recipient_name,
|
||||
$user['Email'],
|
||||
$emailsubject,
|
||||
$emailbody,
|
||||
$sender_name,
|
||||
$email_admin
|
||||
);
|
||||
echo "[OK] Sent to $mail with new password $pass (encrypted:$crypass)... w/ subject: $emailsubject\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user