upgrade
This commit is contained in:
1
main/inc/lib/.htaccess
Normal file
1
main/inc/lib/.htaccess
Normal file
@@ -0,0 +1 @@
|
||||
Options -Indexes
|
||||
441
main/inc/lib/AnnouncementEmail.php
Normal file
441
main/inc/lib/AnnouncementEmail.php
Normal file
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Announcement Email.
|
||||
*
|
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
|
||||
* @author Julio Montoya <gugli100@gmail.com> Adding session support
|
||||
*/
|
||||
class AnnouncementEmail
|
||||
{
|
||||
public $session_id = null;
|
||||
public $logger;
|
||||
protected $course = null;
|
||||
protected $announcement = null;
|
||||
|
||||
/**
|
||||
* @param array $courseInfo
|
||||
* @param int $sessionId
|
||||
* @param int $announcementId
|
||||
* @param \Monolog\Logger $logger
|
||||
*/
|
||||
public function __construct($courseInfo, $sessionId, $announcementId, $logger = null)
|
||||
{
|
||||
if (empty($courseInfo)) {
|
||||
$courseInfo = api_get_course_info();
|
||||
}
|
||||
|
||||
$this->course = $courseInfo;
|
||||
$this->session_id = empty($sessionId) ? api_get_session_id() : (int) $sessionId;
|
||||
|
||||
if (is_numeric($announcementId)) {
|
||||
$this->announcement = AnnouncementManager::get_by_id($courseInfo['real_id'], $announcementId);
|
||||
}
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Course info.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function course($key = '')
|
||||
{
|
||||
$result = $key ? $this->course[$key] : $this->course;
|
||||
$result = $key == 'id' ? intval($result) : $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Announcement info.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function announcement($key = '')
|
||||
{
|
||||
$result = $key ? $this->announcement[$key] : $this->announcement;
|
||||
$result = $key == 'id' ? intval($result) : $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either all course users or all session users depending on whether
|
||||
* session is turned on or not.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all_users()
|
||||
{
|
||||
$courseCode = $this->course('code');
|
||||
if (empty($this->session_id)) {
|
||||
$group_id = api_get_group_id();
|
||||
if (empty($group_id)) {
|
||||
$userList = CourseManager::get_user_list_from_course_code($courseCode);
|
||||
} else {
|
||||
$userList = GroupManager::get_users($group_id);
|
||||
$new_user_list = [];
|
||||
foreach ($userList as $user) {
|
||||
$new_user_list[] = ['user_id' => $user];
|
||||
}
|
||||
$userList = $new_user_list;
|
||||
}
|
||||
} else {
|
||||
$userList = CourseManager::get_user_list_from_course_code(
|
||||
$courseCode,
|
||||
$this->session_id
|
||||
);
|
||||
}
|
||||
|
||||
return $userList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns users and groups an announcement item has been sent to.
|
||||
*
|
||||
* @return array Array of users and groups to whom the element has been sent
|
||||
*/
|
||||
public function sent_to_info()
|
||||
{
|
||||
$result = [];
|
||||
$result['groups'] = [];
|
||||
$result['users'] = [];
|
||||
|
||||
$table = Database::get_course_table(TABLE_ITEM_PROPERTY);
|
||||
$tool = TOOL_ANNOUNCEMENT;
|
||||
$id = $this->announcement('id');
|
||||
$course_id = $this->course('real_id');
|
||||
$sessionCondition = api_get_session_condition($this->session_id);
|
||||
|
||||
$sql = "SELECT to_group_id, to_user_id
|
||||
FROM $table
|
||||
WHERE
|
||||
c_id = $course_id AND
|
||||
tool = '$tool' AND
|
||||
ref = $id
|
||||
$sessionCondition";
|
||||
|
||||
$rs = Database::query($sql);
|
||||
|
||||
while ($row = Database::fetch_array($rs, 'ASSOC')) {
|
||||
// if to_user_id <> 0 then it is sent to a specific user
|
||||
$user_id = $row['to_user_id'];
|
||||
if (!empty($user_id)) {
|
||||
$result['users'][] = (int) $user_id;
|
||||
// If user is set then skip the group
|
||||
continue;
|
||||
}
|
||||
|
||||
// if to_group_id is null then it is sent to a specific user
|
||||
// if to_group_id = 0 then it is sent to everybody
|
||||
$group_id = $row['to_group_id'];
|
||||
if (!empty($group_id)) {
|
||||
$result['groups'][] = (int) $group_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of user info to which an announcement was sent.
|
||||
* This function returns a list of actual users even when recipient
|
||||
* are groups.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sent_to()
|
||||
{
|
||||
$sent_to = $this->sent_to_info();
|
||||
$users = $sent_to['users'];
|
||||
$users = $users ? $users : [];
|
||||
$groups = $sent_to['groups'];
|
||||
|
||||
if ($users) {
|
||||
$users = UserManager::get_user_list_by_ids($users, true);
|
||||
}
|
||||
|
||||
if (!empty($groups)) {
|
||||
$groupUsers = GroupManager::get_groups_users($groups);
|
||||
$groupUsers = UserManager::get_user_list_by_ids($groupUsers, true);
|
||||
|
||||
if (!empty($groupUsers)) {
|
||||
$users = array_merge($users, $groupUsers);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($users)) {
|
||||
if (!empty($this->logger)) {
|
||||
$this->logger->addInfo('User list is empty. No users found. Trying all_users()');
|
||||
}
|
||||
$users = self::all_users();
|
||||
}
|
||||
|
||||
// Clean users just in case
|
||||
$newListUsers = [];
|
||||
if (!empty($users)) {
|
||||
foreach ($users as $user) {
|
||||
$newListUsers[$user['user_id']] = ['user_id' => $user['user_id']];
|
||||
}
|
||||
}
|
||||
|
||||
return $newListUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Email subject.
|
||||
*
|
||||
* @param bool $directMessage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function subject($directMessage = false)
|
||||
{
|
||||
if ($directMessage) {
|
||||
$result = $this->announcement('title');
|
||||
} else {
|
||||
$result = $this->course('title').' - '.$this->announcement('title');
|
||||
}
|
||||
|
||||
$result = stripslashes($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Email message.
|
||||
*
|
||||
* @param int $receiverUserId
|
||||
* @param bool $checkUrls It checks access url of user when multiple_access_urls = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function message($receiverUserId, $checkUrls = false)
|
||||
{
|
||||
$content = $this->announcement('content');
|
||||
$session_id = $this->session_id;
|
||||
$courseCode = $this->course('code');
|
||||
$courseId = $this->course('real_id');
|
||||
$content = AnnouncementManager::parseContent(
|
||||
$receiverUserId,
|
||||
$content,
|
||||
$courseCode,
|
||||
$session_id
|
||||
);
|
||||
|
||||
$accessConfig = [];
|
||||
$useMultipleUrl = api_get_configuration_value('multiple_access_urls');
|
||||
if ($useMultipleUrl && $checkUrls) {
|
||||
$accessUrls = api_get_access_url_from_user($receiverUserId, $courseId);
|
||||
if (!empty($accessUrls)) {
|
||||
$accessConfig['multiple_access_urls'] = true;
|
||||
$accessConfig['access_url'] = (int) $accessUrls[0];
|
||||
}
|
||||
}
|
||||
// Build the link by hand because api_get_cidreq() doesn't accept course params
|
||||
$course_param = 'cidReq='.$courseCode.'&id_session='.$session_id.'&gidReq='.api_get_group_id();
|
||||
$course_name = $this->course('title');
|
||||
$result = "<div>$content</div>";
|
||||
|
||||
// Adding attachment
|
||||
$attachment = $this->attachment();
|
||||
if (!empty($attachment)) {
|
||||
$result .= '<br />';
|
||||
$result .= Display::url(
|
||||
$attachment['filename'],
|
||||
api_get_path(WEB_CODE_PATH, $accessConfig).
|
||||
'announcements/download.php?file='.basename($attachment['path']).'&'.$course_param
|
||||
);
|
||||
$result .= '<br />';
|
||||
}
|
||||
|
||||
$result .= '<hr />';
|
||||
|
||||
$userInfo = api_get_user_info();
|
||||
if (!empty($userInfo)) {
|
||||
if ('true' === api_get_setting('show_email_addresses')) {
|
||||
$result .= '<a href="mailto:'.$userInfo['mail'].'">'.$userInfo['complete_name'].'</a><br/>';
|
||||
} else {
|
||||
$result .= '<p>'.$userInfo['complete_name'].'</p><br/>';
|
||||
}
|
||||
}
|
||||
|
||||
$result .= '<a href="'.api_get_path(WEB_CODE_PATH, $accessConfig).'announcements/announcements.php?'.$course_param.'">'.
|
||||
$course_name.'</a><br/>';
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one file that can be attached to an announcement.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attachment()
|
||||
{
|
||||
$result = [];
|
||||
$table = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
|
||||
$id = $this->announcement('id');
|
||||
$course_id = $this->course('real_id');
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE c_id = $course_id AND announcement_id = $id ";
|
||||
$rs = Database::query($sql);
|
||||
$course_path = $this->course('directory');
|
||||
while ($row = Database::fetch_array($rs)) {
|
||||
$path = api_get_path(SYS_COURSE_PATH).$course_path.'/upload/announcements/'.$row['path'];
|
||||
$filename = $row['filename'];
|
||||
$result[] = ['path' => $path, 'filename' => $filename];
|
||||
}
|
||||
|
||||
$result = $result ? reset($result) : [];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send announcement by email to myself.
|
||||
*/
|
||||
public function sendAnnouncementEmailToMySelf()
|
||||
{
|
||||
$userId = api_get_user_id();
|
||||
$subject = $this->subject();
|
||||
$message = $this->message($userId);
|
||||
MessageManager::send_message_simple(
|
||||
$userId,
|
||||
$subject,
|
||||
$message,
|
||||
api_get_user_id(),
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emails to users.
|
||||
*
|
||||
* @param bool $sendToUsersInSession
|
||||
* @param bool $sendToDrhUsers send a copy of the message to the DRH users
|
||||
* @param int $senderId related to the main user
|
||||
* @param bool $directMessage
|
||||
* @param bool $checkUrls It checks access url of user when multiple_access_urls = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function send($sendToUsersInSession = false, $sendToDrhUsers = false, $senderId = 0, $directMessage = false, $checkUrls = false)
|
||||
{
|
||||
$senderId = empty($senderId) ? api_get_user_id() : (int) $senderId;
|
||||
$subject = $this->subject($directMessage);
|
||||
$courseId = $this->course('real_id');
|
||||
// Send email one by one to avoid antispam
|
||||
$users = $this->sent_to();
|
||||
|
||||
$batchSize = 20;
|
||||
$counter = 1;
|
||||
$em = Database::getManager();
|
||||
|
||||
if (empty($users) && !empty($this->logger)) {
|
||||
$this->logger->addInfo('User list is empty. No emails will be sent.');
|
||||
}
|
||||
$messageSentTo = [];
|
||||
foreach ($users as $user) {
|
||||
$message = $this->message($user['user_id'], $checkUrls);
|
||||
$wasSent = MessageManager::messageWasAlreadySent($senderId, $user['user_id'], $subject, $message);
|
||||
if ($wasSent === false) {
|
||||
if (!empty($this->logger)) {
|
||||
$this->logger->addInfo(
|
||||
'Announcement: #'.$this->announcement('id').'. Send email to user: #'.$user['user_id']
|
||||
);
|
||||
}
|
||||
|
||||
$messageSentTo[] = $user['user_id'];
|
||||
MessageManager::send_message_simple(
|
||||
$user['user_id'],
|
||||
$subject,
|
||||
$message,
|
||||
$senderId,
|
||||
$sendToDrhUsers,
|
||||
true,
|
||||
[],
|
||||
true,
|
||||
[],
|
||||
$checkUrls,
|
||||
$courseId
|
||||
);
|
||||
} else {
|
||||
if (!empty($this->logger)) {
|
||||
$this->logger->addInfo(
|
||||
'Message "'.$subject.'" was already sent. Announcement: #'.$this->announcement('id').'.
|
||||
User: #'.$user['user_id']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (($counter % $batchSize) === 0) {
|
||||
$em->flush();
|
||||
$em->clear();
|
||||
}
|
||||
$counter++;
|
||||
}
|
||||
|
||||
if ($sendToUsersInSession) {
|
||||
$sessionList = SessionManager::get_session_by_course($this->course['real_id']);
|
||||
if (!empty($sessionList)) {
|
||||
foreach ($sessionList as $sessionInfo) {
|
||||
$sessionId = $sessionInfo['id'];
|
||||
$message = $this->message(null);
|
||||
$userList = CourseManager::get_user_list_from_course_code(
|
||||
$this->course['code'],
|
||||
$sessionId
|
||||
);
|
||||
if (!empty($userList)) {
|
||||
foreach ($userList as $user) {
|
||||
$messageSentTo[] = $user['user_id'];
|
||||
MessageManager::send_message_simple(
|
||||
$user['user_id'],
|
||||
$subject,
|
||||
$message,
|
||||
$senderId,
|
||||
false,
|
||||
true,
|
||||
[],
|
||||
true,
|
||||
[],
|
||||
$checkUrls,
|
||||
$courseId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->logMailSent();
|
||||
$messageSentTo = array_unique($messageSentTo);
|
||||
|
||||
return $messageSentTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store that emails where sent.
|
||||
*/
|
||||
public function logMailSent()
|
||||
{
|
||||
$id = $this->announcement('id');
|
||||
$courseId = $this->course('real_id');
|
||||
$table = Database::get_course_table(TABLE_ANNOUNCEMENT);
|
||||
$sql = "UPDATE $table SET
|
||||
email_sent = 1
|
||||
WHERE
|
||||
c_id = $courseId AND
|
||||
id = $id AND
|
||||
session_id = {$this->session_id}
|
||||
";
|
||||
Database::query($sql);
|
||||
}
|
||||
}
|
||||
2282
main/inc/lib/AnnouncementManager.php
Normal file
2282
main/inc/lib/AnnouncementManager.php
Normal file
File diff suppressed because it is too large
Load Diff
402
main/inc/lib/Compilatio.php
Normal file
402
main/inc/lib/Compilatio.php
Normal file
@@ -0,0 +1,402 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
|
||||
/**
|
||||
* Build the communication with the SOAP server Compilatio.net
|
||||
* call several methods for the file management in Compilatio.net.
|
||||
*
|
||||
* @version: 2.0
|
||||
*/
|
||||
class Compilatio
|
||||
{
|
||||
/** Identification key for the Compilatio account*/
|
||||
public $key;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
public $client;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $baseUrl;
|
||||
/** Webservice connection*/
|
||||
private $maxFileSize;
|
||||
private $proxyHost;
|
||||
private $proxyPort;
|
||||
|
||||
/**
|
||||
* Compilatio constructor.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$settings = $this->getSettings();
|
||||
|
||||
$this->maxFileSize = $settings['max_filesize'];
|
||||
$this->key = $settings['key'];
|
||||
$this->baseUrl = $settings['api_url'];
|
||||
|
||||
if (!empty($settings['proxy_host'])) {
|
||||
$this->proxyHost = $settings['proxy_host'];
|
||||
$this->proxyPort = $settings['proxy_port'];
|
||||
}
|
||||
|
||||
$clientConfig = [
|
||||
'base_uri' => api_remove_trailing_slash($this->baseUrl).'/',
|
||||
'headers' => [
|
||||
'X-Auth-Token' => $this->key,
|
||||
'Accept' => 'application/json',
|
||||
],
|
||||
];
|
||||
|
||||
if ($this->proxyPort) {
|
||||
$clientConfig['proxy'] = $this->proxyHost.':'.$this->proxyPort;
|
||||
}
|
||||
|
||||
$this->client = new Client($clientConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return Compilatio
|
||||
*/
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMaxFileSize()
|
||||
{
|
||||
return $this->maxFileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProxyHost()
|
||||
{
|
||||
return $this->proxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProxyPort()
|
||||
{
|
||||
return $this->proxyPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for the file load.
|
||||
*/
|
||||
public function sendDoc(
|
||||
string $title,
|
||||
string $description,
|
||||
string $filename,
|
||||
string $filepath
|
||||
) {
|
||||
$user = api_get_user_entity(api_get_user_id());
|
||||
|
||||
$postData = [
|
||||
'folder_id' => '',
|
||||
'title' => $title,
|
||||
'filename' => basename($filename),
|
||||
'indexed' => 'true',
|
||||
'user_notes' => [
|
||||
'description' => $description,
|
||||
],
|
||||
'authors' => [
|
||||
[
|
||||
'firstname' => $user->getFirstname(),
|
||||
'lastname' => $user->getlastname(),
|
||||
'email_address' => $user->getEmail(),
|
||||
],
|
||||
],
|
||||
'depositor' => [
|
||||
'firstname' => $user->getFirstname(),
|
||||
'lastname' => $user->getlastname(),
|
||||
'email_address' => $user->getEmail(),
|
||||
],
|
||||
];
|
||||
|
||||
try {
|
||||
$responseBody = $this->client
|
||||
->post(
|
||||
'private/documents',
|
||||
[
|
||||
'multipart' => [
|
||||
[
|
||||
'name' => 'postData',
|
||||
'contents' => json_encode($postData),
|
||||
],
|
||||
[
|
||||
'name' => 'file',
|
||||
'contents' => Utils::tryFopen($filepath, 'r'),
|
||||
],
|
||||
],
|
||||
]
|
||||
)
|
||||
->getBody()
|
||||
;
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
|
||||
$body = json_decode((string) $responseBody, true);
|
||||
|
||||
return $body['data']['document']['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for recover a document's information.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getDoc(string $documentId): array
|
||||
{
|
||||
try {
|
||||
$responseBody = $this->client
|
||||
->get(
|
||||
"private/documents/$documentId"
|
||||
)
|
||||
->getBody()
|
||||
;
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
|
||||
$responseJson = json_decode((string) $responseBody, true);
|
||||
$dataDocument = $responseJson['data']['document'];
|
||||
|
||||
$documentInfo = [
|
||||
'report_url' => $dataDocument['report_url'],
|
||||
];
|
||||
// anasim analyse type is applied for services Magister and Copyright
|
||||
// anasim-premium analyse type is applied for services Magister+ and Copyright+
|
||||
$anasim = 'anasim';
|
||||
if (isset($dataDocument['analyses']['anasim-premium'])) {
|
||||
$anasim = 'anasim-premium';
|
||||
if (isset($dataDocument['analyses']['anasim'])) {
|
||||
if (isset($dataDocument['analyses']['anasim']['creation_launch_date']) && isset($dataDocument['analyses']['anasim-premium']['creation_launch_date'])) {
|
||||
// if the 2 analyses type exist (which could happen technically but would be exceptional) then we present the most recent one.
|
||||
if ($dataDocument['analyses']['anasim']['creation_launch_date'] > $dataDocument['analyses']['anasim-premium']['creation_launch_date']) {
|
||||
$anasim = 'anasim';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($dataDocument['analyses'][$anasim]['state'])) {
|
||||
$documentInfo['analysis_status'] = $dataDocument['analyses'][$anasim]['state'];
|
||||
}
|
||||
|
||||
if (isset($dataDocument['light_reports'][$anasim]['scores']['global_score_percent'])) {
|
||||
$documentInfo['report_percent'] = $dataDocument['light_reports'][$anasim]['scores']['global_score_percent'];
|
||||
}
|
||||
|
||||
return $documentInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for deleting a Compialtio's account document.
|
||||
*/
|
||||
public function deldoc(string $documentId)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for start the analysis for a document.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function startAnalyse(string $compilatioId): string
|
||||
{
|
||||
try {
|
||||
$responseBody = $this->client
|
||||
->post(
|
||||
'private/analyses',
|
||||
[
|
||||
'json' => [
|
||||
'doc_id' => $compilatioId,
|
||||
],
|
||||
]
|
||||
)
|
||||
->getBody()
|
||||
;
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
|
||||
$body = json_decode((string) $responseBody, true);
|
||||
|
||||
return $body['data']['analysis']['state'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for identify a file extension and the possibility that the document can be managed by Compilatio.
|
||||
*/
|
||||
public static function verifiFileType(string $filename): bool
|
||||
{
|
||||
$types = ['doc', 'docx', 'rtf', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'pdf', 'txt', 'htm', 'html'];
|
||||
$extension = substr($filename, strrpos($filename, '.') + 1);
|
||||
$extension = strtolower($extension);
|
||||
|
||||
return in_array($extension, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for display the PomprseuilmankBar (% de plagiat).
|
||||
*/
|
||||
public static function getPomprankBarv31(
|
||||
int $index,
|
||||
int $weakThreshold,
|
||||
int $highThreshold
|
||||
): string {
|
||||
$index = round($index);
|
||||
$class = 'danger';
|
||||
if ($index < $weakThreshold) {
|
||||
$class = 'success';
|
||||
} elseif ($index < $highThreshold) {
|
||||
$class = 'warning';
|
||||
}
|
||||
|
||||
return Display::bar_progress($index, true, null, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for delete a document of the compilatio table if plagiarismTool is Compilatio.
|
||||
*/
|
||||
public static function plagiarismDeleteDoc(int $courseId, int $itemId)
|
||||
{
|
||||
if (api_get_configuration_value('allow_compilatio_tool') !== false) {
|
||||
$table = Database::get_course_table(TABLE_PLAGIARISM);
|
||||
$params = [$courseId, $itemId];
|
||||
Database::delete($table, ['c_id = ? AND document_id = ?' => $params]);
|
||||
}
|
||||
}
|
||||
|
||||
public function saveDocument(int $courseId, int $documentId, string $compilatioId)
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_PLAGIARISM);
|
||||
$params = [
|
||||
'c_id' => $courseId,
|
||||
'document_id' => $documentId,
|
||||
'compilatio_id' => $compilatioId,
|
||||
];
|
||||
Database::insert($table, $params);
|
||||
}
|
||||
|
||||
public function getCompilatioId(int $documentId, int $courseId): ?string
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_PLAGIARISM);
|
||||
$sql = "SELECT compilatio_id FROM $table
|
||||
WHERE document_id = $documentId AND c_id= $courseId";
|
||||
$result = Database::query($sql);
|
||||
$result = Database::fetch_object($result);
|
||||
|
||||
return $result ? (string) $result->compilatio_id : null;
|
||||
}
|
||||
|
||||
public function giveWorkIdState(int $workId): string
|
||||
{
|
||||
$courseId = api_get_course_int_id();
|
||||
$compilatioId = $this->getCompilatioId($workId, $courseId);
|
||||
|
||||
$actionCompilatio = '';
|
||||
// if the compilatio's hash is not a valide hash md5,
|
||||
// we return à specific status (cf : IsInCompilatio() )
|
||||
// Not used since implementation of RestAPI but there if needed later
|
||||
//$actionCompilatio = get_lang('CompilatioDocumentTextNotImage').'<br/>'.
|
||||
// get_lang('CompilatioDocumentNotCorrupt');
|
||||
$status = '';
|
||||
if (!empty($compilatioId)) {
|
||||
// if compilatio_id is a hash md5, we call the function of the compilatio's
|
||||
// webservice who return the document's status
|
||||
$soapRes = $this->getDoc($compilatioId);
|
||||
$status = $soapRes['analysis_status'] ?? '';
|
||||
|
||||
$spinnerIcon = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
|
||||
|
||||
switch ($status) {
|
||||
case 'finished':
|
||||
$actionCompilatio .= self::getPomprankBarv31($soapRes['report_percent'], 10, 35)
|
||||
.PHP_EOL
|
||||
.Display::url(
|
||||
get_lang('CompilatioAnalysis'),
|
||||
$soapRes['report_url'],
|
||||
['class' => 'btn btn-primary btn-xs', 'target' => '_blank']
|
||||
);
|
||||
break;
|
||||
case 'running':
|
||||
$actionCompilatio .= "<div style='font-weight:bold;text-align:left'>"
|
||||
.get_lang('CompilatioAnalysisInProgress')
|
||||
."</div>";
|
||||
$actionCompilatio .= "<div style='font-size:80%;font-style:italic;margin-bottom:5px;'>"
|
||||
.get_lang('CompilatioAnalysisPercentage')
|
||||
."</div>";
|
||||
$actionCompilatio .= $spinnerIcon.PHP_EOL.get_lang('CompilatioAnalysisEnding');
|
||||
break;
|
||||
case 'waiting':
|
||||
$actionCompilatio .= $spinnerIcon.PHP_EOL.get_lang('CompilatioWaitingAnalysis');
|
||||
break;
|
||||
case 'canceled':
|
||||
$actionCompilatio .= get_lang('Cancelled');
|
||||
break;
|
||||
case 'scheduled':
|
||||
$actionCompilatio .= $spinnerIcon.PHP_EOL.get_lang('CompilatioAwaitingAnalysis');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $workId.'|'.$actionCompilatio.'|'.$status.'|';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getSettings(): array
|
||||
{
|
||||
if (empty(api_get_configuration_value('allow_compilatio_tool')) ||
|
||||
empty(api_get_configuration_value('compilatio_tool'))
|
||||
) {
|
||||
throw new Exception('Compilatio not available');
|
||||
}
|
||||
|
||||
$compilatioTool = api_get_configuration_value('compilatio_tool');
|
||||
|
||||
if (!isset($compilatioTool['settings'])) {
|
||||
throw new Exception('Compilatio config available');
|
||||
}
|
||||
|
||||
$settings = $compilatioTool['settings'];
|
||||
|
||||
if (empty($settings['key'])) {
|
||||
throw new Exception('API key not available');
|
||||
}
|
||||
|
||||
if (empty($settings['api_url'])) {
|
||||
throw new Exception('Api URL not available');
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
887
main/inc/lib/CourseChatUtils.php
Normal file
887
main/inc/lib/CourseChatUtils.php
Normal file
@@ -0,0 +1,887 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Entity\Course;
|
||||
use Chamilo\CoreBundle\Entity\CourseRelUser;
|
||||
use Chamilo\CoreBundle\Entity\Session;
|
||||
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
|
||||
use Chamilo\CourseBundle\Entity\CChatConnected;
|
||||
use Chamilo\UserBundle\Entity\User;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Michelf\MarkdownExtra;
|
||||
|
||||
/**
|
||||
* Class CourseChat
|
||||
* Manage the chat for a course.
|
||||
*/
|
||||
class CourseChatUtils
|
||||
{
|
||||
private $groupId;
|
||||
private $courseId;
|
||||
private $sessionId;
|
||||
private $userId;
|
||||
|
||||
/**
|
||||
* CourseChat constructor.
|
||||
*
|
||||
* @param int $courseId
|
||||
* @param int $userId
|
||||
* @param int $sessionId
|
||||
* @param int $groupId
|
||||
*/
|
||||
public function __construct($courseId, $userId, $sessionId = 0, $groupId = 0)
|
||||
{
|
||||
$this->courseId = (int) $courseId;
|
||||
$this->userId = (int) $userId;
|
||||
$this->sessionId = (int) $sessionId;
|
||||
$this->groupId = (int) $groupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a message. Clean and insert emojis.
|
||||
*
|
||||
* @param string $message The message to prepare
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function prepareMessage($message)
|
||||
{
|
||||
if (empty($message)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
Emojione\Emojione::$imagePathPNG = api_get_path(WEB_LIBRARY_PATH).'javascript/emojione/png/';
|
||||
Emojione\Emojione::$ascii = true;
|
||||
|
||||
$message = trim($message);
|
||||
$message = nl2br($message);
|
||||
// Security XSS
|
||||
$message = Security::remove_XSS($message);
|
||||
//search urls
|
||||
$message = preg_replace(
|
||||
'@((https?://)?([-\w]+\.[-\w\.]+)+\w(:\d+)?(/([-\w/_\.]*(\?\S+)?)?)*)@',
|
||||
'<a href="$1" target="_blank">$1</a>',
|
||||
$message
|
||||
);
|
||||
// add "http://" if not set
|
||||
$message = preg_replace(
|
||||
'/<a\s[^>]*href\s*=\s*"((?!https?:\/\/)[^"]*)"[^>]*>/i',
|
||||
'<a href="http://$1" target="_blank">',
|
||||
$message
|
||||
);
|
||||
// Parsing emojis
|
||||
$message = Emojione\Emojione::toImage($message);
|
||||
// Parsing text to understand markdown (code highlight)
|
||||
$message = MarkdownExtra::defaultTransform($message);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a chat message in a HTML file.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $friendId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveMessage($message, $friendId = 0)
|
||||
{
|
||||
if (empty($message)) {
|
||||
return false;
|
||||
}
|
||||
$friendId = (int) $friendId;
|
||||
|
||||
$userInfo = api_get_user_info($this->userId);
|
||||
$courseInfo = api_get_course_info_by_id($this->courseId);
|
||||
$isMaster = api_is_course_admin();
|
||||
$document_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
|
||||
$basepath_chat = '/chat_files';
|
||||
$group_info = [];
|
||||
if ($this->groupId) {
|
||||
$group_info = GroupManager::get_group_properties($this->groupId);
|
||||
$basepath_chat = $group_info['directory'].'/chat_files';
|
||||
}
|
||||
|
||||
$chat_path = $document_path.$basepath_chat.'/';
|
||||
|
||||
if (!is_dir($chat_path)) {
|
||||
if (is_file($chat_path)) {
|
||||
@unlink($chat_path);
|
||||
}
|
||||
}
|
||||
|
||||
$date_now = date('Y-m-d');
|
||||
$timeNow = date('d/m/y H:i:s');
|
||||
$basename_chat = 'messages-'.$date_now;
|
||||
|
||||
if ($this->groupId && !$friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_gid-'.$this->groupId;
|
||||
} elseif ($this->sessionId && !$friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_sid-'.$this->sessionId;
|
||||
} elseif ($friendId) {
|
||||
if ($this->userId < $friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_uid-'.$this->userId.'-'.$friendId;
|
||||
} else {
|
||||
$basename_chat = 'messages-'.$date_now.'_uid-'.$friendId.'-'.$this->userId;
|
||||
}
|
||||
}
|
||||
|
||||
$message = self::prepareMessage($message);
|
||||
|
||||
$fileTitle = $basename_chat.'.log.html';
|
||||
$filePath = $basepath_chat.'/'.$fileTitle;
|
||||
$absoluteFilePath = $chat_path.$fileTitle;
|
||||
|
||||
if (!file_exists($absoluteFilePath)) {
|
||||
$doc_id = add_document(
|
||||
$courseInfo,
|
||||
$filePath,
|
||||
'file',
|
||||
0,
|
||||
$fileTitle,
|
||||
null,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false
|
||||
);
|
||||
$documentLogTypes = ['DocumentAdded', 'invisible'];
|
||||
foreach ($documentLogTypes as $logType) {
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
$logType,
|
||||
$this->userId,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$this->sessionId
|
||||
);
|
||||
}
|
||||
|
||||
item_property_update_on_folder($courseInfo, $basepath_chat, $this->userId);
|
||||
} else {
|
||||
$doc_id = DocumentManager::get_document_id($courseInfo, $filePath);
|
||||
}
|
||||
|
||||
$fp = fopen($absoluteFilePath, 'a');
|
||||
$userPhoto = UserManager::getUserPicture($this->userId, USER_IMAGE_SIZE_MEDIUM, true, $userInfo);
|
||||
|
||||
if ($isMaster) {
|
||||
$fileContent = '
|
||||
<div class="message-teacher">
|
||||
<div class="content-message">
|
||||
<div class="chat-message-block-name">'.$userInfo['complete_name'].'</div>
|
||||
<div class="chat-message-block-content">'.$message.'</div>
|
||||
<div class="message-date">'.$timeNow.'</div>
|
||||
</div>
|
||||
<div class="icon-message"></div>
|
||||
<img class="chat-image" src="'.$userPhoto.'">
|
||||
</div>
|
||||
';
|
||||
} else {
|
||||
$fileContent = '
|
||||
<div class="message-student">
|
||||
<img class="chat-image" src="'.$userPhoto.'">
|
||||
<div class="icon-message"></div>
|
||||
<div class="content-message">
|
||||
<div class="chat-message-block-name">'.$userInfo['complete_name'].'</div>
|
||||
<div class="chat-message-block-content">'.$message.'</div>
|
||||
<div class="message-date">'.$timeNow.'</div>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
}
|
||||
|
||||
fputs($fp, $fileContent);
|
||||
fclose($fp);
|
||||
$size = filesize($absoluteFilePath);
|
||||
update_existing_document($courseInfo, $doc_id, $size);
|
||||
item_property_update_on_folder($courseInfo, $basepath_chat, $this->userId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a user from course chats.
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public static function exitChat($userId)
|
||||
{
|
||||
$listCourse = CourseManager::get_courses_list_by_user_id($userId);
|
||||
|
||||
foreach ($listCourse as $course) {
|
||||
Database::getManager()
|
||||
->createQuery('
|
||||
DELETE FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.cId = :course AND ccc.userId = :user
|
||||
')
|
||||
->execute([
|
||||
'course' => intval($course['real_id']),
|
||||
'user' => intval($userId),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect users who are more than 5 seconds inactive.
|
||||
*/
|
||||
public function disconnectInactiveUsers()
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$extraCondition = "AND ccc.toGroupId = {$this->groupId}";
|
||||
if (empty($this->groupId)) {
|
||||
$extraCondition = "AND ccc.sessionId = {$this->sessionId}";
|
||||
}
|
||||
|
||||
$connectedUsers = $em
|
||||
->createQuery("
|
||||
SELECT ccc FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.cId = :course $extraCondition
|
||||
")
|
||||
->setParameter('course', $this->courseId)
|
||||
->getResult();
|
||||
|
||||
$now = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
|
||||
$cd_count_time_seconds = $now->getTimestamp();
|
||||
/** @var CChatConnected $connection */
|
||||
foreach ($connectedUsers as $connection) {
|
||||
$date_count_time_seconds = $connection->getLastConnection()->getTimestamp();
|
||||
if (strcmp($now->format('Y-m-d'), $connection->getLastConnection()->format('Y-m-d')) !== 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (($cd_count_time_seconds - $date_count_time_seconds) <= 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$em
|
||||
->createQuery('
|
||||
DELETE FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.cId = :course AND ccc.userId = :user AND ccc.toGroupId = :group
|
||||
')
|
||||
->execute([
|
||||
'course' => $this->courseId,
|
||||
'user' => $connection->getUserId(),
|
||||
'group' => $this->groupId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep registered to a user as connected.
|
||||
*/
|
||||
public function keepUserAsConnected()
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$extraCondition = null;
|
||||
|
||||
if ($this->groupId) {
|
||||
$extraCondition = 'AND ccc.toGroupId = '.intval($this->groupId);
|
||||
} else {
|
||||
$extraCondition = 'AND ccc.sessionId = '.intval($this->sessionId);
|
||||
}
|
||||
|
||||
$currentTime = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
|
||||
|
||||
$connection = $em
|
||||
->createQuery("
|
||||
SELECT ccc FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.userId = :user AND ccc.cId = :course $extraCondition
|
||||
")
|
||||
->setParameters([
|
||||
'user' => $this->userId,
|
||||
'course' => $this->courseId,
|
||||
])
|
||||
->getOneOrNullResult();
|
||||
|
||||
if ($connection) {
|
||||
$connection->setLastConnection($currentTime);
|
||||
$em->merge($connection);
|
||||
$em->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$connection = new CChatConnected();
|
||||
$connection
|
||||
->setCId($this->courseId)
|
||||
->setUserId($this->userId)
|
||||
->setLastConnection($currentTime)
|
||||
->setSessionId($this->sessionId)
|
||||
->setToGroupId($this->groupId);
|
||||
|
||||
$em->persist($connection);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the emoji allowed on course chat.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getEmojiStrategy()
|
||||
{
|
||||
return require_once api_get_path(SYS_CODE_PATH).'chat/emoji_strategy.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the emoji list to include in chat.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getEmojisToInclude()
|
||||
{
|
||||
return [
|
||||
':bowtie:',
|
||||
':smile:' |
|
||||
':laughing:',
|
||||
':blush:',
|
||||
':smiley:',
|
||||
':relaxed:',
|
||||
':smirk:',
|
||||
':heart_eyes:',
|
||||
':kissing_heart:',
|
||||
':kissing_closed_eyes:',
|
||||
':flushed:',
|
||||
':relieved:',
|
||||
':satisfied:',
|
||||
':grin:',
|
||||
':wink:',
|
||||
':stuck_out_tongue_winking_eye:',
|
||||
':stuck_out_tongue_closed_eyes:',
|
||||
':grinning:',
|
||||
':kissing:',
|
||||
':kissing_smiling_eyes:',
|
||||
':stuck_out_tongue:',
|
||||
':sleeping:',
|
||||
':worried:',
|
||||
':frowning:',
|
||||
':anguished:',
|
||||
':open_mouth:',
|
||||
':grimacing:',
|
||||
':confused:',
|
||||
':hushed:',
|
||||
':expressionless:',
|
||||
':unamused:',
|
||||
':sweat_smile:',
|
||||
':sweat:',
|
||||
':disappointed_relieved:',
|
||||
':weary:',
|
||||
':pensive:',
|
||||
':disappointed:',
|
||||
':confounded:',
|
||||
':fearful:',
|
||||
':cold_sweat:',
|
||||
':persevere:',
|
||||
':cry:',
|
||||
':sob:',
|
||||
':joy:',
|
||||
':astonished:',
|
||||
':scream:',
|
||||
':neckbeard:',
|
||||
':tired_face:',
|
||||
':angry:',
|
||||
':rage:',
|
||||
':triumph:',
|
||||
':sleepy:',
|
||||
':yum:',
|
||||
':mask:',
|
||||
':sunglasses:',
|
||||
':dizzy_face:',
|
||||
':imp:',
|
||||
':smiling_imp:',
|
||||
':neutral_face:',
|
||||
':no_mouth:',
|
||||
':innocent:',
|
||||
':alien:',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chat history file name.
|
||||
*
|
||||
* @param bool $absolute Optional. Whether get the base or the absolute file path
|
||||
* @param int $friendId optional
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName($absolute = false, $friendId = 0)
|
||||
{
|
||||
$date = date('Y-m-d');
|
||||
$base = 'messages-'.$date.'.log.html';
|
||||
|
||||
if ($this->groupId && !$friendId) {
|
||||
$base = 'messages-'.$date.'_gid-'.$this->groupId.'.log.html';
|
||||
} elseif ($this->sessionId && !$friendId) {
|
||||
$base = 'messages-'.$date.'_sid-'.$this->sessionId.'.log.html';
|
||||
} elseif ($friendId) {
|
||||
if ($this->userId < $friendId) {
|
||||
$base = 'messages-'.$date.'_uid-'.$this->userId.'-'.$friendId.'.log.html';
|
||||
} else {
|
||||
$base = 'messages-'.$date.'_uid-'.$friendId.'-'.$this->userId.'.log.html';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$absolute) {
|
||||
return $base;
|
||||
}
|
||||
|
||||
$courseInfo = api_get_course_info_by_id($this->courseId);
|
||||
$document_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
|
||||
$chatPath = $document_path.'/chat_files/';
|
||||
|
||||
if ($this->groupId) {
|
||||
$group_info = GroupManager::get_group_properties($this->groupId);
|
||||
$chatPath = $document_path.$group_info['directory'].'/chat_files/';
|
||||
}
|
||||
|
||||
return $chatPath.$base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chat history.
|
||||
*
|
||||
* @param bool $reset
|
||||
* @param int $friendId optional
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function readMessages($reset = false, $friendId = 0)
|
||||
{
|
||||
$courseInfo = api_get_course_info_by_id($this->courseId);
|
||||
$date_now = date('Y-m-d');
|
||||
$isMaster = (bool) api_is_course_admin();
|
||||
$basepath_chat = '/chat_files';
|
||||
$document_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
|
||||
$group_info = [];
|
||||
if ($this->groupId) {
|
||||
$group_info = GroupManager::get_group_properties($this->groupId);
|
||||
$basepath_chat = $group_info['directory'].'/chat_files';
|
||||
}
|
||||
|
||||
$chat_path = $document_path.$basepath_chat.'/';
|
||||
|
||||
if (!is_dir($chat_path)) {
|
||||
if (is_file($chat_path)) {
|
||||
@unlink($chat_path);
|
||||
}
|
||||
|
||||
if (!api_is_anonymous()) {
|
||||
@mkdir($chat_path, api_get_permissions_for_new_directories());
|
||||
// Save chat files document for group into item property
|
||||
if ($this->groupId) {
|
||||
$doc_id = add_document(
|
||||
$courseInfo,
|
||||
$basepath_chat,
|
||||
'folder',
|
||||
0,
|
||||
'chat_files',
|
||||
null,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false
|
||||
);
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'FolderCreated',
|
||||
null,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'invisible',
|
||||
null,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$filename_chat = 'messages-'.$date_now.'.log.html';
|
||||
|
||||
if ($this->groupId && !$friendId) {
|
||||
$filename_chat = 'messages-'.$date_now.'_gid-'.$this->groupId.'.log.html';
|
||||
} elseif ($this->sessionId && !$friendId) {
|
||||
$filename_chat = 'messages-'.$date_now.'_sid-'.$this->sessionId.'.log.html';
|
||||
} elseif ($friendId) {
|
||||
if ($this->userId < $friendId) {
|
||||
$filename_chat = 'messages-'.$date_now.'_uid-'.$this->userId.'-'.$friendId.'.log.html';
|
||||
} else {
|
||||
$filename_chat = 'messages-'.$date_now.'_uid-'.$friendId.'-'.$this->userId.'.log.html';
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_exists($chat_path.$filename_chat)) {
|
||||
@fclose(fopen($chat_path.$filename_chat, 'w'));
|
||||
if (!api_is_anonymous()) {
|
||||
$doc_id = add_document(
|
||||
$courseInfo,
|
||||
$basepath_chat.'/'.$filename_chat,
|
||||
'file',
|
||||
0,
|
||||
$filename_chat,
|
||||
null,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false
|
||||
);
|
||||
if ($doc_id) {
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'DocumentAdded',
|
||||
$this->userId,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$this->sessionId
|
||||
);
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'invisible',
|
||||
$this->userId,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$this->sessionId
|
||||
);
|
||||
item_property_update_on_folder($courseInfo, $basepath_chat, $this->userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$basename_chat = 'messages-'.$date_now;
|
||||
if ($this->groupId && !$friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_gid-'.$this->groupId;
|
||||
} elseif ($this->sessionId && !$friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_sid-'.$this->sessionId;
|
||||
} elseif ($friendId) {
|
||||
if ($this->userId < $friendId) {
|
||||
$basename_chat = 'messages-'.$date_now.'_uid-'.$this->userId.'-'.$friendId;
|
||||
} else {
|
||||
$basename_chat = 'messages-'.$date_now.'_uid-'.$friendId.'-'.$this->userId;
|
||||
}
|
||||
}
|
||||
|
||||
if ($reset && $isMaster) {
|
||||
$i = 1;
|
||||
while (file_exists($chat_path.$basename_chat.'-'.$i.'.log.html')) {
|
||||
$i++;
|
||||
}
|
||||
|
||||
@rename($chat_path.$basename_chat.'.log.html', $chat_path.$basename_chat.'-'.$i.'.log.html');
|
||||
@fclose(fopen($chat_path.$basename_chat.'.log.html', 'w'));
|
||||
|
||||
$doc_id = add_document(
|
||||
$courseInfo,
|
||||
$basepath_chat.'/'.$basename_chat.'-'.$i.'.log.html',
|
||||
'file',
|
||||
filesize($chat_path.$basename_chat.'-'.$i.'.log.html'),
|
||||
$basename_chat.'-'.$i.'.log.html',
|
||||
null,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'DocumentAdded',
|
||||
$this->userId,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$this->sessionId
|
||||
);
|
||||
api_item_property_update(
|
||||
$courseInfo,
|
||||
TOOL_DOCUMENT,
|
||||
$doc_id,
|
||||
'invisible',
|
||||
$this->userId,
|
||||
$group_info,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$this->sessionId
|
||||
);
|
||||
item_property_update_on_folder($courseInfo, $basepath_chat, $this->userId);
|
||||
$doc_id = DocumentManager::get_document_id(
|
||||
$courseInfo,
|
||||
$basepath_chat.'/'.$basename_chat.'.log.html'
|
||||
);
|
||||
update_existing_document($courseInfo, $doc_id, 0);
|
||||
}
|
||||
|
||||
$remove = 0;
|
||||
$content = [];
|
||||
|
||||
if (file_exists($chat_path.$basename_chat.'.log.html')) {
|
||||
$content = file($chat_path.$basename_chat.'.log.html');
|
||||
$nbr_lines = sizeof($content);
|
||||
$remove = $nbr_lines - 100;
|
||||
}
|
||||
|
||||
if ($remove < 0) {
|
||||
$remove = 0;
|
||||
}
|
||||
|
||||
array_splice($content, 0, $remove);
|
||||
|
||||
if (isset($_GET['origin']) && $_GET['origin'] == 'whoisonline') {
|
||||
//the caller
|
||||
$content[0] = get_lang('CallSent').'<br />'.$content[0];
|
||||
}
|
||||
|
||||
$history = '<div id="content-chat">';
|
||||
foreach ($content as $this_line) {
|
||||
$history .= $this_line;
|
||||
}
|
||||
$history .= '</div>';
|
||||
|
||||
if ($isMaster || $GLOBALS['is_session_general_coach']) {
|
||||
$history .= '
|
||||
<div id="clear-chat">
|
||||
<button type="button" id="chat-reset" class="btn btn-danger btn-sm">
|
||||
'.get_lang('ClearList').'
|
||||
</button>
|
||||
</div>
|
||||
';
|
||||
}
|
||||
|
||||
return $history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of users connected in chat.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countUsersOnline()
|
||||
{
|
||||
$date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
|
||||
$date->modify('-5 seconds');
|
||||
|
||||
if ($this->groupId) {
|
||||
$extraCondition = 'AND ccc.toGroupId = '.intval($this->groupId);
|
||||
} else {
|
||||
$extraCondition = 'AND ccc.sessionId = '.intval($this->sessionId);
|
||||
}
|
||||
|
||||
$number = Database::getManager()
|
||||
->createQuery("
|
||||
SELECT COUNT(ccc.userId) FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.lastConnection > :date AND ccc.cId = :course $extraCondition
|
||||
")
|
||||
->setParameters([
|
||||
'date' => $date,
|
||||
'course' => $this->courseId,
|
||||
])
|
||||
->getSingleScalarResult();
|
||||
|
||||
return (int) $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users online data.
|
||||
*
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listUsersOnline()
|
||||
{
|
||||
$subscriptions = $this->getUsersSubscriptions();
|
||||
$usersInfo = [];
|
||||
|
||||
if ($this->groupId) {
|
||||
/** @var User $groupUser */
|
||||
foreach ($subscriptions as $groupUser) {
|
||||
$usersInfo[] = $this->formatUser(
|
||||
$groupUser,
|
||||
$groupUser->getStatus()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
/** @var CourseRelUser|SessionRelCourseRelUser $subscription */
|
||||
foreach ($subscriptions as $subscription) {
|
||||
$user = $subscription->getUser();
|
||||
$usersInfo[] = $this->formatUser(
|
||||
$user,
|
||||
$this->sessionId ? $user->getStatus() : $subscription->getStatus()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $usersInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the user data to return it in the user list.
|
||||
*
|
||||
* @param int $status
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function formatUser(User $user, $status)
|
||||
{
|
||||
return [
|
||||
'id' => $user->getId(),
|
||||
'firstname' => $user->getFirstname(),
|
||||
'lastname' => $user->getLastname(),
|
||||
'status' => $status,
|
||||
'image_url' => UserManager::getUserPicture($user->getId(), USER_IMAGE_SIZE_MEDIUM),
|
||||
'profile_url' => api_get_path(WEB_CODE_PATH).'social/profile.php?u='.$user->getId(),
|
||||
'complete_name' => UserManager::formatUserFullName($user),
|
||||
'username' => $user->getUsername(),
|
||||
'email' => $user->getEmail(),
|
||||
'isConnected' => $this->userIsConnected($user->getId()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users subscriptions (SessionRelCourseRelUser array or CourseRelUser array) for chat.
|
||||
*
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||
*
|
||||
* @return \Doctrine\Common\Collections\ArrayCollection
|
||||
*/
|
||||
private function getUsersSubscriptions()
|
||||
{
|
||||
$em = Database::getManager();
|
||||
|
||||
if ($this->groupId) {
|
||||
$students = $em
|
||||
->createQuery(
|
||||
'SELECT u FROM ChamiloUserBundle:User u
|
||||
INNER JOIN ChamiloCourseBundle:CGroupRelUser gru
|
||||
WITH u.id = gru.userId AND gru.cId = :course
|
||||
WHERE u.id != :user AND gru.groupId = :group
|
||||
AND u.active = true'
|
||||
)
|
||||
->setParameters(['course' => $this->courseId, 'user' => $this->userId, 'group' => $this->groupId])
|
||||
->getResult();
|
||||
$tutors = $em
|
||||
->createQuery(
|
||||
'SELECT u FROM ChamiloUserBundle:User u
|
||||
INNER JOIN ChamiloCourseBundle:CGroupRelTutor grt
|
||||
WITH u.id = grt.userId AND grt.cId = :course
|
||||
WHERE u.id != :user AND grt.groupId = :group
|
||||
AND u.active = true'
|
||||
)
|
||||
->setParameters(['course' => $this->courseId, 'user' => $this->userId, 'group' => $this->groupId])
|
||||
->getResult();
|
||||
|
||||
return array_merge($tutors, $students);
|
||||
}
|
||||
|
||||
/** @var Course $course */
|
||||
$course = $em->find('ChamiloCoreBundle:Course', $this->courseId);
|
||||
|
||||
if ($this->sessionId) {
|
||||
/** @var Session $session */
|
||||
$session = $em->find('ChamiloCoreBundle:Session', $this->sessionId);
|
||||
$criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
|
||||
$userIsCoach = api_is_course_session_coach($this->userId, $course->getId(), $session->getId());
|
||||
|
||||
if (api_get_configuration_value('course_chat_restrict_to_coach')) {
|
||||
if ($userIsCoach) {
|
||||
$criteria->andWhere(
|
||||
Criteria::expr()->eq('status', Session::STUDENT)
|
||||
);
|
||||
} else {
|
||||
$criteria->andWhere(
|
||||
Criteria::expr()->eq('status', Session::COACH)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$criteria->orderBy(['status' => Criteria::DESC]);
|
||||
|
||||
return $session
|
||||
->getUserCourseSubscriptions()
|
||||
->matching($criteria)
|
||||
->filter(function (SessionRelCourseRelUser $sessionRelCourseRelUser) {
|
||||
return $sessionRelCourseRelUser->getUser()->isActive();
|
||||
});
|
||||
}
|
||||
|
||||
return $course
|
||||
->getUsers()
|
||||
->filter(function (CourseRelUser $courseRelUser) {
|
||||
return $courseRelUser->getUser()->isActive();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is connected in course chat.
|
||||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function userIsConnected($userId)
|
||||
{
|
||||
$date = new DateTime(api_get_utc_datetime(), new DateTimeZone('UTC'));
|
||||
$date->modify('-5 seconds');
|
||||
|
||||
if ($this->groupId) {
|
||||
$extraCondition = 'AND ccc.toGroupId = '.intval($this->groupId);
|
||||
} else {
|
||||
$extraCondition = 'AND ccc.sessionId = '.intval($this->sessionId);
|
||||
}
|
||||
|
||||
$number = Database::getManager()
|
||||
->createQuery("
|
||||
SELECT COUNT(ccc.userId) FROM ChamiloCourseBundle:CChatConnected ccc
|
||||
WHERE ccc.lastConnection > :date AND ccc.cId = :course AND ccc.userId = :user $extraCondition
|
||||
")
|
||||
->setParameters([
|
||||
'date' => $date,
|
||||
'course' => $this->courseId,
|
||||
'user' => $userId,
|
||||
])
|
||||
->getSingleScalarResult();
|
||||
|
||||
return (int) $number;
|
||||
}
|
||||
}
|
||||
2465
main/inc/lib/CoursesAndSessionsCatalog.class.php
Normal file
2465
main/inc/lib/CoursesAndSessionsCatalog.class.php
Normal file
File diff suppressed because it is too large
Load Diff
263
main/inc/lib/ExerciseCategoryManager.php
Normal file
263
main/inc/lib/ExerciseCategoryManager.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CourseBundle\Entity\CExerciseCategory;
|
||||
|
||||
/**
|
||||
* Class ExtraFieldValue
|
||||
* Declaration for the ExtraFieldValue class, managing the values in extra
|
||||
* fields for any data type.
|
||||
*/
|
||||
class ExerciseCategoryManager extends Model
|
||||
{
|
||||
public $type = '';
|
||||
public $columns = [
|
||||
'id',
|
||||
'name',
|
||||
'c_id',
|
||||
'description',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Formats the necessary elements for the given datatype.
|
||||
*
|
||||
* @assert (-1) === false
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->is_course_model = true;
|
||||
$this->table = Database::get_course_table('exercise_category');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of values stored in the table (all fields together)
|
||||
* for this type of resource.
|
||||
*
|
||||
* @param int $courseId
|
||||
*
|
||||
* @return int Number of rows in the table
|
||||
*/
|
||||
public function getCourseCount($courseId)
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$query = $em->getRepository('ChamiloCourseBundle:CExerciseCategory')->createQueryBuilder('e');
|
||||
$query->select('count(e.id)');
|
||||
$query->where('e.cId = :cId');
|
||||
$query->setParameter('cId', $courseId);
|
||||
|
||||
return $query->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategories($courseId)
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$query = $em->getRepository('ChamiloCourseBundle:CExerciseCategory')->createQueryBuilder('e');
|
||||
$query->where('e.cId = :cId');
|
||||
$query->setParameter('cId', $courseId);
|
||||
$query->orderBy('e.position');
|
||||
|
||||
return $query->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $courseId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoriesForSelect($courseId)
|
||||
{
|
||||
$categories = $this->getCategories($courseId);
|
||||
$options = [];
|
||||
|
||||
if (!empty($categories)) {
|
||||
/** @var CExerciseCategory $category */
|
||||
foreach ($categories as $category) {
|
||||
$options[$category->getId()] = $category->getName();
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$repo = Database::getManager()->getRepository('ChamiloCourseBundle:CExerciseCategory');
|
||||
$category = $repo->find($id);
|
||||
if ($category) {
|
||||
$em->remove($category);
|
||||
$em->flush();
|
||||
|
||||
$courseId = api_get_course_int_id();
|
||||
$table = Database::get_course_table(TABLE_QUIZ_TEST);
|
||||
$id = (int) $id;
|
||||
|
||||
$sql = "UPDATE $table SET exercise_category_id = 0
|
||||
WHERE c_id = $courseId AND exercise_category_id = $id";
|
||||
Database::query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save values in the *_field_values table.
|
||||
*
|
||||
* @param array $params Structured array with the values to save
|
||||
* @param bool $showQuery Whether to show the insert query (passed to the parent save() method)
|
||||
*/
|
||||
public function save($params, $showQuery = false)
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$category = new CExerciseCategory();
|
||||
$category
|
||||
->setName($params['name'])
|
||||
->setCId(api_get_course_int_id())
|
||||
->setDescription($params['name'])
|
||||
;
|
||||
/*
|
||||
// Update position
|
||||
$query = $em->getRepository('ChamiloCourseBundle:CExerciseCategory')->createQueryBuilder('e');
|
||||
$query
|
||||
->where('e.cId = :cId')
|
||||
->setParameter('cId', $courseId)
|
||||
->setMaxResults(1)
|
||||
->orderBy('e.position', 'DESC');
|
||||
$last = $query->getQuery()->getOneOrNullResult();
|
||||
$position = 0;
|
||||
if (!empty($last)) {
|
||||
$position = $last->getPosition() + 1;
|
||||
}
|
||||
$category->setPosition($position);
|
||||
*/
|
||||
$em->persist($category);
|
||||
$em->flush();
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJqgridActionLinks($token)
|
||||
{
|
||||
//With this function we can add actions to the jgrid (edit, delete, etc)
|
||||
$editIcon = Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL);
|
||||
$deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
|
||||
$confirmMessage = addslashes(
|
||||
api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES)
|
||||
);
|
||||
|
||||
$courseParams = api_get_cidreq();
|
||||
|
||||
$editButton = <<<JAVASCRIPT
|
||||
<a href="?action=edit&{$courseParams}&id=' + options.rowId + '" class="btn btn-link btn-xs">\
|
||||
$editIcon\
|
||||
</a>
|
||||
JAVASCRIPT;
|
||||
$deleteButton = <<<JAVASCRIPT
|
||||
<a \
|
||||
onclick="if (!confirm(\'$confirmMessage\')) {return false;}" \
|
||||
href="?sec_token=$token&{$courseParams}&id=' + options.rowId + '&action=delete" \
|
||||
class="btn btn-link btn-xs">\
|
||||
$deleteIcon\
|
||||
</a>
|
||||
JAVASCRIPT;
|
||||
|
||||
return "function action_formatter(cellvalue, options, rowObject) {
|
||||
return '$editButton $deleteButton';
|
||||
}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $action
|
||||
*
|
||||
* @return FormValidator
|
||||
*/
|
||||
public function return_form($url, $action)
|
||||
{
|
||||
$form = new FormValidator('category', 'post', $url);
|
||||
$id = isset($_GET['id']) ? (int) $_GET['id'] : null;
|
||||
$form->addElement('hidden', 'id', $id);
|
||||
|
||||
// Setting the form elements
|
||||
$header = get_lang('Add');
|
||||
$defaults = [];
|
||||
|
||||
if ($action === 'edit') {
|
||||
$header = get_lang('Modify');
|
||||
// Setting the defaults
|
||||
$defaults = $this->get($id, false);
|
||||
}
|
||||
|
||||
$form->addElement('header', $header);
|
||||
|
||||
$form->addText(
|
||||
'name',
|
||||
get_lang('Name')
|
||||
);
|
||||
|
||||
$form->addHtmlEditor('description', get_lang('Description'));
|
||||
|
||||
if ($action === 'edit') {
|
||||
$form->addButtonUpdate(get_lang('Modify'));
|
||||
} else {
|
||||
$form->addButtonCreate(get_lang('Add'));
|
||||
}
|
||||
|
||||
/*if (!empty($defaults['created_at'])) {
|
||||
$defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
|
||||
}
|
||||
if (!empty($defaults['updated_at'])) {
|
||||
$defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
|
||||
}*/
|
||||
$form->setDefaults($defaults);
|
||||
|
||||
// Setting the rules
|
||||
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
// action links
|
||||
$content = '<div class="actions">';
|
||||
$content .= '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq().'">';
|
||||
$content .= Display::return_icon(
|
||||
'back.png',
|
||||
get_lang('BackTo').' '.get_lang('PlatformAdmin'),
|
||||
'',
|
||||
ICON_SIZE_MEDIUM
|
||||
);
|
||||
$content .= '</a>';
|
||||
$content .= '<a href="'.api_get_self().'?action=add&'.api_get_cidreq().'">';
|
||||
$content .= Display::return_icon(
|
||||
'add.png',
|
||||
get_lang('Add'),
|
||||
'',
|
||||
ICON_SIZE_MEDIUM
|
||||
);
|
||||
$content .= '</a>';
|
||||
$content .= '</div>';
|
||||
$content .= Display::grid_html('categories');
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
231
main/inc/lib/GamificationUtils.php
Normal file
231
main/inc/lib/GamificationUtils.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* GamificationUtils class
|
||||
* Functions to manage the gamification mode.
|
||||
*
|
||||
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||
*/
|
||||
class GamificationUtils
|
||||
{
|
||||
/**
|
||||
* Get the calculated points on session with gamification mode.
|
||||
*
|
||||
* @param int $userId The user ID
|
||||
* @param int $userStatus The user Status
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function getTotalUserPoints($userId, $userStatus)
|
||||
{
|
||||
$points = 0;
|
||||
|
||||
$sessions = SessionManager::getSessionsFollowedByUser(
|
||||
$userId,
|
||||
$userStatus
|
||||
);
|
||||
|
||||
if (empty($sessions)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
$points += self::getSessionPoints($session['id'], $userId);
|
||||
}
|
||||
|
||||
return round($points / count($sessions), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the achieved points for an user in a session.
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param int $userId The user ID
|
||||
*
|
||||
* @return int The count of points
|
||||
*/
|
||||
public static function getSessionPoints($sessionId, $userId)
|
||||
{
|
||||
$totalPoints = 0;
|
||||
$courses = SessionManager::get_course_list_by_session_id($sessionId);
|
||||
|
||||
if (empty($courses)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$learnPathListObject = new LearnpathList(
|
||||
$userId,
|
||||
api_get_course_info($course['code']),
|
||||
$sessionId
|
||||
);
|
||||
$learnPaths = $learnPathListObject->get_flat_list();
|
||||
|
||||
if (empty($learnPaths)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$score = 0;
|
||||
|
||||
foreach ($learnPaths as $learnPathId => $learnPathInfo) {
|
||||
if (empty($learnPathInfo['seriousgame_mode'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$learnPath = new learnpath(
|
||||
$course['code'],
|
||||
$learnPathId,
|
||||
$userId
|
||||
);
|
||||
$score += $learnPath->getCalculateScore($sessionId);
|
||||
}
|
||||
$totalPoints += round($score / count($learnPaths), 2);
|
||||
}
|
||||
|
||||
return round($totalPoints / count($courses), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the calculated progress for an user in a session.
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param int $userId The user ID
|
||||
*
|
||||
* @return float The progress
|
||||
*/
|
||||
public static function getSessionProgress($sessionId, $userId)
|
||||
{
|
||||
$courses = SessionManager::get_course_list_by_session_id($sessionId);
|
||||
$progress = 0;
|
||||
|
||||
if (empty($courses)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$courseProgress = Tracking::get_avg_student_progress(
|
||||
$userId,
|
||||
$course['code'],
|
||||
[],
|
||||
$sessionId,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
if (false === $courseProgress) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$progress += $courseProgress;
|
||||
}
|
||||
|
||||
return round($progress / count($courses), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of stars achieved for an user in a session.
|
||||
*
|
||||
* @param int $sessionId The session ID
|
||||
* @param int $userId The user ID
|
||||
*
|
||||
* @return int The number of stars
|
||||
*/
|
||||
public static function getSessionStars($sessionId, $userId)
|
||||
{
|
||||
$totalStars = 0;
|
||||
$courses = SessionManager::get_course_list_by_session_id($sessionId);
|
||||
|
||||
if (empty($courses)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$learnPathListObject = new LearnpathList(
|
||||
$userId,
|
||||
api_get_course_info($course['code']),
|
||||
$sessionId
|
||||
);
|
||||
$learnPaths = $learnPathListObject->get_flat_list();
|
||||
|
||||
if (empty($learnPaths)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stars = 0;
|
||||
|
||||
foreach ($learnPaths as $learnPathId => $learnPathInfo) {
|
||||
if (empty($learnPathInfo['seriousgame_mode'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$learnPath = new learnpath(
|
||||
$course['code'],
|
||||
$learnPathId,
|
||||
$userId
|
||||
);
|
||||
|
||||
$stars += $learnPath->getCalculateStars($sessionId);
|
||||
}
|
||||
|
||||
$totalStars += round($stars / count($learnPaths));
|
||||
}
|
||||
|
||||
return round($totalStars / count($courses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stars on sessions with gamification mode.
|
||||
*
|
||||
* @param int $userId The user ID
|
||||
* @param int $userStatus The user Status
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getTotalUserStars($userId, $userStatus)
|
||||
{
|
||||
$stars = 0;
|
||||
$sessions = SessionManager::getSessionsFollowedByUser(
|
||||
$userId,
|
||||
$userStatus
|
||||
);
|
||||
|
||||
if (empty($sessions)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
$stars += self::getSessionStars($session['id'], $userId);
|
||||
}
|
||||
|
||||
return round($stars / count($sessions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total progress on sessions with gamification mode.
|
||||
*
|
||||
* @param int $userId The user ID
|
||||
* @param int $userStatus The user Status
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function getTotalUserProgress($userId, $userStatus)
|
||||
{
|
||||
$progress = 0;
|
||||
|
||||
$sessions = SessionManager::getSessionsFollowedByUser(
|
||||
$userId,
|
||||
$userStatus
|
||||
);
|
||||
|
||||
if (empty($sessions)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach ($sessions as $session) {
|
||||
$progress += self::getSessionProgress($session['id'], $userId);
|
||||
}
|
||||
|
||||
return round($progress / count($sessions), 2);
|
||||
}
|
||||
}
|
||||
237
main/inc/lib/MailTemplateManager.php
Normal file
237
main/inc/lib/MailTemplateManager.php
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Class MailTemplateManager.
|
||||
*/
|
||||
class MailTemplateManager extends Model
|
||||
{
|
||||
public $columns = [
|
||||
'id',
|
||||
'name',
|
||||
'template',
|
||||
'type',
|
||||
'system',
|
||||
'url_id',
|
||||
'default_template',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'author_id',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->table = 'mail_template';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_count()
|
||||
{
|
||||
$row = Database::select(
|
||||
'count(*) as count',
|
||||
$this->table,
|
||||
['where' => ['url_id = ? ' => api_get_current_access_url_id()]],
|
||||
'first'
|
||||
);
|
||||
|
||||
return $row['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the title + grid.
|
||||
*
|
||||
* @return string html code
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
// Action links
|
||||
$html = '<div class="actions" style="margin-bottom:20px">';
|
||||
$html .= '<a href="'.api_get_path(WEB_CODE_PATH).'admin">'.
|
||||
Display::return_icon(
|
||||
'back.png',
|
||||
get_lang('Back'),
|
||||
'',
|
||||
'32'
|
||||
)
|
||||
.'</a>';
|
||||
$html .= '<a href="'.api_get_self().'?action=add">'.
|
||||
Display::return_icon(
|
||||
'add.png',
|
||||
get_lang('Add'),
|
||||
'',
|
||||
'32'
|
||||
).'</a>';
|
||||
$html .= '</div>';
|
||||
$html .= Display::grid_html('mail_template');
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Form validator Obj.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $action
|
||||
*
|
||||
* @return FormValidator
|
||||
*/
|
||||
public function returnForm($url, $action = 'add')
|
||||
{
|
||||
$form = new FormValidator('template', 'post', $url);
|
||||
// Setting the form elements
|
||||
$header = get_lang('Add');
|
||||
if ($action === 'edit') {
|
||||
$header = get_lang('Modify');
|
||||
}
|
||||
$id = isset($_GET['id']) ? (int) $_GET['id'] : '';
|
||||
|
||||
$form->addElement('header', '', $header);
|
||||
$form->addElement('hidden', 'id', $id);
|
||||
$form->addElement(
|
||||
'text',
|
||||
'name',
|
||||
get_lang('Name'),
|
||||
['size' => '70', 'id' => 'name']
|
||||
);
|
||||
|
||||
/*$form->addHtmlEditor(
|
||||
'email_template',
|
||||
get_lang('Template'),
|
||||
false,
|
||||
false,
|
||||
[
|
||||
'ToolbarSet' => 'Careers',
|
||||
'Width' => '100%',
|
||||
'Height' => '250',
|
||||
]
|
||||
);*/
|
||||
$form->addTextarea(
|
||||
'email_template',
|
||||
get_lang('Template')
|
||||
);
|
||||
|
||||
$finder = new Finder();
|
||||
$files = $finder
|
||||
->files()
|
||||
->in(api_get_path(SYS_CODE_PATH).'template/default/mail')
|
||||
->sort(
|
||||
function ($a, $b) {
|
||||
return strcmp($a->getRealpath(), $b->getRealpath());
|
||||
}
|
||||
);
|
||||
|
||||
$options = [];
|
||||
/** @var SplFileInfo $file */
|
||||
foreach ($files as $file) {
|
||||
$options[$file->getFilename()] = $file->getFilename();
|
||||
}
|
||||
|
||||
$form->addSelect(
|
||||
'type',
|
||||
get_lang('Type'),
|
||||
$options
|
||||
);
|
||||
|
||||
$defaults = $this->get($id);
|
||||
|
||||
if ($action === 'edit') {
|
||||
$form->addLabel(get_lang('CreatedAt'), Display::dateToStringAgoAndLongDate($defaults['created_at']));
|
||||
$form->addLabel(get_lang('UpdatedAt'), Display::dateToStringAgoAndLongDate($defaults['updated_at']));
|
||||
$form->addButtonSave(get_lang('Modify'), 'submit');
|
||||
} else {
|
||||
$form->addButtonCreate(get_lang('Add'), 'submit');
|
||||
}
|
||||
|
||||
// Setting the defaults
|
||||
if (!empty($defaults)) {
|
||||
$defaults['email_template'] = $defaults['template'];
|
||||
}
|
||||
$form->setDefaults($defaults);
|
||||
|
||||
// Setting the rules
|
||||
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setDefault($id)
|
||||
{
|
||||
$template = $this->get($id);
|
||||
if (empty($template)) {
|
||||
return false;
|
||||
}
|
||||
$type = $template['type'];
|
||||
$urlId = api_get_current_access_url_id();
|
||||
$sql = "UPDATE {$this->table} SET default_template = 0
|
||||
WHERE type = '$type' AND url_id = $urlId";
|
||||
Database::query($sql);
|
||||
|
||||
$sql = "UPDATE {$this->table} SET default_template = 1
|
||||
WHERE id = $id";
|
||||
Database::query($sql);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $templateId
|
||||
* @param array $userInfo
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function parseTemplate($templateId, $userInfo)
|
||||
{
|
||||
$templateInfo = $this->get($templateId);
|
||||
if (!empty($templateInfo)) {
|
||||
$emailTemplate = nl2br($templateInfo['template']);
|
||||
|
||||
$keys = array_keys($userInfo);
|
||||
foreach ($keys as $key) {
|
||||
$emailTemplate = str_replace("{{user.$key}}", $userInfo[$key], $emailTemplate);
|
||||
}
|
||||
$template = new Template();
|
||||
$template->twig->setLoader(new \Twig_Loader_String());
|
||||
$emailBody = $template->twig->render($emailTemplate);
|
||||
|
||||
return $emailBody;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a custom mail template by the name of the template it replaces.
|
||||
*
|
||||
* @param string $templateType Name of the template file it replaces
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplateByType($templateType)
|
||||
{
|
||||
if (empty($templateType)) {
|
||||
return '';
|
||||
}
|
||||
$result = Database::select(
|
||||
'template',
|
||||
$this->table,
|
||||
['where' => ['type = ? ' => $templateType, ' AND url_id = ? ' => api_get_current_access_url_id()]],
|
||||
'first'
|
||||
);
|
||||
if (empty($result)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $result['template'];
|
||||
}
|
||||
}
|
||||
2880
main/inc/lib/MoodleImport.php
Normal file
2880
main/inc/lib/MoodleImport.php
Normal file
File diff suppressed because it is too large
Load Diff
101
main/inc/lib/MyStudents.php
Normal file
101
main/inc/lib/MyStudents.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class MyStudents
|
||||
{
|
||||
public static function userCareersTable(int $studentId): string
|
||||
{
|
||||
if (!api_get_configuration_value('allow_career_users')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$careers = UserManager::getUserCareers($studentId);
|
||||
|
||||
if (empty($careers)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$title = Display::page_subheader(get_lang('Careers'), null, 'h3', ['class' => 'section-title']);
|
||||
|
||||
return $title.self::getCareersTable($careers, $studentId);
|
||||
}
|
||||
|
||||
public static function getCareersTable(array $careers, int $studentId): string
|
||||
{
|
||||
if (empty($careers)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$webCodePath = api_get_path(WEB_CODE_PATH);
|
||||
$iconDiagram = Display::return_icon('multiplicate_survey.png', get_lang('Diagram'));
|
||||
$careerModel = new Career();
|
||||
|
||||
$headers = [
|
||||
get_lang('Career'),
|
||||
get_lang('Diagram'),
|
||||
];
|
||||
|
||||
$data = array_map(
|
||||
function (array $careerInfo) use ($careerModel, $webCodePath, $iconDiagram, $studentId) {
|
||||
$careerId = $careerInfo['id'];
|
||||
if (api_get_configuration_value('use_career_external_id_as_identifier_in_diagrams')) {
|
||||
$careerId = $careerModel->getCareerIdFromInternalToExternal($careerId);
|
||||
}
|
||||
|
||||
$url = $webCodePath.'user/career_diagram.php?career_id='.$careerId.'&user_id='.$studentId;
|
||||
|
||||
return [
|
||||
$careerInfo['name'],
|
||||
Display::url($iconDiagram, $url),
|
||||
];
|
||||
},
|
||||
$careers
|
||||
);
|
||||
|
||||
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
|
||||
$table->setHeaders($headers);
|
||||
$table->setData($data);
|
||||
|
||||
return $table->toHtml();
|
||||
}
|
||||
|
||||
public static function getBlockForSkills(int $studentId, int $courseId, int $sessionId): string
|
||||
{
|
||||
$allowAll = api_get_configuration_value('allow_teacher_access_student_skills');
|
||||
|
||||
if ($allowAll) {
|
||||
return Tracking::displayUserSkills($studentId, 0, 0, true);
|
||||
}
|
||||
|
||||
// Default behaviour - Show all skills depending the course and session id
|
||||
return Tracking::displayUserSkills($studentId, $courseId, $sessionId);
|
||||
}
|
||||
|
||||
public static function getBlockForClasses($studentId): ?string
|
||||
{
|
||||
$userGroupManager = new UserGroup();
|
||||
$userGroups = $userGroupManager->getNameListByUser(
|
||||
$studentId,
|
||||
UserGroup::NORMAL_CLASS
|
||||
);
|
||||
|
||||
if (empty($userGroups)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$headers = [get_lang('Classes')];
|
||||
$data = array_map(
|
||||
function ($class) {
|
||||
return [$class];
|
||||
},
|
||||
$userGroups
|
||||
);
|
||||
|
||||
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
|
||||
$table->setHeaders($headers);
|
||||
$table->setData($data);
|
||||
|
||||
return $table->toHtml();
|
||||
}
|
||||
}
|
||||
452
main/inc/lib/NotificationEvent.php
Normal file
452
main/inc/lib/NotificationEvent.php
Normal file
@@ -0,0 +1,452 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
class NotificationEvent extends Model
|
||||
{
|
||||
public const ACCOUNT_EXPIRATION = 1;
|
||||
public const JUSTIFICATION_EXPIRATION = 2;
|
||||
public const GLOBAL_NOTIFICATION = 3;
|
||||
public const SPECIFIC_USER = 4;
|
||||
|
||||
public $table;
|
||||
public $columns = [
|
||||
'id',
|
||||
'title',
|
||||
'content',
|
||||
'link',
|
||||
'persistent',
|
||||
'day_diff',
|
||||
'event_type',
|
||||
'event_id',
|
||||
];
|
||||
public $extraFieldName;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->table = 'notification_event';
|
||||
$this->extraFieldName = 'notification_event';
|
||||
}
|
||||
|
||||
public function eventTypeToString($eventTypeId)
|
||||
{
|
||||
$list = $this->getEventsForSelect(false);
|
||||
|
||||
return $list[$eventTypeId];
|
||||
}
|
||||
|
||||
public function getEventsForSelect($onlyEnabled = true): array
|
||||
{
|
||||
$eventTypes = [
|
||||
self::ACCOUNT_EXPIRATION => get_lang('AccountExpiration'),
|
||||
self::GLOBAL_NOTIFICATION => get_lang('Global'),
|
||||
self::SPECIFIC_USER => get_lang('SpecificUsers'),
|
||||
];
|
||||
|
||||
if (!$onlyEnabled || api_get_plugin_setting('justification', 'tool_enable') === 'true') {
|
||||
$eventTypes[self::JUSTIFICATION_EXPIRATION] = get_lang('JustificationExpiration');
|
||||
}
|
||||
|
||||
return $eventTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getForm(FormValidator $form, $data = []): FormValidator
|
||||
{
|
||||
$options = $this->getEventsForSelect();
|
||||
$form->addSelect('event_type', get_lang('EventType'), $options);
|
||||
$form->freeze('event_type');
|
||||
|
||||
$eventType = $data['event_type'];
|
||||
switch ($eventType) {
|
||||
case self::JUSTIFICATION_EXPIRATION:
|
||||
$list = [];
|
||||
if (api_get_plugin_setting('justification', 'tool_enable') === 'true'
|
||||
&& $list = Justification::create()->getList()
|
||||
) {
|
||||
$list = array_column($list, 'name', 'id');
|
||||
}
|
||||
$form->addSelect('event_id', get_lang('JustificationType'), $list);
|
||||
$form->freeze('event_id');
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$form->addText('title', get_lang('Title'));
|
||||
$form->addTextarea('content', get_lang('Content'));
|
||||
$form->addText('link', get_lang('Link'), false);
|
||||
$form->addCheckBox('persistent', get_lang('Persistent'));
|
||||
$form->addNumeric('day_diff', get_lang('DaysDifference'), false);
|
||||
|
||||
switch ($eventType) {
|
||||
case self::SPECIFIC_USER:
|
||||
$form->addSelectAjax(
|
||||
'users',
|
||||
get_lang('Users'),
|
||||
$data['users'] ?? [],
|
||||
[
|
||||
'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like',
|
||||
'multiple' => 'multiple',
|
||||
]
|
||||
);
|
||||
//no break
|
||||
case self::GLOBAL_NOTIFICATION:
|
||||
$form->removeElement('day_diff');
|
||||
break;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAddForm(FormValidator $form): FormValidator
|
||||
{
|
||||
$options = $this->getEventsForSelect();
|
||||
$eventType = $form->getSubmitValue('event_type');
|
||||
|
||||
$form->addSelect(
|
||||
'event_type',
|
||||
get_lang('EventType'),
|
||||
$options,
|
||||
['placeholder' => get_lang('SelectAnOption'), 'onchange' => 'document.add.submit()']
|
||||
);
|
||||
|
||||
if (!empty($eventType)) {
|
||||
$form->freeze('event_type');
|
||||
$form->addText('title', get_lang('Title'));
|
||||
$form->addTextarea('content', get_lang('Content'));
|
||||
$form->addText('link', get_lang('Link'), false);
|
||||
$form->addCheckBox('persistent', get_lang('Persistent'));
|
||||
$form->addNumeric('day_diff', get_lang('DaysDifference'), false);
|
||||
|
||||
switch ($eventType) {
|
||||
case self::JUSTIFICATION_EXPIRATION:
|
||||
$list = [];
|
||||
if (api_get_plugin_setting('justification', 'tool_enable') === 'true'
|
||||
&& $list = Justification::create()->getList()
|
||||
) {
|
||||
$list = array_column($list, 'name', 'id');
|
||||
}
|
||||
$form->addSelect('event_id', get_lang('JustificationType'), $list);
|
||||
break;
|
||||
case self::SPECIFIC_USER:
|
||||
$form->addSelectAjax(
|
||||
'users',
|
||||
get_lang('Users'),
|
||||
[],
|
||||
[
|
||||
'url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like',
|
||||
'multiple' => 'multiple',
|
||||
]
|
||||
);
|
||||
//no break
|
||||
case self::GLOBAL_NOTIFICATION:
|
||||
$form->removeElement('day_diff');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$form->addButtonSave(get_lang('Save'));
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function getUserExtraData($userId)
|
||||
{
|
||||
$data = UserManager::get_extra_user_data_by_field($userId, $this->extraFieldName);
|
||||
|
||||
return $data['notification_event'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getNotificationsByUser(int $userId): array
|
||||
{
|
||||
$userInfo = api_get_user_info($userId);
|
||||
$events = $this->get_all();
|
||||
$extraFieldData = $this->getUserExtraData($userId);
|
||||
|
||||
$notifications = [];
|
||||
foreach ($events as $event) {
|
||||
$days = (int) $event['day_diff'];
|
||||
$checkIsRead = $event['persistent'] == 0;
|
||||
$eventItemId = $event['event_id'];
|
||||
|
||||
switch ($event['event_type']) {
|
||||
case self::ACCOUNT_EXPIRATION:
|
||||
if (empty($userInfo['expiration_date'])) {
|
||||
break;
|
||||
}
|
||||
|
||||
$id = 'id_'.self::ACCOUNT_EXPIRATION.'_event_'.$event['id'].'_'.$userInfo['id'];
|
||||
|
||||
$read = false;
|
||||
if ($checkIsRead) {
|
||||
$read = $this->isRead($id, $extraFieldData);
|
||||
}
|
||||
|
||||
$showNotification = $this->showNotification($userInfo['expiration_date'], $days);
|
||||
if ($showNotification && $read === false) {
|
||||
$notifications[] = [
|
||||
'id' => $id,
|
||||
'title' => $event['title'],
|
||||
'content' => $event['content'],
|
||||
'event_text' => get_lang('ExpirationDate').': '.api_get_local_time($userInfo['expiration_date']),
|
||||
'link' => $event['link'],
|
||||
'persistent' => $event['persistent'],
|
||||
];
|
||||
}
|
||||
break;
|
||||
case self::JUSTIFICATION_EXPIRATION:
|
||||
if (api_get_plugin_setting('justification', 'tool_enable') !== 'true') {
|
||||
break;
|
||||
}
|
||||
|
||||
$plugin = Justification::create();
|
||||
$userJustificationList = $plugin->getUserJustificationList($userId);
|
||||
|
||||
foreach ($userJustificationList as $userJustification) {
|
||||
if (empty($userJustification['date_validity'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($eventItemId != $userJustification['justification_document_id']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$showNotification = $this->showNotification($userJustification['date_validity'], $days);
|
||||
|
||||
$id = 'id_'.self::JUSTIFICATION_EXPIRATION.'_event_'.$event['id'].'_'.$userJustification['id'];
|
||||
|
||||
$fieldData = $plugin->getJustification($userJustification['justification_document_id']);
|
||||
|
||||
$read = false;
|
||||
if ($checkIsRead) {
|
||||
$read = $this->isRead($id, $extraFieldData);
|
||||
}
|
||||
|
||||
$eventText = $plugin->get_lang('Justification').': '.$fieldData['name'].' <br />';
|
||||
$eventText .= $plugin->get_lang('JustificationDate').': '.$userJustification['date_validity'];
|
||||
|
||||
$url = $event['link'];
|
||||
if (empty($url)) {
|
||||
$url = api_get_path(WEB_CODE_PATH).'auth/justification.php#'.$fieldData['code'];
|
||||
}
|
||||
|
||||
if ($showNotification && $read === false) {
|
||||
$notifications[] = [
|
||||
'id' => $id,
|
||||
'title' => $event['title'],
|
||||
'content' => $event['content'],
|
||||
'event_text' => $eventText,
|
||||
'link' => $url,
|
||||
'persistent' => $event['persistent'],
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case self::SPECIFIC_USER:
|
||||
$assignedUsers = self::getAssignedUsers($event['id']);
|
||||
$assignedUserIdList = array_keys($assignedUsers);
|
||||
|
||||
if (!in_array($userId, $assignedUserIdList)) {
|
||||
break;
|
||||
}
|
||||
//no break
|
||||
case self::GLOBAL_NOTIFICATION:
|
||||
$id = "id_{$event['event_type']}_event_{$event['id']}_$userId";
|
||||
|
||||
$wasRead = $checkIsRead && $this->isRead($id, $extraFieldData);
|
||||
|
||||
if (!$wasRead) {
|
||||
$notifications[] = [
|
||||
'id' => $id,
|
||||
'title' => $event['title'],
|
||||
'content' => $event['content'],
|
||||
'event_text' => null,
|
||||
'link' => $event['link'],
|
||||
'persistent' => $event['persistent'],
|
||||
];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $notifications;
|
||||
}
|
||||
|
||||
public function isRead($id, $extraData): bool
|
||||
{
|
||||
$userId = api_get_user_id();
|
||||
|
||||
if (empty($extraData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = $this->getUserExtraData($userId);
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = json_decode($data);
|
||||
|
||||
if (in_array($id, $data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function markAsRead($id): bool
|
||||
{
|
||||
if (empty($id)) {
|
||||
return false;
|
||||
}
|
||||
$userId = api_get_user_id();
|
||||
$data = $this->getUserExtraData($userId);
|
||||
if (!empty($data)) {
|
||||
$data = json_decode($data);
|
||||
} else {
|
||||
$data = [];
|
||||
}
|
||||
$data[] = $id;
|
||||
$data = json_encode($data);
|
||||
|
||||
UserManager::update_extra_field_value($userId, $this->extraFieldName, $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function showNotification($date, $dayDiff): bool
|
||||
{
|
||||
$today = api_get_utc_datetime();
|
||||
$expiration = api_get_utc_datetime($date, false, true);
|
||||
$interval = new DateInterval('P'.$dayDiff.'D');
|
||||
$diff = $expiration->sub($interval);
|
||||
|
||||
if ($diff->format('Y-m-d H:i:s') < $today) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
$sql = "CREATE TABLE IF NOT EXISTS notification_event (
|
||||
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
|
||||
title VARCHAR(255),
|
||||
content TEXT,
|
||||
link TEXT,
|
||||
persistent INT,
|
||||
day_diff INT,
|
||||
event_type VARCHAR(255)
|
||||
)";
|
||||
Database::query($sql);
|
||||
}
|
||||
|
||||
public function save($params, $show_query = false)
|
||||
{
|
||||
$userIdList = [];
|
||||
|
||||
if (isset($params['users'])) {
|
||||
$userIdList = $params['users'];
|
||||
unset($params['users']);
|
||||
}
|
||||
|
||||
/** @var int|bool $saved */
|
||||
$saved = parent::save($params, $show_query);
|
||||
|
||||
if (false !== $saved && !empty($userIdList)) {
|
||||
self::assignUserIdList($saved, $userIdList);
|
||||
}
|
||||
|
||||
return $saved;
|
||||
}
|
||||
|
||||
public function update($params, $showQuery = false): bool
|
||||
{
|
||||
$userIdList = [];
|
||||
|
||||
if (isset($params['users'])) {
|
||||
$userIdList = $params['users'];
|
||||
unset($params['users']);
|
||||
}
|
||||
|
||||
$updated = parent::update($params, $showQuery);
|
||||
|
||||
self::deleteAssignedUsers($params['id']);
|
||||
self::assignUserIdList($params['id'], $userIdList);
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
$props = parent::get($id);
|
||||
$props['users'] = self::getAssignedUsers($id);
|
||||
|
||||
return $props;
|
||||
}
|
||||
|
||||
public static function assignUserIdList(int $eventId, array $userIdList)
|
||||
{
|
||||
foreach ($userIdList as $userId) {
|
||||
Database::insert(
|
||||
'notification_event_rel_user',
|
||||
[
|
||||
'event_id' => $eventId,
|
||||
'user_id' => (int) $userId,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getAssignedUsers(int $eventId): array
|
||||
{
|
||||
$tblUser = Database::get_main_table(TABLE_MAIN_USER);
|
||||
|
||||
$result = Database::select(
|
||||
'u.id, u.username, u.firstname, u.lastname',
|
||||
"notification_event_rel_user neru INNER JOIN $tblUser u ON neru.user_id = u.id",
|
||||
['where' => ['neru.event_id = ?' => $eventId]]
|
||||
);
|
||||
|
||||
$userList = [];
|
||||
|
||||
foreach ($result as $userInfo) {
|
||||
$userList[$userInfo['id']] = api_get_person_name(
|
||||
$userInfo['firstname'],
|
||||
$userInfo['lastname'],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$userInfo['username']
|
||||
);
|
||||
}
|
||||
|
||||
return $userList;
|
||||
}
|
||||
|
||||
public static function deleteAssignedUsers(int $eventId)
|
||||
{
|
||||
Database::delete(
|
||||
'notification_event_rel_user',
|
||||
['event_id = ?' => $eventId]
|
||||
);
|
||||
}
|
||||
}
|
||||
4495
main/inc/lib/PortfolioController.php
Normal file
4495
main/inc/lib/PortfolioController.php
Normal file
File diff suppressed because it is too large
Load Diff
102
main/inc/lib/PortfolioNotifier.php
Normal file
102
main/inc/lib/PortfolioNotifier.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Entity\Course as CourseEntity;
|
||||
use Chamilo\CoreBundle\Entity\PortfolioComment;
|
||||
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
|
||||
|
||||
class PortfolioNotifier
|
||||
{
|
||||
public static function notifyTeachersAndAuthor(PortfolioComment $comment)
|
||||
{
|
||||
$item = $comment->getItem();
|
||||
$course = $item->getCourse();
|
||||
$session = $item->getSession();
|
||||
|
||||
$messageSubject = sprintf(
|
||||
get_lang('PortfolioAlertNewCommentSubject'),
|
||||
$item->getTitle(true)
|
||||
);
|
||||
$userIdListToSend = [];
|
||||
$userIdListToSend[] = $comment->getItem()->getUser()->getId();
|
||||
|
||||
$cidreq = api_get_cidreq_params(
|
||||
$course ? $course->getCode() : '',
|
||||
$session ? $session->getId() : 0
|
||||
);
|
||||
$commentUrl = api_get_path(WEB_CODE_PATH).'portfolio/index.php?'
|
||||
.($course ? $cidreq.'&' : '')
|
||||
.http_build_query(['action' => 'view', 'id' => $item->getId()])."#comment-{$comment->getId()}";
|
||||
|
||||
if ($course) {
|
||||
$courseInfo = api_get_course_info($course->getCode());
|
||||
|
||||
if (1 !== (int) api_get_course_setting('email_alert_teachers_student_new_comment', $courseInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$courseTitle = self::getCourseTitle($course, $session);
|
||||
$userIdListToSend = array_merge(
|
||||
$userIdListToSend,
|
||||
self::getTeacherList($course, $session)
|
||||
);
|
||||
|
||||
$messageContent = sprintf(
|
||||
get_lang('CoursePortfolioAlertNewCommentContent'),
|
||||
$item->getTitle(),
|
||||
$courseTitle,
|
||||
$commentUrl
|
||||
);
|
||||
} else {
|
||||
$messageContent = sprintf(
|
||||
get_lang('PortfolioAlertNewCommentContent'),
|
||||
$item->getTitle(),
|
||||
$commentUrl
|
||||
);
|
||||
}
|
||||
|
||||
$messageContent .= '<br><br><figure>'
|
||||
.'<blockquote>'.$comment->getExcerpt().'</blockquote>'
|
||||
.'<figcaption>'.$comment->getAuthor()->getCompleteName().'</figcaption>'
|
||||
.'</figure>';
|
||||
|
||||
foreach ($userIdListToSend as $userIdToSend) {
|
||||
MessageManager::send_message_simple(
|
||||
$userIdToSend,
|
||||
$messageSubject,
|
||||
$messageContent,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
[],
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static function getCourseTitle(CourseEntity $course, ?SessionEntity $session = null): string
|
||||
{
|
||||
if ($session) {
|
||||
return "{$course->getTitle()} ({$session->getName()})";
|
||||
}
|
||||
|
||||
return $course->getTitle();
|
||||
}
|
||||
|
||||
private static function getTeacherList(CourseEntity $course, ?SessionEntity $session = null): array
|
||||
{
|
||||
if ($session) {
|
||||
$teachers = SessionManager::getCoachesByCourseSession(
|
||||
$session->getId(),
|
||||
$course->getId()
|
||||
);
|
||||
|
||||
return array_values($teachers);
|
||||
}
|
||||
|
||||
$teachers = CourseManager::get_teacher_list_from_course_code($course->getCode());
|
||||
|
||||
return array_keys($teachers);
|
||||
}
|
||||
}
|
||||
612
main/inc/lib/ScheduledAnnouncement.php
Normal file
612
main/inc/lib/ScheduledAnnouncement.php
Normal file
@@ -0,0 +1,612 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class ScheduledAnnouncement
|
||||
* Requires DB change:.
|
||||
*
|
||||
* CREATE TABLE scheduled_announcements (id INT AUTO_INCREMENT NOT NULL, subject VARCHAR(255) NOT NULL, message LONGTEXT NOT NULL, date DATETIME DEFAULT NULL, sent TINYINT(1) NOT NULL, session_id INT NOT NULL, c_id INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
|
||||
*
|
||||
* Config setting:
|
||||
* $_configuration['allow_scheduled_announcements'] = true;
|
||||
*
|
||||
* Setup linux cron file:
|
||||
* main/cron/scheduled_announcement.php
|
||||
*
|
||||
* Requires:
|
||||
* composer update
|
||||
*/
|
||||
class ScheduledAnnouncement extends Model
|
||||
{
|
||||
public $table;
|
||||
public $columns = ['id', 'subject', 'message', 'date', 'sent', 'session_id'];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->table = 'scheduled_announcements';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $where_conditions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all($where_conditions = [])
|
||||
{
|
||||
return Database::select(
|
||||
'*',
|
||||
$this->table,
|
||||
['where' => $where_conditions, 'order' => 'subject ASC']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_count()
|
||||
{
|
||||
$row = Database::select(
|
||||
'count(*) as count',
|
||||
$this->table,
|
||||
[],
|
||||
'first'
|
||||
);
|
||||
|
||||
return $row['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the title + grid.
|
||||
*
|
||||
* @param int $sessionId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGrid($sessionId)
|
||||
{
|
||||
// action links
|
||||
$action = '<div class="actions" style="margin-bottom:20px">';
|
||||
$action .= Display::url(
|
||||
Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM),
|
||||
api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$sessionId
|
||||
);
|
||||
|
||||
$action .= '<a href="'.api_get_self().'?action=add&session_id='.$sessionId.'">'.
|
||||
Display::return_icon('add.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
|
||||
$action .= '<a href="scheduled_announcement.php?action=run&session_id='.$sessionId.'">'.
|
||||
Display::return_icon('tuning.png', get_lang('SendManuallyPendingAnnouncements'), '', ICON_SIZE_MEDIUM).
|
||||
'</a>';
|
||||
|
||||
$action .= '</div>';
|
||||
|
||||
$html = $action;
|
||||
$html .= '<div id="session-table" class="table-responsive">';
|
||||
$html .= Display::grid_html('programmed');
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Form validator Obj.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $url
|
||||
* @param string $action add, edit
|
||||
* @param array $sessionInfo
|
||||
*
|
||||
* @return FormValidator form validator obj
|
||||
*/
|
||||
public function returnSimpleForm($id, $url, $action, $sessionInfo = [])
|
||||
{
|
||||
$form = new FormValidator(
|
||||
'announcement',
|
||||
'post',
|
||||
$url
|
||||
);
|
||||
|
||||
$form->addHidden('session_id', $sessionInfo['id']);
|
||||
$form->addDateTimePicker('date', get_lang('Date'));
|
||||
|
||||
$useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
|
||||
if ($useBaseProgress) {
|
||||
$extraFieldValue = new ExtraFieldValue('scheduled_announcement');
|
||||
$baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$id,
|
||||
'use_base_progress'
|
||||
);
|
||||
$form->addNumeric('progress',
|
||||
get_lang('Progress'),
|
||||
[
|
||||
'step' => 1,
|
||||
'min' => 1,
|
||||
'max' => 100,
|
||||
'value' => $baseProgress['value'],
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$form->addText('subject', get_lang('Subject'));
|
||||
$form->addHtmlEditor('message', get_lang('Message'));
|
||||
|
||||
$extraField = new ExtraField('scheduled_announcement');
|
||||
$extra = $extraField->addElements($form, $id);
|
||||
$js = $extra['jquery_ready_content'];
|
||||
$form->addHtml("<script> $(function() { $js }); </script> ");
|
||||
|
||||
$this->setTagsInForm($form);
|
||||
|
||||
$form->addCheckBox('sent', null, get_lang('MessageSent'));
|
||||
|
||||
if ('edit' === $action) {
|
||||
$form->addButtonUpdate(get_lang('Modify'));
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Form validator Obj.
|
||||
*
|
||||
* @todo the form should be auto generated
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $action add, edit
|
||||
* @param array
|
||||
*
|
||||
* @return FormValidator form validator obj
|
||||
*/
|
||||
public function returnForm($url, $action, $sessionInfo = [])
|
||||
{
|
||||
// Setting the form elements
|
||||
$header = get_lang('Add');
|
||||
|
||||
if ('edit' === $action) {
|
||||
$header = get_lang('Modify');
|
||||
}
|
||||
|
||||
$form = new FormValidator(
|
||||
'announcement',
|
||||
'post',
|
||||
$url
|
||||
);
|
||||
|
||||
$form->addHeader($header);
|
||||
if ('add' === $action) {
|
||||
$form->addHtml(
|
||||
Display::return_message(
|
||||
nl2br(get_lang('ScheduleAnnouncementDescription')),
|
||||
'normal',
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
$form->addHidden('session_id', $sessionInfo['id']);
|
||||
|
||||
$useBaseDate = false;
|
||||
$startDate = $sessionInfo['access_start_date'];
|
||||
$endDate = $sessionInfo['access_end_date'];
|
||||
|
||||
if (!empty($startDate) || !empty($endDate)) {
|
||||
$useBaseDate = true;
|
||||
}
|
||||
|
||||
$typeOptions = [
|
||||
'specific_date' => get_lang('SpecificDate'),
|
||||
];
|
||||
|
||||
if ($useBaseDate) {
|
||||
$typeOptions['base_date'] = get_lang('BaseDate');
|
||||
}
|
||||
|
||||
$useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
|
||||
if ($useBaseProgress) {
|
||||
$typeOptions['base_progress'] = get_lang('Progress');
|
||||
}
|
||||
|
||||
$form->addSelect(
|
||||
'type',
|
||||
get_lang('Type'),
|
||||
$typeOptions,
|
||||
[
|
||||
'onchange' => "javascript:
|
||||
if (this.options[this.selectedIndex].value == 'base_date') {
|
||||
document.getElementById('options').style.display = 'block';
|
||||
document.getElementById('specific_date').style.display = 'none';
|
||||
document.getElementById('base_progress').style.display = 'none';
|
||||
} else if (this.options[this.selectedIndex].value == 'specific_date') {
|
||||
document.getElementById('options').style.display = 'none';
|
||||
document.getElementById('specific_date').style.display = 'block';
|
||||
document.getElementById('base_progress').style.display = 'none';
|
||||
} else {
|
||||
document.getElementById('options').style.display = 'block';
|
||||
document.getElementById('specific_date').style.display = 'none';
|
||||
document.getElementById('base_progress').style.display = 'block';
|
||||
}
|
||||
", ]
|
||||
);
|
||||
|
||||
$form->addHtml('<div id="specific_date">');
|
||||
$form->addDateTimePicker('date', get_lang('Date'));
|
||||
$form->addHtml('</div>');
|
||||
|
||||
$form->addHtml('<div id="base_progress" style="display:none">');
|
||||
$form->addNumeric('progress',
|
||||
get_lang('Progress'),
|
||||
[
|
||||
'step' => 1,
|
||||
'min' => 1,
|
||||
'max' => 100,
|
||||
'value' => 100,
|
||||
],
|
||||
true
|
||||
);
|
||||
$form->addHtml('</div>');
|
||||
|
||||
$form->addHtml('<div id="options" style="display:none">');
|
||||
|
||||
$startDate = $sessionInfo['access_start_date'];
|
||||
$endDate = $sessionInfo['access_end_date'];
|
||||
|
||||
$form->addText(
|
||||
'days',
|
||||
get_lang('Days'),
|
||||
false
|
||||
);
|
||||
|
||||
$form->addSelect(
|
||||
'moment_type',
|
||||
get_lang('AfterOrBefore'),
|
||||
[
|
||||
'after' => get_lang('After'),
|
||||
'before' => get_lang('Before'),
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($startDate)) {
|
||||
$options['start_date'] = get_lang('StartDate').' - '.$startDate;
|
||||
}
|
||||
|
||||
if (!empty($endDate)) {
|
||||
$options['end_date'] = get_lang('EndDate').' - '.$endDate;
|
||||
}
|
||||
if (!empty($options)) {
|
||||
$form->addSelect('base_date', get_lang('BaseDate'), $options);
|
||||
}
|
||||
|
||||
$form->addHtml('</div>');
|
||||
$form->addText('subject', get_lang('Subject'));
|
||||
$form->addHtmlEditor('message', get_lang('Message'));
|
||||
|
||||
$extraField = new ExtraField('scheduled_announcement');
|
||||
$extra = $extraField->addElements($form);
|
||||
$js = $extra['jquery_ready_content'];
|
||||
$form->addHtml("<script> $(function() { $js }); </script> ");
|
||||
|
||||
$this->setTagsInForm($form);
|
||||
|
||||
if ('edit' === $action) {
|
||||
$form->addButtonUpdate(get_lang('Modify'));
|
||||
} else {
|
||||
$form->addButtonCreate(get_lang('Add'));
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAttachmentToString($id)
|
||||
{
|
||||
$file = $this->getAttachment($id);
|
||||
if (!empty($file) && !empty($file['value'])) {
|
||||
$url = api_get_path(WEB_UPLOAD_PATH).$file['value'];
|
||||
|
||||
return get_lang('Attachment').': '.Display::url(basename($file['value']), $url, ['target' => '_blank']);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAttachment($id)
|
||||
{
|
||||
$extraFieldValue = new ExtraFieldValue('scheduled_announcement');
|
||||
$attachment = $extraFieldValue->get_values_by_handler_and_field_variable($id, 'attachment');
|
||||
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $urlId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function sendPendingMessages($urlId = 0)
|
||||
{
|
||||
if (!$this->allowed()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$messagesSent = 0;
|
||||
$now = api_get_utc_datetime();
|
||||
$result = $this->get_all();
|
||||
$extraFieldValue = new ExtraFieldValue('scheduled_announcement');
|
||||
|
||||
// get user extra fields list (only visible to self and filter-able)
|
||||
$extraField = new ExtraField('user');
|
||||
$extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
|
||||
|
||||
foreach ($result as $result) {
|
||||
if (empty($result['sent'])) {
|
||||
if (!empty($result['date']) && $result['date'] < $now) {
|
||||
$sessionId = $result['session_id'];
|
||||
$sessionInfo = api_get_session_info($sessionId);
|
||||
if (empty($sessionInfo)) {
|
||||
continue;
|
||||
}
|
||||
$users = SessionManager::get_users_by_session(
|
||||
$sessionId,
|
||||
0,
|
||||
false,
|
||||
$urlId
|
||||
);
|
||||
|
||||
$coachId = $sessionInfo['id_coach'];
|
||||
|
||||
if (empty($users) || empty($coachId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$coachList = [];
|
||||
if ($users) {
|
||||
$sendToCoaches = $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$result['id'],
|
||||
'send_to_coaches'
|
||||
);
|
||||
$courseList = SessionManager::getCoursesInSession($sessionId);
|
||||
if (!empty($sendToCoaches) && !empty($sendToCoaches['value']) && 1 == $sendToCoaches['value']) {
|
||||
foreach ($courseList as $courseItemId) {
|
||||
$coaches = SessionManager::getCoachesByCourseSession(
|
||||
$sessionId,
|
||||
$courseItemId
|
||||
);
|
||||
$coachList = array_merge($coachList, $coaches);
|
||||
}
|
||||
$coachList = array_unique($coachList);
|
||||
}
|
||||
|
||||
$useBaseProgress = api_get_configuration_value('scheduled_announcements_use_base_progress');
|
||||
if ($useBaseProgress) {
|
||||
$baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$result['id'],
|
||||
'use_base_progress'
|
||||
);
|
||||
if (empty($baseProgress) || empty($baseProgress['value']) || $baseProgress['value'] < 1) {
|
||||
$this->update(['id' => $result['id'], 'sent' => 1]);
|
||||
}
|
||||
} else {
|
||||
$this->update(['id' => $result['id'], 'sent' => 1]);
|
||||
}
|
||||
|
||||
$attachments = $this->getAttachmentToString($result['id']);
|
||||
$subject = $result['subject'];
|
||||
|
||||
$courseInfo = [];
|
||||
if (!empty($courseList)) {
|
||||
$courseId = current($courseList);
|
||||
$courseInfo = api_get_course_info_by_id($courseId);
|
||||
}
|
||||
|
||||
$message = '';
|
||||
foreach ($users as $user) {
|
||||
// Take original message
|
||||
$message = $result['message'];
|
||||
$userInfo = api_get_user_info($user['user_id']);
|
||||
$userPicture = UserManager::getUserPicture($user['user_id'], USER_IMAGE_SIZE_ORIGINAL);
|
||||
|
||||
$progress = '';
|
||||
if (!empty($sessionInfo) && !empty($courseInfo)) {
|
||||
$progress = Tracking::get_avg_student_progress(
|
||||
$user['user_id'],
|
||||
$courseInfo['code'],
|
||||
[],
|
||||
$sessionId
|
||||
);
|
||||
}
|
||||
|
||||
if ($useBaseProgress) {
|
||||
$baseProgress = $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$result['id'],
|
||||
'use_base_progress'
|
||||
);
|
||||
if (!empty($baseProgress) && !empty($baseProgress['value']) && $baseProgress['value'] >= 1) {
|
||||
if ((is_numeric($progress) && $progress > $baseProgress['value']) || !is_numeric($progress)) {
|
||||
continue;
|
||||
} else {
|
||||
$comment = json_decode($baseProgress['comment'], true);
|
||||
if ($comment !== null && is_array($comment)) {
|
||||
if (isset($comment['sended']) && is_array($comment['sended'])) {
|
||||
$userFound = false;
|
||||
foreach ($comment['sended'] as $item) {
|
||||
if (isset($item['user']) && $item['user'] === $user['user_id']) {
|
||||
$userFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($userFound) {
|
||||
continue;
|
||||
} else {
|
||||
$comment['sended'][] = ['user' => $user['user_id'], 'send_date' => time(), 'progress_user' => $progress, 'progress_mark' => $baseProgress['value']];
|
||||
$newExtraFieldParams = $baseProgress;
|
||||
$newExtraFieldParams['comment'] = json_encode($comment);
|
||||
$extraFieldValue->save($newExtraFieldParams);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$comment['sended'][] = ['user' => $user['user_id'], 'send_date' => time(), 'progress_user' => $progress, 'progress_mark' => $baseProgress['value']];
|
||||
$newExtraFieldParams = $baseProgress;
|
||||
$newExtraFieldParams['comment'] = json_encode($comment);
|
||||
$extraFieldValue->save($newExtraFieldParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_numeric($progress)) {
|
||||
$progress = $progress.'%';
|
||||
} else {
|
||||
$progress = '0%';
|
||||
}
|
||||
|
||||
$startTime = api_get_local_time(
|
||||
$sessionInfo['access_start_date'],
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
$endTime = api_get_local_time(
|
||||
$sessionInfo['access_end_date'],
|
||||
null,
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
$generalCoach = '';
|
||||
$generalCoachEmail = '';
|
||||
if (!empty($coachId)) {
|
||||
$coachInfo = api_get_user_info($coachId);
|
||||
if (!empty($coachInfo)) {
|
||||
$generalCoach = $coachInfo['complete_name'];
|
||||
$generalCoachEmail = $coachInfo['email'];
|
||||
}
|
||||
}
|
||||
|
||||
$tags = [
|
||||
'((session_name))' => $sessionInfo['name'],
|
||||
'((session_start_date))' => $startTime,
|
||||
'((general_coach))' => $generalCoach,
|
||||
'((general_coach_email))' => $generalCoachEmail,
|
||||
'((session_end_date))' => $endTime,
|
||||
'((user_username))' => $userInfo['username'],
|
||||
'((user_complete_name))' => $userInfo['complete_name'],
|
||||
'((user_firstname))' => $userInfo['firstname'],
|
||||
'((user_lastname))' => $userInfo['lastname'],
|
||||
'((user_first_name))' => $userInfo['firstname'],
|
||||
'((user_last_name))' => $userInfo['lastname'],
|
||||
'((user_official_code))' => $userInfo['official_code'],
|
||||
'((user_picture))' => $userPicture,
|
||||
'((lp_progress))' => $progress,
|
||||
];
|
||||
|
||||
if (!empty($extraFields)) {
|
||||
$efv = new ExtraFieldValue('user');
|
||||
|
||||
foreach ($extraFields as $extraField) {
|
||||
$valueExtra = $efv->get_values_by_handler_and_field_variable(
|
||||
$user['user_id'],
|
||||
$extraField['variable'],
|
||||
true
|
||||
);
|
||||
$tags['(('.strtolower($extraField['variable']).'))'] = $valueExtra['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$message = str_replace(array_keys($tags), $tags, $message);
|
||||
$message .= $attachments;
|
||||
|
||||
MessageManager::send_message_simple(
|
||||
$userInfo['user_id'],
|
||||
$subject,
|
||||
$message,
|
||||
$coachId
|
||||
);
|
||||
}
|
||||
|
||||
$message = get_lang('YouAreReceivingACopyBecauseYouAreACourseCoach').'<br /><br />'.$message;
|
||||
|
||||
foreach ($coachList as $courseCoachId) {
|
||||
MessageManager::send_message_simple(
|
||||
$courseCoachId,
|
||||
get_lang('YouAreReceivingACopyBecauseYouAreACourseCoach').' '.$subject,
|
||||
$message,
|
||||
$coachId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$messagesSent++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $messagesSent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
$tags = [
|
||||
'((session_name))',
|
||||
'((session_start_date))',
|
||||
'((session_end_date))',
|
||||
'((general_coach))',
|
||||
'((general_coach_email))',
|
||||
'((user_username))',
|
||||
'((user_complete_name))',
|
||||
'((user_first_name))',
|
||||
'((user_last_name))',
|
||||
'((user_picture))',
|
||||
'((lp_progress))',
|
||||
'((user_official_code))',
|
||||
];
|
||||
// get user extra fields list (only visible to self and filter-able)
|
||||
$extraField = new ExtraField('user');
|
||||
$extraFields = $extraField->get_all(['filter = ? AND visible_to_self = ?' => [1, 1]]);
|
||||
if (!empty($extraFields)) {
|
||||
foreach ($extraFields as $extraField) {
|
||||
$tags[] = '(('.strtolower($extraField['variable']).'))';
|
||||
}
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function allowed()
|
||||
{
|
||||
return api_get_configuration_value('allow_scheduled_announcements');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormValidator $form
|
||||
*/
|
||||
private function setTagsInForm(&$form)
|
||||
{
|
||||
$form->addLabel(
|
||||
get_lang('Tags'),
|
||||
Display::return_message(
|
||||
implode('<br />', $this->getTags()),
|
||||
'normal',
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
143
main/inc/lib/SmsPlugin.php
Normal file
143
main/inc/lib/SmsPlugin.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class SmsPlugin.
|
||||
*
|
||||
* @author Julio Montoya
|
||||
*/
|
||||
class SmsPlugin extends Plugin
|
||||
{
|
||||
public const WELCOME_LOGIN_PASSWORD = 0;
|
||||
public const NEW_FILE_SHARED_COURSE_BY = 1;
|
||||
public const ACCOUNT_APPROVED_CONNECT = 2;
|
||||
public const NEW_COURSE_BEEN_CREATED = 3;
|
||||
public const NEW_USER_SUBSCRIBED_COURSE = 4;
|
||||
public const NEW_COURSE_SUGGESTED_TEACHER = 5;
|
||||
public const COURSE_OPENING_REQUEST_CODE_REGISTERED = 6;
|
||||
public const COURSE_OPENING_REQUEST_CODE_APPROVED = 7;
|
||||
public const COURSE_OPENING_REQUEST_CODE_REJECTED = 8;
|
||||
public const COURSE_OPENING_REQUEST_CODE = 9;
|
||||
public const BEEN_SUBSCRIBED_COURSE = 10;
|
||||
public const ASSIGNMENT_BEEN_CREATED_COURSE = 11;
|
||||
public const ACCOUNT_CREATED_UPDATED_LOGIN_PASSWORD = 12;
|
||||
public const PASSWORD_UPDATED_LOGIN_PASSWORD = 13;
|
||||
public const REQUESTED_PASSWORD_CHANGE = 14;
|
||||
public const RECEIVED_NEW_PERSONAL_MESSAGES = 15;
|
||||
public const NEW_USER_PENDING_APPROVAL = 16;
|
||||
public const POSTED_FORUM_COURSE = 17;
|
||||
public const CHECK_EMAIL_CONNECT_MORE_INFO = 18;
|
||||
public const STUDENT_ANSWERED_TEST = 19;
|
||||
public const STUDENT_ANSWERED_TEST_OPEN_QUESTION = 20;
|
||||
public const STUDENT_ANSWERED_TEST_VOICE_QUESTION = 21;
|
||||
public const ANSWER_OPEN_QUESTION_TEST_REVIEWED = 22;
|
||||
public const NEW_THREAD_STARTED_FORUM = 23;
|
||||
public const NEW_ANSWER_POSTED_FORUM = 24;
|
||||
public const NEW_SYSTEM_ANNOUNCEMENT_ADDED = 25;
|
||||
public const TEST_NEW_SYSTEM_ANNOUNCEMENT_ADDED = 26;
|
||||
public const SYSTEM_ANNOUNCEMENT_UPDATE = 27;
|
||||
public const TEST_SYSTEM_ANNOUNCEMENT_UPDATE = 28;
|
||||
public const USER_UPLOADED_ASSIGNMENT_COURSE_STUDENT_SUBMITS_PAPER = 29;
|
||||
public const USER_UPLOADED_ASSIGNMENT_CHECK_STUDENT_SUBMITS_PAPER = 30;
|
||||
public const USER_UPLOADED_ASSIGNMENT_COURSE = 31;
|
||||
public const USER_UPLOADED_ASSIGNMENT_CHECK = 32;
|
||||
public const SUBSCRIBED_SESSION = 33;
|
||||
public const SUBSCRIBED_SESSION_CSV = 34;
|
||||
public const USER_SUGGESTED_BE_FRIENDS = 35;
|
||||
public const USER_ANSWERED_INBOX_MESSAGE = 36;
|
||||
public const BEEN_INVITED_JOIN_GROUP = 37;
|
||||
public const MESSAGES_SENT_EDITED_GROUP_EDITED = 38;
|
||||
public const MESSAGES_SENT_EDITED_GROUP_ADDED = 39;
|
||||
public const BEEN_INVITED_COMPLETE_SURVEY_COURSE = 40;
|
||||
public const REMINDER_ASSIGNMENT_COURSE_DUE = 41;
|
||||
public const USER_DETAILS_MODIFIED = 42;
|
||||
public const CERTIFICATE_NOTIFICATION = 43;
|
||||
|
||||
public $isCoursePlugin = true;
|
||||
public $isMailPlugin = true;
|
||||
|
||||
/**
|
||||
* getSmsTypeOptions (returns all SMS types).
|
||||
*
|
||||
* @return array SMS types
|
||||
*/
|
||||
public function getSmsTypeOptions()
|
||||
{
|
||||
return [
|
||||
'MessageWelcomeXLoginXPasswordX',
|
||||
'MessageXNewFileSharedCourseXByX',
|
||||
'MessageXAccountApprovedConnectX',
|
||||
'MessageXNewCourseXBeenCreatedX',
|
||||
'MessageXNewUserXSubscribedCourseX',
|
||||
'MessageXNewCourseSuggestedTeacherX',
|
||||
'MessageXCourseOpeningRequestCodeXRegistered',
|
||||
'MessageXCourseOpeningRequestCourseCodeXApproved',
|
||||
'MessageXRequestOpenCourseCodeXReject',
|
||||
'MessageXCourseOpeningRequestCourseCodeX',
|
||||
'MessageXBeenSubscribedCourseX',
|
||||
'MessageXAssignmentBeenCreatedCourseX',
|
||||
'MessageXAccountCreatedUpdatedLoginXPasswordX',
|
||||
'MessageXPasswordUpdatedLoginXPasswordX',
|
||||
'MessageXRequestedPasswordChange',
|
||||
'MessageXReceivedNewPersonalMessages',
|
||||
'MessageXNewUserXPendingApproval',
|
||||
'MessageXXPostedForumXCourseX',
|
||||
'MessageXXXCheckEmailConnectMoreInfo',
|
||||
'MessageXXStudentXAnsweredTestX',
|
||||
'MessageXXStudentXAnsweredTestXOpenQuestion',
|
||||
'MessageXXStudentXAnsweredTestXVoiceQuestion',
|
||||
'MessageXXAnswerOpenQuestionTestXReviewed',
|
||||
'MessageXXNewThreadXStartedForumX',
|
||||
'MessageXXNewAnswerPostedXForumX',
|
||||
'MessageXXNewSystemAnnouncementAdded',
|
||||
'MessageXTestXNewSystemAnnouncementAdded',
|
||||
'MessageXXSystemAnnouncementUpdate',
|
||||
'MessageXTestXSystemAnnouncementUpdate',
|
||||
'MessageXUserXUploadedAssignmentXCourseXStudentSubmitsPaper',
|
||||
'MessageXUserXUploadedAssignmentXCheckXStudentSubmitsPaper',
|
||||
'MessageXUserXUploadedAssignmentXCourseX',
|
||||
'MessageXUserXUploadedAssignmentXCheckX',
|
||||
'MessageXSubscribedSessionX',
|
||||
'MessageXSubscribedSessionXCSV',
|
||||
'MessageXUserXSuggestedBeFriends',
|
||||
'MessageXUserXAnsweredInboxMessage',
|
||||
'MessageXBeenInvitedJoinGroupX',
|
||||
'MessageXMessagesSentEditedGroupXEdited',
|
||||
'MessageXMessagesSentEditedGroupXAdded',
|
||||
'MessageXBeenInvitedCompleteSurveyXCourseX',
|
||||
'MessageXReminderAssignmentXCourseXDue',
|
||||
'MessageXUserDetailsModified',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* install (installs the plugin).
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$this->addMobilePhoneNumberField();
|
||||
}
|
||||
|
||||
/**
|
||||
* addMobilePhoneNumberField (adds a mobile phone number field if it is not
|
||||
* already created).
|
||||
*/
|
||||
private function addMobilePhoneNumberField()
|
||||
{
|
||||
$extraField = new ExtraField('user');
|
||||
$extraFieldInfo = $extraField->get_handler_field_info_by_field_variable('mobile_phone_number');
|
||||
|
||||
if (empty($extraFieldInfo)) {
|
||||
$extraField->save([
|
||||
'field_type' => 1,
|
||||
'variable' => 'mobile_phone_number',
|
||||
'display_text' => $this->get_lang('mobile_phone_number'),
|
||||
'default_value' => null,
|
||||
'field_order' => 2,
|
||||
'visible' => 1,
|
||||
'changeable' => 1,
|
||||
'filter' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
main/inc/lib/SmsPluginLibraryInterface.php
Normal file
46
main/inc/lib/SmsPluginLibraryInterface.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class SmsPluginLibraryInterface.
|
||||
*
|
||||
* @author Julio Montoya
|
||||
*/
|
||||
interface SmsPluginLibraryInterface
|
||||
{
|
||||
/**
|
||||
* getMobilePhoneNumberById (retrieves a user mobile phone number by user id).
|
||||
*
|
||||
* @param int $userId
|
||||
*
|
||||
* @return int User's mobile phone number
|
||||
*/
|
||||
public function getMobilePhoneNumberById($userId);
|
||||
|
||||
/**
|
||||
* @param array $additionalParameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function send($additionalParameters);
|
||||
|
||||
/**
|
||||
* @param array $additionalParameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSms($additionalParameters);
|
||||
|
||||
/**
|
||||
* buildSms (builds an SMS from a template and data).
|
||||
*
|
||||
* @param object $plugin ClockworksmsPlugin object
|
||||
* @param object $tpl Template object
|
||||
* @param string $templateName Template file name
|
||||
* @param string $messageKey Text key from lang file
|
||||
* @param array $parameters Data to fill message variables (if any)
|
||||
*
|
||||
* @return object Template object with message property updated
|
||||
*/
|
||||
public function buildSms($plugin, $tpl, $templateName, $messageKey, $parameters = null);
|
||||
}
|
||||
89
main/inc/lib/SortableTableFromArray.php
Normal file
89
main/inc/lib/SortableTableFromArray.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Sortable table which can be used for data available in an array.
|
||||
*/
|
||||
class SortableTableFromArray extends SortableTable
|
||||
{
|
||||
/**
|
||||
* The array containing all data for this table.
|
||||
*/
|
||||
public $table_data;
|
||||
public $handlePagination;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $table_data
|
||||
* @param int $default_column
|
||||
* @param int $default_items_per_page
|
||||
* @param string $tableName
|
||||
* @param string $get_total_number_function
|
||||
* @param string $tableId
|
||||
*/
|
||||
public function __construct(
|
||||
$table_data,
|
||||
$default_column = 1,
|
||||
$default_items_per_page = 20,
|
||||
$tableName = 'tablename',
|
||||
$get_total_number_function = null,
|
||||
$tableId = ''
|
||||
) {
|
||||
parent::__construct(
|
||||
$tableName,
|
||||
$get_total_number_function,
|
||||
null,
|
||||
$default_column,
|
||||
$default_items_per_page,
|
||||
null,
|
||||
$tableId
|
||||
);
|
||||
$this->table_data = $table_data;
|
||||
$this->handlePagination = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table data to show on current page.
|
||||
*
|
||||
* @see SortableTable#get_table_data
|
||||
*/
|
||||
public function get_table_data(
|
||||
$from = 1,
|
||||
$per_page = null,
|
||||
$column = null,
|
||||
$direction = null,
|
||||
$sort = true
|
||||
) {
|
||||
if ($sort) {
|
||||
$content = TableSort::sort_table(
|
||||
$this->table_data,
|
||||
$this->column,
|
||||
'ASC' === $this->direction ? SORT_ASC : SORT_DESC
|
||||
);
|
||||
} else {
|
||||
$content = $this->table_data;
|
||||
}
|
||||
|
||||
return array_slice($content, $from, $this->per_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total number of items.
|
||||
*
|
||||
* @see SortableTable#get_total_number_of_items
|
||||
*/
|
||||
public function get_total_number_of_items()
|
||||
{
|
||||
if (isset($this->total_number_of_items) && !empty($this->total_number_of_items) && $this->total_number_of_items != -1) {
|
||||
return $this->total_number_of_items;
|
||||
} else {
|
||||
if (!empty($this->table_data)) {
|
||||
return count($this->table_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
118
main/inc/lib/SortableTableFromArrayConfig.php
Normal file
118
main/inc/lib/SortableTableFromArrayConfig.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Sortable table which can be used for data available in an array.
|
||||
*
|
||||
* Is a variation of SortableTableFromArray because we add 2 new arrays $column_show and $column_order
|
||||
* $column_show is an array that lets us decide which are going to be the columns to show
|
||||
* $column_order is an array that lets us decide the ordering of the columns
|
||||
* i.e: $column_header=array('a','b','c','d','e'); $column_order=array(1,2,5,4,5);
|
||||
* These means that the 3th column (letter "c") will be sort like the order we use in the 5th column
|
||||
*/
|
||||
class SortableTableFromArrayConfig extends SortableTable
|
||||
{
|
||||
/**
|
||||
* The array containing the columns that will be show
|
||||
* i.e $column_show=array('1','0','0'); we will show only the 1st column.
|
||||
*/
|
||||
private $column_show;
|
||||
|
||||
/**
|
||||
* The array containing the real sort column
|
||||
* $column_order=array('1''4','3','4');
|
||||
* The 2nd column will be order like the 4th column.
|
||||
*/
|
||||
private $column_order;
|
||||
|
||||
private $doc_filter;
|
||||
private $handlePagination = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $data All the information of the table
|
||||
* @param int $column Default column that will be used in the sort functions
|
||||
* @param int $itemsPerPage Number of items per pages that we are going to see
|
||||
* @param string $tableName Name of the table
|
||||
* @param array $columnShow An array with binary values: 1 = show column, 2 = don't show it
|
||||
* @param array $columnOrder An array of integers that let us decide how the columns are going to be sort
|
||||
* @param string $direction ASC/DESC
|
||||
* @param bool $docFilter special modification to fix the document name order
|
||||
*/
|
||||
public function __construct(
|
||||
$data,
|
||||
$column = 1,
|
||||
$itemsPerPage = 20,
|
||||
$tableName = 'tablename',
|
||||
$columnShow = [],
|
||||
$columnOrder = [],
|
||||
$direction = 'ASC',
|
||||
$docFilter = false
|
||||
) {
|
||||
$this->column_show = $columnShow;
|
||||
$this->column_order = $columnOrder;
|
||||
$this->doc_filter = $docFilter;
|
||||
|
||||
// if data is empty the pagination is handled with query in database
|
||||
if (empty($data)) {
|
||||
$this->handlePagination = false;
|
||||
}
|
||||
parent::__construct(
|
||||
$tableName,
|
||||
null,
|
||||
null,
|
||||
$column,
|
||||
$itemsPerPage,
|
||||
$direction
|
||||
);
|
||||
$this->table_data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table data to show on current page.
|
||||
*
|
||||
* @see SortableTable#get_table_data
|
||||
*/
|
||||
public function get_table_data(
|
||||
$from = 1,
|
||||
$perPage = null,
|
||||
$column = null,
|
||||
$direction = null,
|
||||
$sort = true
|
||||
) {
|
||||
$table = TableSort::sort_table_config(
|
||||
$this->table_data,
|
||||
$this->column,
|
||||
'ASC' === $this->direction ? SORT_ASC : SORT_DESC,
|
||||
$this->column_show,
|
||||
$this->column_order,
|
||||
SORT_REGULAR,
|
||||
$this->doc_filter
|
||||
);
|
||||
|
||||
if ($this->handlePagination) {
|
||||
return array_slice($table, $from, $this->per_page);
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total number of items.
|
||||
*
|
||||
* @see SortableTable#get_total_number_of_items
|
||||
*/
|
||||
public function get_total_number_of_items()
|
||||
{
|
||||
if (!empty($this->total_number_of_items) && $this->total_number_of_items !== -1) {
|
||||
return $this->total_number_of_items;
|
||||
} else {
|
||||
if (!empty($this->table_data)) {
|
||||
return count($this->table_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
214
main/inc/lib/StudentFollowPage.php
Normal file
214
main/inc/lib/StudentFollowPage.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CourseBundle\Entity\CItemProperty;
|
||||
|
||||
/**
|
||||
* Class StudentFollowPage.
|
||||
*/
|
||||
class StudentFollowPage
|
||||
{
|
||||
public const VARIABLE_ACQUISITION = 'acquisition';
|
||||
public const VARIABLE_INVISIBLE = 'invisible';
|
||||
|
||||
public static function getLpSubscription(
|
||||
array $lpInfo,
|
||||
int $studentId,
|
||||
int $courseId,
|
||||
int $sessionId = 0,
|
||||
bool $showTeacherName = true
|
||||
): string {
|
||||
$em = Database::getManager();
|
||||
|
||||
if ($lpInfo['subscribe_users']) {
|
||||
$itemRepo = $em->getRepository(CItemProperty::class);
|
||||
$itemProperty = $itemRepo->findByUserSuscribedToItem(
|
||||
'learnpath',
|
||||
$lpInfo['iid'],
|
||||
$studentId,
|
||||
$courseId,
|
||||
$sessionId
|
||||
);
|
||||
|
||||
if (null === $itemProperty) {
|
||||
$userGroups = GroupManager::getAllGroupPerUserSubscription($studentId, $courseId);
|
||||
|
||||
foreach ($userGroups as $groupInfo) {
|
||||
$itemProperty = $itemRepo->findByGroupSuscribedToLp(
|
||||
'learnpath',
|
||||
$lpInfo['iid'],
|
||||
$groupInfo['iid'],
|
||||
$courseId,
|
||||
$sessionId
|
||||
);
|
||||
|
||||
if (null !== $itemProperty) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $itemProperty) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$formattedDate = api_convert_and_format_date($itemProperty->getInsertDate(), DATE_TIME_FORMAT_LONG);
|
||||
|
||||
if ($showTeacherName) {
|
||||
$insertUser = $itemProperty->getInsertUser()->getId() !== $studentId
|
||||
? $itemProperty->getInsertUser()->getCompleteName()
|
||||
: '-';
|
||||
|
||||
return "$insertUser<br>".Display::tag('small', $formattedDate);
|
||||
}
|
||||
|
||||
return $formattedDate;
|
||||
}
|
||||
|
||||
$subscriptionEvent = Event::findUserSubscriptionToCourse($studentId, $courseId, $sessionId);
|
||||
|
||||
if (empty($subscriptionEvent)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$formattedDate = api_convert_and_format_date($subscriptionEvent['default_date'], DATE_TIME_FORMAT_LONG);
|
||||
|
||||
if ($showTeacherName) {
|
||||
$creator = api_get_user_entity($subscriptionEvent['default_user_id']);
|
||||
|
||||
return "{$creator->getCompleteName()}<br>".Display::tag('small', $formattedDate);
|
||||
}
|
||||
|
||||
return $formattedDate;
|
||||
}
|
||||
|
||||
public static function getLpAcquisition(
|
||||
array $lpInfo,
|
||||
int $studentId,
|
||||
int $courseId,
|
||||
int $sessionId = 0,
|
||||
bool $allowEdit = false
|
||||
): string {
|
||||
$lpView = learnpath::findLastView($lpInfo['iid'], $studentId, $courseId, $sessionId, true);
|
||||
|
||||
$extraField = new ExtraField('lp_view');
|
||||
$field = $extraField->get_handler_field_info_by_field_variable(self::VARIABLE_ACQUISITION);
|
||||
|
||||
$extraFieldValue = new ExtraFieldValue('lp_view');
|
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable($lpView['iid'], self::VARIABLE_ACQUISITION);
|
||||
|
||||
$return = '';
|
||||
|
||||
if (empty($value)) {
|
||||
$return .= '-';
|
||||
} else {
|
||||
$optionSelected = array_filter(
|
||||
$field['options'],
|
||||
function (array $option) use ($value) {
|
||||
return $option['option_value'] == $value['value'];
|
||||
}
|
||||
);
|
||||
|
||||
if (empty($optionSelected)) {
|
||||
$return .= '-';
|
||||
} else {
|
||||
$optionSelected = current($optionSelected);
|
||||
$valueComment = json_decode($value['comment'], true);
|
||||
|
||||
$register = api_get_user_entity($valueComment['user']);
|
||||
|
||||
$return .= ExtraFieldOption::translateDisplayName($optionSelected['display_text']).'<br>'
|
||||
.Display::tag('small', $register->getCompleteName()).'<br>'
|
||||
.Display::tag(
|
||||
'small',
|
||||
api_convert_and_format_date($valueComment['datetime'], DATE_TIME_FORMAT_LONG)
|
||||
).'<br>';
|
||||
}
|
||||
}
|
||||
|
||||
$editUrl = api_get_path(WEB_AJAX_PATH).'student_follow_page.ajax.php?'
|
||||
.http_build_query(['lp_view' => $lpView['iid'], 'a' => 'form_adquisition']);
|
||||
|
||||
if ($allowEdit) {
|
||||
$return .= Display::url(
|
||||
Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_TINY),
|
||||
$editUrl,
|
||||
['class' => 'ajax', 'data-title' => strip_tags($lpInfo['lp_name'])]
|
||||
);
|
||||
}
|
||||
|
||||
return '<div id="acquisition-'.$lpView['iid'].'">'.$return.'</div>';
|
||||
}
|
||||
|
||||
public static function getLpVisibleScript()
|
||||
{
|
||||
$url = api_get_path(WEB_AJAX_PATH).'student_follow_page.ajax.php?'.http_build_query(['a' => 'views_invisible']);
|
||||
|
||||
return "<script>$(function () {
|
||||
var chkbView = $('[name=\"chkb_view[]\"]');
|
||||
|
||||
function doRequest(element, state) {
|
||||
element.prop('disabled', true);
|
||||
|
||||
var views = $.makeArray(element).map(function (input) { return input.value; });
|
||||
|
||||
return $.post('$url', { 'chkb_view[]': views, 'state': state }, function () { element.prop('disabled', false); });
|
||||
}
|
||||
|
||||
$('[name=\"chkb_category[]\"]').on('change', function () {
|
||||
var checked = this.checked;
|
||||
var chkbs = $(this).parents('table').find('td :checkbox').each(function () { this.checked = checked; });
|
||||
|
||||
doRequest(chkbs, checked);
|
||||
}).prop('checked', true);
|
||||
|
||||
chkbView.on('change', function () {
|
||||
doRequest($(this), this.checked);
|
||||
|
||||
$(this).parents('table').find('th :checkbox').prop(
|
||||
'checked',
|
||||
$.makeArray($(this).parents('table').find('td :checkbox'))
|
||||
.map(function (input) { return input.checked; })
|
||||
.reduce(function (acc, cur) { return acc && cur; })
|
||||
);
|
||||
}).each(function () {
|
||||
if (!this.checked) {
|
||||
$(this).parents('table').find('th :checkbox').prop('checked', false);
|
||||
}
|
||||
});
|
||||
});</script>";
|
||||
}
|
||||
|
||||
public static function getLpVisibleField(array $lpInfo, int $studentId, int $courseId, int $sessionId = 0)
|
||||
{
|
||||
$attrs = [];
|
||||
|
||||
$isVisible = self::isViewVisible($lpInfo['iid'], $studentId, $courseId, $sessionId);
|
||||
|
||||
if (!$isVisible) {
|
||||
$attrs['checked'] = 'checked';
|
||||
}
|
||||
|
||||
return Display::input(
|
||||
'checkbox',
|
||||
'chkb_view[]',
|
||||
implode('_', [$lpInfo['iid'], $studentId, $courseId, $sessionId]),
|
||||
$attrs
|
||||
);
|
||||
}
|
||||
|
||||
public static function isViewVisible(int $lpId, int $studentId, int $courseId, int $sessionId): bool
|
||||
{
|
||||
$lpView = learnpath::findLastView($lpId, $studentId, $courseId, $sessionId);
|
||||
|
||||
if (empty($lpView)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$extraFieldValue = new ExtraFieldValue('lp_view');
|
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable($lpView['iid'], self::VARIABLE_INVISIBLE);
|
||||
|
||||
return empty($value) || empty($value['value']);
|
||||
}
|
||||
}
|
||||
111
main/inc/lib/TeacherTimeReport.php
Normal file
111
main/inc/lib/TeacherTimeReport.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Library for generate a teacher time report.
|
||||
*
|
||||
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||
*/
|
||||
class TeacherTimeReport
|
||||
{
|
||||
/**
|
||||
* The report data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data = [];
|
||||
|
||||
/**
|
||||
* Callback for compare sessions names.
|
||||
*
|
||||
* @param array $dataA The data A
|
||||
* @param array $dataB The data B
|
||||
*
|
||||
* @return int returns -1 if dataA is less than dataB, 1 if dataA is greater than dataB, and 0 if they are equal
|
||||
*/
|
||||
public function compareSessions($dataA, $dataB)
|
||||
{
|
||||
return strnatcmp($dataA['session']['name'], $dataB['session']['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for compare courses names.
|
||||
*
|
||||
* @param array $dataA The datab A
|
||||
* @param array $dataB The data B
|
||||
*
|
||||
* @return int returns -1 if dataA is less than dataB, 1 if dataA is greater than dataB, and 0 if they are equal
|
||||
*/
|
||||
public function compareCourses($dataA, $dataB)
|
||||
{
|
||||
return strnatcmp($dataA['course']['name'], $dataB['course']['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for compare coaches names.
|
||||
*
|
||||
* @param array $dataA The datab A
|
||||
* @param array $dataB The data B
|
||||
*
|
||||
* @return int returns -1 if dataA is less than dataB, 1 if dataA is greater than dataB, and 0 if they are equal
|
||||
*/
|
||||
public function compareCoaches($dataA, $dataB)
|
||||
{
|
||||
return strnatcmp($dataA['coach']['complete_name'], $dataB['coach']['complete_name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the report data.
|
||||
*
|
||||
* @param bool $withFilter Whether sort by sessions and courses
|
||||
*/
|
||||
public function sortData($withFilter = false)
|
||||
{
|
||||
if ($withFilter) {
|
||||
uasort($this->data, [$this, 'compareSessions']);
|
||||
uasort($this->data, [$this, 'compareCourses']);
|
||||
}
|
||||
|
||||
uasort($this->data, [$this, 'compareCoaches']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|false $withFilter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function prepareDataToExport($withFilter = false)
|
||||
{
|
||||
$dataToExport = [];
|
||||
|
||||
if ($withFilter) {
|
||||
$dataToExport[] = [
|
||||
get_lang('Session'),
|
||||
get_lang('Course'),
|
||||
get_lang('Coach'),
|
||||
get_lang('TotalTime'),
|
||||
];
|
||||
} else {
|
||||
$dataToExport[] = [
|
||||
get_lang('Coach'),
|
||||
get_lang('TotalTime'),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->data as $row) {
|
||||
$data = [];
|
||||
|
||||
if ($withFilter) {
|
||||
$data[] = $row['session']['name'];
|
||||
$data[] = $row['course']['name'];
|
||||
}
|
||||
|
||||
$data[] = $row['coach']['complete_name'];
|
||||
$data[] = $row['total_time'];
|
||||
|
||||
$dataToExport[] = $data;
|
||||
}
|
||||
|
||||
return $dataToExport;
|
||||
}
|
||||
}
|
||||
2591
main/inc/lib/TicketManager.php
Normal file
2591
main/inc/lib/TicketManager.php
Normal file
File diff suppressed because it is too large
Load Diff
1609
main/inc/lib/TrackingCourseLog.php
Normal file
1609
main/inc/lib/TrackingCourseLog.php
Normal file
File diff suppressed because it is too large
Load Diff
121
main/inc/lib/UnserializeApi.php
Normal file
121
main/inc/lib/UnserializeApi.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class UnserializeApi.
|
||||
*/
|
||||
class UnserializeApi
|
||||
{
|
||||
/**
|
||||
* Unserialize content using Brummann\Polyfill\Unserialize.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $serialized
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unserialize($type, $serialized, $ignoreErrors = false)
|
||||
{
|
||||
$allowedClasses = [];
|
||||
|
||||
switch ($type) {
|
||||
case 'career':
|
||||
case 'sequence_graph':
|
||||
$allowedClasses = [
|
||||
\Fhaculty\Graph\Graph::class,
|
||||
\Fhaculty\Graph\Set\VerticesMap::class,
|
||||
\Fhaculty\Graph\Set\Vertices::class,
|
||||
\Fhaculty\Graph\Set\Edges::class,
|
||||
\Fhaculty\Graph\Vertex::class,
|
||||
\Fhaculty\Graph\Edge\Base::class,
|
||||
\Fhaculty\Graph\Edge\Directed::class,
|
||||
\Fhaculty\Graph\Edge\Undirected::class,
|
||||
];
|
||||
break;
|
||||
case 'course':
|
||||
$allowedClasses = [
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Course::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Announcement::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Asset::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Attendance::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\CalendarEvent::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyLearnpath::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseCopyTestCategory::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseDescription::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\CourseSession::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Document::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Forum::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumCategory::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumPost::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\ForumTopic::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Glossary::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\GradeBookBackup::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\LearnPathCategory::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Link::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\LinkCategory::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Quiz::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestion::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestionOption::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\ScormDocument::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Survey::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\SurveyInvitation::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\SurveyQuestion::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Thematic::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\ToolIntro::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Wiki::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\Work::class,
|
||||
\Chamilo\CourseBundle\Component\CourseCopy\Resources\XapiTool::class,
|
||||
\Chamilo\CourseBundle\Entity\CLpCategory::class,
|
||||
stdClass::class,
|
||||
Category::class,
|
||||
AttendanceLink::class,
|
||||
DropboxLink::class,
|
||||
Evaluation::class,
|
||||
ExerciseLink::class,
|
||||
ForumThreadLink::class,
|
||||
LearnpathLink::class,
|
||||
LinkFactory::class,
|
||||
Result::class,
|
||||
StudentPublicationLink::class,
|
||||
SurveyLink::class,
|
||||
];
|
||||
// no break
|
||||
case 'lp':
|
||||
$allowedClasses = array_merge(
|
||||
$allowedClasses,
|
||||
[
|
||||
learnpath::class,
|
||||
learnpathItem::class,
|
||||
aicc::class,
|
||||
aiccBlock::class,
|
||||
aiccItem::class,
|
||||
aiccObjective::class,
|
||||
aiccResource::class,
|
||||
scorm::class,
|
||||
scormItem::class,
|
||||
scormMetadata::class,
|
||||
scormOrganization::class,
|
||||
scormResource::class,
|
||||
Link::class,
|
||||
LpItem::class,
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'not_allowed_classes':
|
||||
default:
|
||||
$allowedClasses = false;
|
||||
}
|
||||
|
||||
if ($ignoreErrors) {
|
||||
return @unserialize(
|
||||
$serialized,
|
||||
['allowed_classes' => $allowedClasses]
|
||||
);
|
||||
}
|
||||
|
||||
return unserialize(
|
||||
$serialized,
|
||||
['allowed_classes' => $allowedClasses]
|
||||
);
|
||||
}
|
||||
}
|
||||
96
main/inc/lib/VideoChat.php
Normal file
96
main/inc/lib/VideoChat.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* VideoChat class.
|
||||
*
|
||||
* This class provides methods for video chat management.
|
||||
*
|
||||
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
|
||||
*/
|
||||
class VideoChat
|
||||
{
|
||||
/**
|
||||
* Get the video chat info by its users.
|
||||
*
|
||||
* @param int $user1 User id
|
||||
* @param int $user2 Other user id
|
||||
*
|
||||
* @return array The video chat info. Otherwise return false
|
||||
*/
|
||||
public static function getChatRoomByUsers($user1, $user2)
|
||||
{
|
||||
$user1 = (int) $user1;
|
||||
$user2 = (int) $user2;
|
||||
|
||||
if (empty($user1) || empty($user2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Database::select(
|
||||
'*',
|
||||
Database::get_main_table(TABLE_MAIN_CHAT_VIDEO),
|
||||
[
|
||||
'where' => [
|
||||
'(from_user = ? AND to_user = ?)' => [$user1, $user2],
|
||||
'OR (from_user = ? AND to_user = ?)' => [$user2, $user1],
|
||||
],
|
||||
],
|
||||
'first'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a video chat.
|
||||
*
|
||||
* @param int $fromUser The sender user
|
||||
* @param int $toUser The receiver user
|
||||
*
|
||||
* @return int The created video chat id. Otherwise return false
|
||||
*/
|
||||
public static function createRoom($fromUser, $toUser)
|
||||
{
|
||||
$fromUserInfo = api_get_user_info($fromUser);
|
||||
$toUserInfo = api_get_user_info($toUser);
|
||||
|
||||
$chatName = vsprintf(
|
||||
get_lang('VideoChatBetweenUserXAndUserY'),
|
||||
[$fromUserInfo['firstname'], $toUserInfo['firstname']]
|
||||
);
|
||||
|
||||
return Database::insert(
|
||||
Database::get_main_table(TABLE_MAIN_CHAT_VIDEO),
|
||||
[
|
||||
'from_user' => $fromUser,
|
||||
'to_user' => $toUser,
|
||||
'room_name' => $chatName,
|
||||
'datetime' => api_get_utc_datetime(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the video chat exists by its room name.
|
||||
*
|
||||
* @param string $name The video chat name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function nameExists($name)
|
||||
{
|
||||
$resultData = Database::select(
|
||||
'COUNT(1) AS count',
|
||||
Database::get_main_table(TABLE_MAIN_CHAT_VIDEO),
|
||||
[
|
||||
'where' => ['room_name = ?' => $name],
|
||||
],
|
||||
'first'
|
||||
);
|
||||
|
||||
if ($resultData !== false) {
|
||||
return $resultData['count'] > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Definition of the Accessurleditcoursestourl class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Access_url_edit_courses_to_url class
|
||||
* Contains several functions dealing with displaying,
|
||||
* editing,... of a Access_url_edit_courses_to_url_functions.
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Toon Keppens <toon@vi-host.net>
|
||||
* @author Julio Montoya - Cleaning code
|
||||
* @author Ricardo Rodriguez - Separated the function and code
|
||||
*/
|
||||
class Accessurleditcoursestourl
|
||||
{
|
||||
/**
|
||||
* Search for a list of available courses by title or code, based on
|
||||
* a given string.
|
||||
*
|
||||
* @param string String to search for
|
||||
* @param int Deprecated param
|
||||
*
|
||||
* @return xajaxResponse A formatted, xajax answer block
|
||||
* @assert () === false
|
||||
*/
|
||||
public function search_courses($needle, $id)
|
||||
{
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$xajax_response = new xajaxResponse();
|
||||
$return = '';
|
||||
|
||||
if (!empty($needle)) {
|
||||
// xajax send utf8 datas... datas in db can be non-utf8 datas
|
||||
$charset = api_get_system_encoding();
|
||||
$needle = api_convert_encoding($needle, $charset, 'utf-8');
|
||||
$needle = Database::escape_string($needle);
|
||||
// search courses where username or firstname or lastname begins likes $needle
|
||||
$sql = 'SELECT id, code, title FROM '.$tbl_course.' u '.
|
||||
' WHERE (title LIKE "'.$needle.'%" '.
|
||||
' OR code LIKE "'.$needle.'%" '.
|
||||
' ) '.
|
||||
' ORDER BY title, code '.
|
||||
' LIMIT 11';
|
||||
$rs = Database::query($sql);
|
||||
$i = 0;
|
||||
while ($course = Database::fetch_array($rs)) {
|
||||
$i++;
|
||||
if ($i <= 10) {
|
||||
$return .= '<a href="javascript: void(0);" onclick="javascript: add_course_to_url('.addslashes($course['id']).',\''.addslashes($course['title']).' ('.addslashes($course['code']).')'.'\')">'.$course['title'].' ('.$course['code'].')</a><br />';
|
||||
} else {
|
||||
$return .= '...<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
$xajax_response->addAssign(
|
||||
'ajax_list_courses',
|
||||
'innerHTML',
|
||||
api_utf8_encode($return)
|
||||
);
|
||||
|
||||
return $xajax_response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* Definition of the Accessurleditsessiontourl class.
|
||||
*/
|
||||
require_once 'xajax/xajax.inc.php';
|
||||
|
||||
/**
|
||||
* Accessurleditsessiontourl class
|
||||
* Contains several functions dealing with displaying,
|
||||
* editing,... of a Access_url_edit_session_to_url_functions.
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Toon Keppens <toon@vi-host.net>
|
||||
* @author Julio Montoya - Cleaning code
|
||||
* @author Ricardo Rodriguez - Separated the function and code
|
||||
*/
|
||||
class Accessurleditsessionstourl
|
||||
{
|
||||
/**
|
||||
* Search sessions by name, based on a search string.
|
||||
*
|
||||
* @param string Search string
|
||||
* @param int Deprecated param
|
||||
*
|
||||
* @return string Xajax response block
|
||||
* @assert () === false
|
||||
*/
|
||||
public function search_sessions($needle, $id)
|
||||
{
|
||||
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
|
||||
$xajax_response = new xajaxResponse();
|
||||
$return = '';
|
||||
|
||||
if (!empty($needle)) {
|
||||
// xajax send utf8 datas... datas in db can be non-utf8 datas
|
||||
$charset = api_get_system_encoding();
|
||||
$needle = api_convert_encoding($needle, $charset, 'utf-8');
|
||||
$needle = Database::escape_string($needle);
|
||||
// search sessiones where username or firstname or lastname begins likes $needle
|
||||
$sql = 'SELECT id, name FROM '.$tbl_session.' u
|
||||
WHERE (name LIKE "'.$needle.'%")
|
||||
ORDER BY name, id
|
||||
LIMIT 11';
|
||||
$rs = Database::query($sql);
|
||||
$i = 0;
|
||||
while ($session = Database::fetch_array($rs)) {
|
||||
$i++;
|
||||
if ($i <= 10) {
|
||||
$return .= '<a href="#" onclick="add_user_to_url(\''.addslashes($session['id']).'\',\''.addslashes($session['name']).' ('.addslashes($session['id']).')'.'\')">'.$session['name'].' </a><br />';
|
||||
} else {
|
||||
$return .= '...<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
$xajax_response->addAssign(
|
||||
'ajax_list_courses',
|
||||
'innerHTML',
|
||||
api_utf8_encode($return)
|
||||
);
|
||||
|
||||
return $xajax_response;
|
||||
}
|
||||
}
|
||||
65
main/inc/lib/access_url_edit_users_to_url_functions.lib.php
Normal file
65
main/inc/lib/access_url_edit_users_to_url_functions.lib.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* AccessUrlEditUsersToUrl class definition
|
||||
* Contains several functions dealing with displaying,
|
||||
* editing,... of a Access_url_edit_users_to_url_functions.
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Toon Keppens <toon@vi-host.net>
|
||||
* @author Julio Montoya - Cleaning code
|
||||
* @author Ricardo Rodriguez - Separated the function and code
|
||||
*/
|
||||
class AccessUrlEditUsersToUrl
|
||||
{
|
||||
/**
|
||||
* Search users by username, firstname or lastname, based on the given
|
||||
* search string.
|
||||
*
|
||||
* @param string Search string
|
||||
* @param int Deprecated param
|
||||
*
|
||||
* @return xajaxResponse Xajax response block
|
||||
* @assert () === false
|
||||
*/
|
||||
public static function search_users($needle, $id)
|
||||
{
|
||||
$tbl_user = Database::get_main_table(TABLE_MAIN_USER);
|
||||
$xajax_response = new xajaxResponse();
|
||||
$return = '';
|
||||
if (!empty($needle)) {
|
||||
// xajax send utf8 datas... datas in db can be non-utf8 datas
|
||||
$charset = api_get_system_encoding();
|
||||
$needle = api_convert_encoding($needle, $charset, 'utf-8');
|
||||
$needle = Database::escape_string($needle);
|
||||
// search users where username or firstname or lastname begins likes $needle
|
||||
$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
|
||||
$sql = 'SELECT u.user_id, username, lastname, firstname FROM '.$tbl_user.' u '.
|
||||
' WHERE (username LIKE "'.$needle.'%" '.
|
||||
' OR firstname LIKE "'.$needle.'%" '.
|
||||
' OR lastname LIKE "'.$needle.'%") '.
|
||||
$order_clause.
|
||||
' LIMIT 11';
|
||||
$rs = Database::query($sql);
|
||||
$i = 0;
|
||||
|
||||
while ($user = Database::fetch_array($rs)) {
|
||||
$i++;
|
||||
if ($i <= 10) {
|
||||
$return .= '<a href="javascript: void(0);" onclick="javascript: add_user_to_url(\''.addslashes($user['user_id']).'\',\''.api_get_person_name(addslashes($user['firstname']), addslashes($user['lastname'])).' ('.addslashes($user['username']).')'.'\')">'.api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')</a><br />';
|
||||
} else {
|
||||
$return .= '...<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
$xajax_response->addAssign(
|
||||
'ajax_list_users',
|
||||
'innerHTML',
|
||||
api_utf8_encode($return)
|
||||
);
|
||||
|
||||
return $xajax_response;
|
||||
}
|
||||
}
|
||||
1485
main/inc/lib/add_course.lib.inc.php
Normal file
1485
main/inc/lib/add_course.lib.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
132
main/inc/lib/add_courses_to_session_functions.lib.php
Normal file
132
main/inc/lib/add_courses_to_session_functions.lib.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use ChamiloSession as Session;
|
||||
|
||||
/**
|
||||
* Class AddCourseToSession.
|
||||
*/
|
||||
class AddCourseToSession
|
||||
{
|
||||
/**
|
||||
* Searches a course, given a search string and a type of search box.
|
||||
*
|
||||
* @param string $needle Search string
|
||||
* @param string $type Type of search box ('single' or anything else)
|
||||
* @param int $id_session
|
||||
*
|
||||
* @return xajaxResponse XajaxResponse
|
||||
* @assert ('abc', 'single') !== null
|
||||
* @assert ('abc', 'multiple') !== null
|
||||
*/
|
||||
public static function search_courses($needle, $type, $id_session)
|
||||
{
|
||||
$tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
|
||||
// Session value set in file add_courses_to_session.php
|
||||
$id_session = (int) $id_session;
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$course_title = null;
|
||||
$xajax_response = new xajaxResponse();
|
||||
$return = '';
|
||||
if (!empty($needle) && !empty($type)) {
|
||||
// xajax send utf8 datas... datas in db can be non-utf8 datas
|
||||
$charset = api_get_system_encoding();
|
||||
$needle = api_convert_encoding($needle, $charset, 'utf-8');
|
||||
$needle = Database::escape_string($needle);
|
||||
|
||||
$cond_course_code = '';
|
||||
if (!empty($id_session)) {
|
||||
$id_session = (int) $id_session;
|
||||
// check course_code from session_rel_course table
|
||||
$sql = 'SELECT c_id FROM '.$tbl_session_rel_course.'
|
||||
WHERE session_id = '.$id_session;
|
||||
$res = Database::query($sql);
|
||||
$course_codes = '';
|
||||
if (Database::num_rows($res) > 0) {
|
||||
while ($row = Database::fetch_row($res)) {
|
||||
$course_codes .= '\''.$row[0].'\',';
|
||||
}
|
||||
$course_codes = substr($course_codes, 0, (strlen($course_codes) - 1));
|
||||
$cond_course_code = ' AND course.id NOT IN('.$course_codes.') ';
|
||||
}
|
||||
}
|
||||
|
||||
if ('single' == $type) {
|
||||
// search users where username or firstname or lastname begins likes $needle
|
||||
$sql = 'SELECT
|
||||
course.id,
|
||||
course.visual_code,
|
||||
course.title,
|
||||
session_rel_course.session_id
|
||||
FROM '.$tbl_course.' course
|
||||
LEFT JOIN '.$tbl_session_rel_course.' session_rel_course
|
||||
ON course.id = session_rel_course.c_id
|
||||
AND session_rel_course.session_id = '.intval($id_session).'
|
||||
WHERE
|
||||
course.visual_code LIKE "'.$needle.'%" OR
|
||||
course.title LIKE "'.$needle.'%"';
|
||||
} else {
|
||||
$sql = 'SELECT course.id, course.visual_code, course.title
|
||||
FROM '.$tbl_course.' course
|
||||
WHERE
|
||||
course.visual_code LIKE "'.$needle.'%" '.$cond_course_code.'
|
||||
ORDER BY course.code ';
|
||||
}
|
||||
|
||||
if (api_is_multiple_url_enabled()) {
|
||||
$tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
|
||||
$access_url_id = api_get_current_access_url_id();
|
||||
if (-1 != $access_url_id) {
|
||||
if ('single' == $type) {
|
||||
$sql = 'SELECT
|
||||
course.id,
|
||||
course.visual_code,
|
||||
course.title,
|
||||
session_rel_course.session_id
|
||||
FROM '.$tbl_course.' course
|
||||
LEFT JOIN '.$tbl_session_rel_course.' session_rel_course
|
||||
ON course.id = session_rel_course.c_id
|
||||
AND session_rel_course.session_id = '.intval($id_session).'
|
||||
INNER JOIN '.$tbl_course_rel_access_url.' url_course
|
||||
ON (url_course.c_id = course.id)
|
||||
WHERE
|
||||
access_url_id = '.$access_url_id.' AND
|
||||
(course.visual_code LIKE "'.$needle.'%" OR
|
||||
course.title LIKE "'.$needle.'%" )';
|
||||
} else {
|
||||
$sql = 'SELECT course.id, course.visual_code, course.title
|
||||
FROM '.$tbl_course.' course, '.$tbl_course_rel_access_url.' url_course
|
||||
WHERE
|
||||
url_course.c_id = course.id AND
|
||||
access_url_id = '.$access_url_id.' AND
|
||||
course.visual_code LIKE "'.$needle.'%" '.$cond_course_code.'
|
||||
ORDER BY course.code ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rs = Database::query($sql);
|
||||
$course_list = [];
|
||||
if ('single' == $type) {
|
||||
while ($course = Database::fetch_array($rs)) {
|
||||
$course_list[] = $course['id'];
|
||||
$course_title = str_replace("'", "\'", $course_title);
|
||||
$return .= '<a href="javascript: void(0);" onclick="javascript: add_course_to_session(\''.$course['id'].'\',\''.$course_title.' ('.$course['visual_code'].')'.'\')">'.$course['title'].' ('.$course['visual_code'].')</a><br />';
|
||||
}
|
||||
$xajax_response->addAssign('ajax_list_courses_single', 'innerHTML', api_utf8_encode($return));
|
||||
} else {
|
||||
$return .= '<select id="origin" name="NoSessionCoursesList[]" multiple="multiple" size="20" style="width:340px;">';
|
||||
while ($course = Database::fetch_array($rs)) {
|
||||
$course_list[] = $course['id'];
|
||||
$course_title = str_replace("'", "\'", $course_title);
|
||||
$return .= '<option value="'.$course['id'].'" title="'.htmlspecialchars($course['title'].' ('.$course['visual_code'].')', ENT_QUOTES).'">'.$course['title'].' ('.$course['visual_code'].')</option>';
|
||||
}
|
||||
$return .= '</select>';
|
||||
$xajax_response->addAssign('ajax_list_courses_multiple', 'innerHTML', api_utf8_encode($return));
|
||||
}
|
||||
}
|
||||
Session::write('course_list', $course_list);
|
||||
|
||||
return $xajax_response;
|
||||
}
|
||||
}
|
||||
5386
main/inc/lib/agenda.lib.php
Normal file
5386
main/inc/lib/agenda.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
10701
main/inc/lib/api.lib.php
Normal file
10701
main/inc/lib/api.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
106
main/inc/lib/app_view.php
Normal file
106
main/inc/lib/app_view.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class View.
|
||||
*
|
||||
* @deprecated use Template class
|
||||
*/
|
||||
class View
|
||||
{
|
||||
private $data;
|
||||
private $template;
|
||||
private $layout;
|
||||
private $tool_path;
|
||||
|
||||
/**
|
||||
* Constructor, init tool path for rendering.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $toolname tool name (optional)
|
||||
* @param string $template_path
|
||||
*/
|
||||
public function __construct($toolname = '', $template_path = null)
|
||||
{
|
||||
if (!empty($toolname)) {
|
||||
if (isset($template_path)) {
|
||||
$path = $template_path.$toolname.'/';
|
||||
} else {
|
||||
$path = api_get_path(SYS_CODE_PATH).$toolname.'/';
|
||||
}
|
||||
if (is_dir($path)) {
|
||||
$this->tool_path = $path;
|
||||
} else {
|
||||
throw new Exception('View::__construct() $path directory does not exist '.$path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data sent from a controller.
|
||||
*
|
||||
* @param array data
|
||||
*/
|
||||
public function set_data($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
throw new Exception('View::set_data() $data must to be an array, you have sent a'.gettype($data));
|
||||
}
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layout view sent from a controller.
|
||||
*
|
||||
* @param string $layout view
|
||||
*/
|
||||
public function set_layout($layout)
|
||||
{
|
||||
$this->layout = $layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set template view sent from a controller.
|
||||
*
|
||||
* @param string $template view
|
||||
*/
|
||||
public function set_template($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render data to the template and layout views.
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$content = $this->render_template();
|
||||
$target = $this->tool_path.$this->layout.'.php';
|
||||
if (file_exists($target)) {
|
||||
require_once $target;
|
||||
} else {
|
||||
throw new Exception('View::render() invalid file path '.$target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It's used into render method for rendering data in the template and layout views.
|
||||
*
|
||||
* @return string Rendered template (as HTML, most of the time)
|
||||
*/
|
||||
private function render_template()
|
||||
{
|
||||
$target = $this->tool_path.$this->template.'.php';
|
||||
if (file_exists($target)) {
|
||||
ob_start();
|
||||
@extract($this->data, EXTR_OVERWRITE); //pass the $this->data array into local scope
|
||||
require_once $target;
|
||||
$content = ob_get_clean();
|
||||
|
||||
return $content;
|
||||
} else {
|
||||
throw new Exception('View::render_template() invalid file path '.$target);
|
||||
}
|
||||
}
|
||||
}
|
||||
152
main/inc/lib/array.lib.php
Normal file
152
main/inc/lib/array.lib.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/**
|
||||
* This is the array library for Chamilo.
|
||||
* Include/require it in your code to use its functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes duplicate values from a dimensional array.
|
||||
*
|
||||
* @param array $array dimensional array
|
||||
*
|
||||
* @return array an array with unique values
|
||||
*/
|
||||
function array_unique_dimensional($array)
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
foreach ($array as &$myvalue) {
|
||||
$myvalue = serialize($myvalue);
|
||||
}
|
||||
|
||||
$array = array_unique($array);
|
||||
|
||||
foreach ($array as &$myvalue) {
|
||||
$myvalue = UnserializeApi::unserialize('not_allowed_clases', $myvalue);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort multidimensional arrays.
|
||||
*
|
||||
* @param array unsorted multidimensional array
|
||||
* @param string key to be sorted
|
||||
*
|
||||
* @return array result array
|
||||
*
|
||||
* @author found in http://php.net/manual/en/function.sort.php
|
||||
*/
|
||||
function msort($array, $id = 'id', $order = 'desc')
|
||||
{
|
||||
if (empty($array)) {
|
||||
return $array;
|
||||
}
|
||||
$temp_array = [];
|
||||
while (count($array) > 0) {
|
||||
$lowest_id = 0;
|
||||
$index = 0;
|
||||
foreach ($array as $item) {
|
||||
if ('desc' == $order) {
|
||||
if (strip_tags($item[$id]) < strip_tags($array[$lowest_id][$id])) {
|
||||
$lowest_id = $index;
|
||||
}
|
||||
} else {
|
||||
if (isset($item[$id]) && strip_tags($item[$id]) > strip_tags($array[$lowest_id][$id])) {
|
||||
$lowest_id = $index;
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
$temp_array[] = $array[$lowest_id];
|
||||
$array = array_merge(
|
||||
array_slice($array, 0, $lowest_id),
|
||||
array_slice($array, $lowest_id + 1)
|
||||
);
|
||||
}
|
||||
|
||||
return $temp_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function utf8_sort($array)
|
||||
{
|
||||
$old_locale = setlocale(LC_ALL, 0);
|
||||
$code = api_get_language_isocode();
|
||||
$locale_list = [$code.'.utf8', 'en.utf8', 'en_US.utf8', 'en_GB.utf8'];
|
||||
$try_sort = false;
|
||||
|
||||
foreach ($locale_list as $locale) {
|
||||
$my_local = setlocale(LC_COLLATE, $locale);
|
||||
if ($my_local) {
|
||||
$try_sort = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($try_sort) {
|
||||
uasort($array, 'strcoll');
|
||||
}
|
||||
setlocale(LC_COLLATE, $old_locale);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @param string $separator
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function array_to_string($array, $separator = ',')
|
||||
{
|
||||
if (empty($array)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return implode($separator.' ', $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
function array_flatten(array $array)
|
||||
{
|
||||
$flatten = [];
|
||||
array_walk_recursive(
|
||||
$array,
|
||||
function ($value) use (&$flatten) {
|
||||
$flatten[] = $value;
|
||||
}
|
||||
);
|
||||
|
||||
return $flatten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffles an array keeping the associations.
|
||||
*
|
||||
* @param $array
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function shuffle_assoc(&$array)
|
||||
{
|
||||
$keys = array_keys($array);
|
||||
shuffle($keys);
|
||||
$new = [];
|
||||
foreach ($keys as $key) {
|
||||
$new[$key] = $array[$key];
|
||||
}
|
||||
$array = $new;
|
||||
|
||||
return true;
|
||||
}
|
||||
2958
main/inc/lib/attendance.lib.php
Normal file
2958
main/inc/lib/attendance.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
399
main/inc/lib/auth.lib.php
Normal file
399
main/inc/lib/auth.lib.php
Normal file
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class Auth
|
||||
* Auth can be used to instantiate objects or as a library to manage courses
|
||||
* This file contains a class used like library provides functions for auth tool.
|
||||
* It's also used like model to courses_controller (MVC pattern).
|
||||
*
|
||||
* @author Christian Fasanando <christian1827@gmail.com>
|
||||
*/
|
||||
class Auth
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get all the courses in the particular user category.
|
||||
*
|
||||
* @param bool $hidePrivate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCoursesInCategory($hidePrivate = true)
|
||||
{
|
||||
$user_id = api_get_user_id();
|
||||
|
||||
$TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition();
|
||||
$showCoursesCondition = CoursesAndSessionsCatalog::getCoursesToShowInCatalogueCondition();
|
||||
$visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true, $hidePrivate);
|
||||
|
||||
$sql = "SELECT
|
||||
course.id as real_id,
|
||||
course.code, course.visual_code, course.subscribe subscr, course.unsubscribe unsubscr,
|
||||
course.title title, course.tutor_name tutor, course.directory, course_rel_user.status status,
|
||||
course_rel_user.sort sort, course_rel_user.user_course_cat user_course_cat
|
||||
FROM $TABLECOURS course,
|
||||
$TABLECOURSUSER course_rel_user
|
||||
WHERE
|
||||
course.id = course_rel_user.c_id AND
|
||||
course_rel_user.user_id = '".$user_id."' AND
|
||||
course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."
|
||||
$avoidCoursesCondition
|
||||
$showCoursesCondition
|
||||
$visibilityCondition
|
||||
ORDER BY course_rel_user.user_course_cat, course_rel_user.sort ASC";
|
||||
$result = Database::query($sql);
|
||||
$data = [];
|
||||
while ($course = Database::fetch_array($result)) {
|
||||
$data[$course['user_course_cat']][] = $course;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* stores the changes in a course category
|
||||
* (moving a course to a different course category).
|
||||
*
|
||||
* @param int $courseId
|
||||
* @param int Category id
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function updateCourseCategory($courseId, $newcategory)
|
||||
{
|
||||
$courseId = (int) $courseId;
|
||||
$newcategory = (int) $newcategory;
|
||||
$current_user = api_get_user_id();
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$max_sort_value = api_max_sort_value($newcategory, $current_user);
|
||||
$sql = "UPDATE $table SET
|
||||
user_course_cat='".$newcategory."',
|
||||
sort='".($max_sort_value + 1)."'
|
||||
WHERE
|
||||
c_id ='".$courseId."' AND
|
||||
user_id='".$current_user."' AND
|
||||
relation_type<>".COURSE_RELATION_TYPE_RRHH;
|
||||
$resultQuery = Database::query($sql);
|
||||
|
||||
$result = false;
|
||||
if (Database::affected_rows($resultQuery)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* moves the course one place up or down.
|
||||
*
|
||||
* @param string Direction (up/down)
|
||||
* @param string Course code
|
||||
* @param int Category id
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function move_course($direction, $course2move, $category)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
|
||||
$current_user_id = api_get_user_id();
|
||||
$all_user_courses = CourseManager::getCoursesByUserCourseCategory($current_user_id);
|
||||
|
||||
// we need only the courses of the category we are moving in
|
||||
$user_courses = [];
|
||||
foreach ($all_user_courses as $key => $course) {
|
||||
if ($course['user_course_category'] == $category) {
|
||||
$user_courses[] = $course;
|
||||
}
|
||||
}
|
||||
|
||||
$target_course = [];
|
||||
foreach ($user_courses as $count => $course) {
|
||||
if ($course2move == $course['code']) {
|
||||
// source_course is the course where we clicked the up or down icon
|
||||
$source_course = $course;
|
||||
// target_course is the course before/after the source_course (depending on the up/down icon)
|
||||
if ('up' == $direction) {
|
||||
$target_course = $user_courses[$count - 1];
|
||||
} else {
|
||||
$target_course = $user_courses[$count + 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result = false;
|
||||
if (count($target_course) > 0 && count($source_course) > 0) {
|
||||
$courseInfo = api_get_course_info($source_course['code']);
|
||||
$courseId = $courseInfo['real_id'];
|
||||
|
||||
$targetCourseInfo = api_get_course_info($target_course['code']);
|
||||
$targetCourseId = $targetCourseInfo['real_id'];
|
||||
|
||||
$sql = "UPDATE $table
|
||||
SET sort='".$target_course['sort']."'
|
||||
WHERE
|
||||
c_id = '".$courseId."' AND
|
||||
user_id = '".$current_user_id."' AND
|
||||
relation_type<>".COURSE_RELATION_TYPE_RRHH;
|
||||
|
||||
$result1 = Database::query($sql);
|
||||
|
||||
$sql = "UPDATE $table SET sort='".$source_course['sort']."'
|
||||
WHERE
|
||||
c_id ='".$targetCourseId."' AND
|
||||
user_id='".$current_user_id."' AND
|
||||
relation_type<>".COURSE_RELATION_TYPE_RRHH;
|
||||
|
||||
$result2 = Database::query($sql);
|
||||
|
||||
if (Database::affected_rows($result1) && Database::affected_rows($result2)) {
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the course one place up or down.
|
||||
*
|
||||
* @param string $direction Direction up/down
|
||||
* @param string $category2move Category id
|
||||
*
|
||||
* @return bool True If it success
|
||||
*/
|
||||
public function move_category($direction, $category2move)
|
||||
{
|
||||
$userId = api_get_user_id();
|
||||
$userCategories = CourseManager::get_user_course_categories($userId);
|
||||
$categories = array_values($userCategories);
|
||||
|
||||
$previous = null;
|
||||
$target_category = [];
|
||||
foreach ($categories as $key => $category) {
|
||||
$category_id = $category['id'];
|
||||
if ($category2move == $category_id) {
|
||||
// source_course is the course where we clicked the up or down icon
|
||||
$source_category = $userCategories[$category2move];
|
||||
// target_course is the course before/after the source_course (depending on the up/down icon)
|
||||
if ('up' == $direction) {
|
||||
if (isset($categories[$key - 1])) {
|
||||
$target_category = $userCategories[$categories[$key - 1]['id']];
|
||||
}
|
||||
} else {
|
||||
if (isset($categories[$key + 1])) {
|
||||
$target_category = $userCategories[$categories[$key + 1]['id']];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = false;
|
||||
if (count($target_category) > 0 && count($source_category) > 0) {
|
||||
$table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
|
||||
$sql = "UPDATE $table SET
|
||||
sort = '".Database::escape_string($target_category['sort'])."'
|
||||
WHERE id='".intval($source_category['id'])."' AND user_id='".$userId."'";
|
||||
$resultFirst = Database::query($sql);
|
||||
$sql = "UPDATE $table SET
|
||||
sort = '".Database::escape_string($source_category['sort'])."'
|
||||
WHERE id='".intval($target_category['id'])."' AND user_id='".$userId."'";
|
||||
$resultSecond = Database::query($sql);
|
||||
if (Database::affected_rows($resultFirst) && Database::affected_rows($resultSecond)) {
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the user course category in the chamilo_user database.
|
||||
*
|
||||
* @param string Category title
|
||||
* @param int Category id
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function store_edit_course_category($title, $category_id)
|
||||
{
|
||||
$title = Database::escape_string($title);
|
||||
$category_id = (int) $category_id;
|
||||
$result = false;
|
||||
$table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
|
||||
$sql = "UPDATE $table
|
||||
SET title='".api_htmlentities($title, ENT_QUOTES, api_get_system_encoding())."'
|
||||
WHERE id='".$category_id."'";
|
||||
$resultQuery = Database::query($sql);
|
||||
if (Database::affected_rows($resultQuery)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a course category and moves all the courses that were in this category to main category.
|
||||
*
|
||||
* @param int Category id
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function delete_course_category($category_id)
|
||||
{
|
||||
$current_user_id = api_get_user_id();
|
||||
$tucc = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
|
||||
$TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
$category_id = (int) $category_id;
|
||||
$result = false;
|
||||
$sql = "DELETE FROM $tucc
|
||||
WHERE
|
||||
id='".$category_id."' AND
|
||||
user_id='".$current_user_id."'";
|
||||
$resultQuery = Database::query($sql);
|
||||
if (Database::affected_rows($resultQuery)) {
|
||||
$result = true;
|
||||
}
|
||||
$sql = "UPDATE $TABLECOURSUSER
|
||||
SET user_course_cat='0'
|
||||
WHERE
|
||||
user_course_cat='".$category_id."' AND
|
||||
user_id='".$current_user_id."' AND
|
||||
relation_type<>".COURSE_RELATION_TYPE_RRHH." ";
|
||||
Database::query($sql);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $categoryId
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getUserCourseCategory($categoryId)
|
||||
{
|
||||
$userId = api_get_user_id();
|
||||
$tucc = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
|
||||
$categoryId = (int) $categoryId;
|
||||
|
||||
$sql = "SELECT * FROM $tucc
|
||||
WHERE
|
||||
id= $categoryId AND
|
||||
user_id= $userId";
|
||||
$resultQuery = Database::query($sql);
|
||||
|
||||
return Database::fetch_array($resultQuery, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* unsubscribe the user from a given course.
|
||||
*
|
||||
* @param string $course_code
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function remove_user_from_course($course_code, $sessionId = 0)
|
||||
{
|
||||
$tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
|
||||
|
||||
// protect variables
|
||||
$current_user_id = api_get_user_id();
|
||||
$course_code = Database::escape_string($course_code);
|
||||
|
||||
$courseInfo = api_get_course_info($course_code);
|
||||
|
||||
if (empty($courseInfo) || empty($current_user_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if course can be unsubscribe.
|
||||
if ('1' !== $courseInfo['unsubscribe']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$courseId = $courseInfo['real_id'];
|
||||
|
||||
// we check (once again) if the user is not course administrator
|
||||
// because the course administrator cannot unsubscribe himself
|
||||
// (s)he can only delete the course
|
||||
$sql = "SELECT * FROM $tbl_course_user
|
||||
WHERE
|
||||
user_id='".$current_user_id."' AND
|
||||
c_id ='".$courseId."' AND
|
||||
status='1' ";
|
||||
$result_check = Database::query($sql);
|
||||
$number_of_rows = Database::num_rows($result_check);
|
||||
|
||||
$result = true;
|
||||
if ($number_of_rows > 0) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
CourseManager::unsubscribe_user($current_user_id, $course_code, $sessionId);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* stores the user course category in the chamilo_user database.
|
||||
*
|
||||
* @param string Category title
|
||||
*
|
||||
* @return bool True if it success
|
||||
*/
|
||||
public function store_course_category($category_title)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY);
|
||||
|
||||
// protect data
|
||||
$current_user_id = api_get_user_id();
|
||||
$category_title = Database::escape_string($category_title);
|
||||
|
||||
// step 1: we determine the max value of the user defined course categories
|
||||
$sql = "SELECT sort FROM $table
|
||||
WHERE user_id='".$current_user_id."'
|
||||
ORDER BY sort DESC";
|
||||
$rs_sort = Database::query($sql);
|
||||
$maxsort = Database::fetch_array($rs_sort);
|
||||
$nextsort = $maxsort['sort'] + 1;
|
||||
|
||||
// step 2: we check if there is already a category with this name,
|
||||
// if not we store it, else we give an error.
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE
|
||||
user_id='".$current_user_id."' AND
|
||||
title='".$category_title."'
|
||||
ORDER BY sort DESC";
|
||||
$rs = Database::query($sql);
|
||||
|
||||
$result = false;
|
||||
if (0 == Database::num_rows($rs)) {
|
||||
$sql = "INSERT INTO $table (user_id, title,sort)
|
||||
VALUES ('".$current_user_id."', '".api_htmlentities(
|
||||
$category_title,
|
||||
ENT_QUOTES,
|
||||
api_get_system_encoding()
|
||||
)."', '".$nextsort."')";
|
||||
$resultQuery = Database::query($sql);
|
||||
if (Database::affected_rows($resultQuery)) {
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
176
main/inc/lib/baker.lib.php
Normal file
176
main/inc/lib/baker.lib.php
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Php library to Bake the PNG Images.
|
||||
*/
|
||||
class PNGImageBaker
|
||||
{
|
||||
private $_contents;
|
||||
private $_size;
|
||||
private $_chunks;
|
||||
|
||||
/**
|
||||
* Prepares file for handling metadata.
|
||||
* Verifies that this file is a valid PNG file.
|
||||
* Unpacks file chunks and reads them into an array.
|
||||
*
|
||||
* @param string $contents File content as a string
|
||||
*/
|
||||
public function __construct($contents)
|
||||
{
|
||||
$this->_contents = $contents;
|
||||
$png_signature = pack("C8", 137, 80, 78, 71, 13, 10, 26, 10);
|
||||
// Read 8 bytes of PNG header and verify.
|
||||
$header = substr($this->_contents, 0, 8);
|
||||
if ($header != $png_signature) {
|
||||
echo 'This is not a valid PNG image';
|
||||
}
|
||||
$this->_size = strlen($this->_contents);
|
||||
$this->_chunks = [];
|
||||
// Skip 8 bytes of IHDR image header.
|
||||
$position = 8;
|
||||
do {
|
||||
$chunk = @unpack('Nsize/a4type', substr($this->_contents, $position, 8));
|
||||
$this->_chunks[$chunk['type']][] = substr($this->_contents, $position + 8, $chunk['size']);
|
||||
// Skip 12 bytes chunk overhead.
|
||||
$position += $chunk['size'] + 12;
|
||||
} while ($position < $this->_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a key already exists in the chunk of said type.
|
||||
* We need to avoid writing same keyword into file chunks.
|
||||
*
|
||||
* @param string $type chunk type, like iTXt, tEXt, etc
|
||||
* @param string $check keyword that needs to be checked
|
||||
*
|
||||
* @return bool (true|false) True if file is safe to write this keyword, false otherwise
|
||||
*/
|
||||
public function checkChunks($type, $check)
|
||||
{
|
||||
if (array_key_exists($type, $this->_chunks)) {
|
||||
foreach (array_keys($this->_chunks[$type]) as $typekey) {
|
||||
list($key, $data) = explode("\0", $this->_chunks[$type][$typekey]);
|
||||
if (0 == strcmp($key, $check)) {
|
||||
echo 'Key "'.$check.'" already exists in "'.$type.'" chunk.';
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a chunk by type with given key and text.
|
||||
*
|
||||
* @param string $chunkType chunk type, like iTXt, tEXt, etc
|
||||
* @param string $key keyword that needs to be added
|
||||
* @param string $value currently an assertion URL that is added to an image metadata
|
||||
*
|
||||
* @return string $result file content with a new chunk as a string
|
||||
*/
|
||||
public function addChunk($chunkType, $key, $value)
|
||||
{
|
||||
$chunkData = $key."\0".$value;
|
||||
$crc = pack("N", crc32($chunkType.$chunkData));
|
||||
$len = pack("N", strlen($chunkData));
|
||||
|
||||
$newChunk = $len.$chunkType.$chunkData.$crc;
|
||||
$result = substr($this->_contents, 0, $this->_size - 12)
|
||||
.$newChunk
|
||||
.substr($this->_contents, $this->_size - 12, 12);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a chunk by type with given key and text.
|
||||
*
|
||||
* @param string $chunkType chunk type, like iTXt, tEXt, etc
|
||||
* @param string $key keyword that needs to be deleted
|
||||
* @param string $png the png image
|
||||
*
|
||||
* @return string $result new File content
|
||||
*/
|
||||
public function removeChunks($chunkType, $key, $png)
|
||||
{
|
||||
// Read the magic bytes and verify
|
||||
$retval = substr($png, 0, 8);
|
||||
$ipos = 8;
|
||||
if ($retval != "\x89PNG\x0d\x0a\x1a\x0a") {
|
||||
throw new Exception('Is not a valid PNG image');
|
||||
}
|
||||
// Loop through the chunks. Byte 0-3 is length, Byte 4-7 is type
|
||||
$chunkHeader = substr($png, $ipos, 8);
|
||||
$ipos = $ipos + 8;
|
||||
while ($chunkHeader) {
|
||||
// Extract length and type from binary data
|
||||
$chunk = @unpack('Nsize/a4type', $chunkHeader);
|
||||
$skip = false;
|
||||
if ($chunk['type'] == $chunkType) {
|
||||
$data = substr($png, $ipos, $chunk['size']);
|
||||
$sections = explode("\0", $data);
|
||||
print_r($sections);
|
||||
if ($sections[0] == $key) {
|
||||
$skip = true;
|
||||
}
|
||||
}
|
||||
// Extract the data and the CRC
|
||||
$data = substr($png, $ipos, $chunk['size'] + 4);
|
||||
$ipos = $ipos + $chunk['size'] + 4;
|
||||
// Add in the header, data, and CRC
|
||||
if (!$skip) {
|
||||
$retval = $retval.$chunkHeader.$data;
|
||||
}
|
||||
// Read next chunk header
|
||||
$chunkHeader = substr($png, $ipos, 8);
|
||||
$ipos = $ipos + 8;
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the baked PNG info by the Key.
|
||||
*
|
||||
* @param string $png the png image
|
||||
* @param string $key keyword that needs to be searched
|
||||
*
|
||||
* @return mixed - If there is an error - boolean false is returned
|
||||
* If there is PNG information that matches the key an array is returned
|
||||
*/
|
||||
public function extractBadgeInfo($png, $key = 'openbadges')
|
||||
{
|
||||
// Read the magic bytes and verify
|
||||
$retval = substr($png, 0, 8);
|
||||
$ipos = 8;
|
||||
if ("\x89PNG\x0d\x0a\x1a\x0a" != $retval) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loop through the chunks. Byte 0-3 is length, Byte 4-7 is type
|
||||
$chunkHeader = substr($png, $ipos, 8);
|
||||
$ipos = $ipos + 8;
|
||||
while ($chunkHeader) {
|
||||
// Extract length and type from binary data
|
||||
$chunk = @unpack('Nsize/a4type', $chunkHeader);
|
||||
$skip = false;
|
||||
if ('tEXt' == $chunk['type']) {
|
||||
$data = substr($png, $ipos, $chunk['size']);
|
||||
$sections = explode("\0", $data);
|
||||
if ($sections[0] == $key) {
|
||||
return $sections;
|
||||
}
|
||||
}
|
||||
// Extract the data and the CRC
|
||||
$data = substr($png, $ipos, $chunk['size'] + 4);
|
||||
$ipos = $ipos + $chunk['size'] + 4;
|
||||
|
||||
// Read next chunk header
|
||||
$chunkHeader = substr($png, $ipos, 8);
|
||||
$ipos = $ipos + 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
1085
main/inc/lib/banner.lib.php
Normal file
1085
main/inc/lib/banner.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
3306
main/inc/lib/blog.lib.php
Normal file
3306
main/inc/lib/blog.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
1221
main/inc/lib/browser/Browser.php
Normal file
1221
main/inc/lib/browser/Browser.php
Normal file
File diff suppressed because it is too large
Load Diff
1570
main/inc/lib/career.lib.php
Normal file
1570
main/inc/lib/career.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
955
main/inc/lib/certificate.lib.php
Normal file
955
main/inc/lib/certificate.lib.php
Normal file
@@ -0,0 +1,955 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Endroid\QrCode\ErrorCorrectionLevel;
|
||||
use Endroid\QrCode\QrCode;
|
||||
|
||||
/**
|
||||
* Certificate Class
|
||||
* Generate certificates based in the gradebook tool.
|
||||
*/
|
||||
class Certificate extends Model
|
||||
{
|
||||
public $table;
|
||||
public $columns = [
|
||||
'id',
|
||||
'cat_id',
|
||||
'score_certificate',
|
||||
'created_at',
|
||||
'path_certificate',
|
||||
];
|
||||
/**
|
||||
* Certification data.
|
||||
*/
|
||||
public $certificate_data = [];
|
||||
|
||||
/**
|
||||
* Student's certification path.
|
||||
*/
|
||||
public $certification_user_path = null;
|
||||
public $certification_web_user_path = null;
|
||||
public $html_file = null;
|
||||
public $qr_file = null;
|
||||
public $user_id;
|
||||
|
||||
/** If true every time we enter to the certificate URL
|
||||
* we would generate a new certificate (good thing because we can edit the
|
||||
* certificate and all users will have the latest certificate bad because we.
|
||||
* load the certificate every time */
|
||||
public $force_certificate_generation = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $certificate_id ID of the certificate
|
||||
* @param int $userId
|
||||
* @param bool $sendNotification send message to student
|
||||
* @param bool $updateCertificateData
|
||||
*
|
||||
* If no ID given, take user_id and try to generate one
|
||||
*/
|
||||
public function __construct(
|
||||
$certificate_id = 0,
|
||||
$userId = 0,
|
||||
$sendNotification = false,
|
||||
$updateCertificateData = true
|
||||
) {
|
||||
$this->table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
|
||||
$this->user_id = !empty($userId) ? $userId : api_get_user_id();
|
||||
|
||||
if (!empty($certificate_id)) {
|
||||
$certificate = $this->get($certificate_id);
|
||||
if (!empty($certificate) && is_array($certificate)) {
|
||||
$this->certificate_data = $certificate;
|
||||
$this->user_id = $this->certificate_data['user_id'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->user_id) {
|
||||
// Need to be called before any operation
|
||||
$this->check_certificate_path();
|
||||
// To force certification generation
|
||||
if ($this->force_certificate_generation) {
|
||||
$this->generate([], $sendNotification);
|
||||
}
|
||||
if (isset($this->certificate_data) && $this->certificate_data) {
|
||||
if (empty($this->certificate_data['path_certificate'])) {
|
||||
$this->generate([], $sendNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setting the qr and html variables
|
||||
if (isset($certificate_id) &&
|
||||
!empty($this->certification_user_path) &&
|
||||
isset($this->certificate_data['path_certificate'])
|
||||
) {
|
||||
$pathinfo = pathinfo($this->certificate_data['path_certificate']);
|
||||
$this->html_file = $this->certification_user_path.basename($this->certificate_data['path_certificate']);
|
||||
$this->qr_file = $this->certification_user_path.$pathinfo['filename'].'_qr.png';
|
||||
} else {
|
||||
$this->check_certificate_path();
|
||||
if (api_get_configuration_value('allow_general_certificate')) {
|
||||
// General certificate
|
||||
$name = md5($this->user_id).'.html';
|
||||
$my_path_certificate = $this->certification_user_path.$name;
|
||||
$path_certificate = '/'.$name;
|
||||
|
||||
// Getting QR filename
|
||||
$file_info = pathinfo($path_certificate);
|
||||
$content = $this->generateCustomCertificate();
|
||||
|
||||
$my_new_content_html = str_replace(
|
||||
'((certificate_barcode))',
|
||||
Display::img(
|
||||
$this->certification_web_user_path.$file_info['filename'].'_qr.png',
|
||||
'QR'
|
||||
),
|
||||
$content
|
||||
);
|
||||
|
||||
$my_new_content_html = mb_convert_encoding(
|
||||
$my_new_content_html,
|
||||
'UTF-8',
|
||||
api_get_system_encoding()
|
||||
);
|
||||
|
||||
$this->html_file = $my_path_certificate;
|
||||
$result = @file_put_contents($my_path_certificate, $my_new_content_html);
|
||||
|
||||
if ($result) {
|
||||
// Updating the path
|
||||
self::updateUserCertificateInfo(
|
||||
0,
|
||||
$this->user_id,
|
||||
$path_certificate,
|
||||
$updateCertificateData
|
||||
);
|
||||
$this->certificate_data['path_certificate'] = $path_certificate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the certificate user path directory is created.
|
||||
*/
|
||||
public function check_certificate_path()
|
||||
{
|
||||
$this->certification_user_path = null;
|
||||
|
||||
// Setting certification path
|
||||
$path_info = UserManager::getUserPathById($this->user_id, 'system');
|
||||
$web_path_info = UserManager::getUserPathById($this->user_id, 'web');
|
||||
|
||||
if (!empty($path_info) && isset($path_info)) {
|
||||
$this->certification_user_path = $path_info.'certificate/';
|
||||
$this->certification_web_user_path = $web_path_info.'certificate/';
|
||||
$mode = api_get_permissions_for_new_directories();
|
||||
if (!is_dir($path_info)) {
|
||||
mkdir($path_info, $mode, true);
|
||||
}
|
||||
if (!is_dir($this->certification_user_path)) {
|
||||
mkdir($this->certification_user_path, $mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the current certificate object. This is generally triggered by
|
||||
* the teacher from the gradebook tool to re-generate the certificate because
|
||||
* the original version wa flawed.
|
||||
*
|
||||
* @param bool $force_delete
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($force_delete = false)
|
||||
{
|
||||
$delete_db = false;
|
||||
if (!empty($this->certificate_data)) {
|
||||
if (!is_null($this->html_file) || $this->html_file != '' || strlen($this->html_file)) {
|
||||
// Deleting HTML file
|
||||
if (is_file($this->html_file)) {
|
||||
@unlink($this->html_file);
|
||||
if (is_file($this->html_file) === false) {
|
||||
$delete_db = true;
|
||||
} else {
|
||||
$delete_db = false;
|
||||
}
|
||||
}
|
||||
// Deleting QR code PNG image file
|
||||
if (is_file($this->qr_file)) {
|
||||
@unlink($this->qr_file);
|
||||
}
|
||||
if ($delete_db || $force_delete) {
|
||||
return parent::delete($this->certificate_data['id']);
|
||||
}
|
||||
} else {
|
||||
return parent::delete($this->certificate_data['id']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an HTML Certificate and fills the path_certificate field in the DB.
|
||||
*
|
||||
* @param array $params
|
||||
* @param bool $sendNotification
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
public function generate($params = [], $sendNotification = false)
|
||||
{
|
||||
// The user directory should be set
|
||||
if (empty($this->certification_user_path) &&
|
||||
$this->force_certificate_generation === false
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$params['hide_print_button'] = isset($params['hide_print_button']) ? true : false;
|
||||
$categoryId = 0;
|
||||
$my_category = [];
|
||||
if (isset($this->certificate_data) && isset($this->certificate_data['cat_id'])) {
|
||||
$categoryId = $this->certificate_data['cat_id'];
|
||||
$my_category = Category::load($categoryId);
|
||||
}
|
||||
|
||||
if (isset($my_category[0]) && !empty($categoryId) &&
|
||||
$my_category[0]->is_certificate_available($this->user_id)
|
||||
) {
|
||||
/** @var Category $category */
|
||||
$category = $my_category[0];
|
||||
|
||||
$courseInfo = api_get_course_info($category->get_course_code());
|
||||
$courseId = $courseInfo['real_id'];
|
||||
$sessionId = $category->get_session_id();
|
||||
|
||||
$skill = new Skill();
|
||||
$skill->addSkillToUser(
|
||||
$this->user_id,
|
||||
$category,
|
||||
$courseId,
|
||||
$sessionId
|
||||
);
|
||||
|
||||
if (is_dir($this->certification_user_path)) {
|
||||
if (!empty($this->certificate_data)) {
|
||||
$new_content_html = GradebookUtils::get_user_certificate_content(
|
||||
$this->user_id,
|
||||
$category->get_course_code(),
|
||||
$category->get_session_id(),
|
||||
false,
|
||||
$params['hide_print_button']
|
||||
);
|
||||
|
||||
if ($category->get_id() == $categoryId) {
|
||||
$name = $this->certificate_data['path_certificate'];
|
||||
$myPathCertificate = $this->certification_user_path.basename($name);
|
||||
|
||||
if (file_exists($myPathCertificate) &&
|
||||
!empty($name) &&
|
||||
!is_dir($myPathCertificate) &&
|
||||
$this->force_certificate_generation == false
|
||||
) {
|
||||
// Seems that the file was already generated
|
||||
return true;
|
||||
} else {
|
||||
// Creating new name
|
||||
$name = md5($this->user_id.$this->certificate_data['cat_id']).'.html';
|
||||
$myPathCertificate = $this->certification_user_path.$name;
|
||||
$path_certificate = '/'.$name;
|
||||
|
||||
// Getting QR filename
|
||||
$file_info = pathinfo($path_certificate);
|
||||
$qr_code_filename = $this->certification_user_path.$file_info['filename'].'_qr.png';
|
||||
|
||||
$newContent = str_replace(
|
||||
'((certificate_barcode))',
|
||||
Display::img(
|
||||
$this->certification_web_user_path.$file_info['filename'].'_qr.png',
|
||||
'QR'
|
||||
),
|
||||
$new_content_html['content']
|
||||
);
|
||||
|
||||
$newContent = api_convert_encoding(
|
||||
$newContent,
|
||||
'UTF-8',
|
||||
api_get_system_encoding()
|
||||
);
|
||||
|
||||
$result = @file_put_contents($myPathCertificate, $newContent);
|
||||
if ($result) {
|
||||
// Updating the path
|
||||
$this->updateUserCertificateInfo(
|
||||
$this->certificate_data['cat_id'],
|
||||
$this->user_id,
|
||||
$path_certificate
|
||||
);
|
||||
$this->certificate_data['path_certificate'] = $path_certificate;
|
||||
|
||||
if ($this->isHtmlFileGenerated()) {
|
||||
if (!empty($file_info)) {
|
||||
$text = $this->parseCertificateVariables(
|
||||
$new_content_html['variables']
|
||||
);
|
||||
$this->generateQRImage(
|
||||
$text,
|
||||
$qr_code_filename
|
||||
);
|
||||
|
||||
if ($sendNotification) {
|
||||
$subject = get_lang('NotificationCertificateSubject');
|
||||
$message = nl2br(get_lang('NotificationCertificateTemplate'));
|
||||
$score = $this->certificate_data['score_certificate'];
|
||||
self::sendNotification(
|
||||
$subject,
|
||||
$message,
|
||||
api_get_user_info($this->user_id),
|
||||
$courseInfo,
|
||||
[
|
||||
'score_certificate' => $score,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->check_certificate_path();
|
||||
|
||||
// General certificate
|
||||
$name = md5($this->user_id).'.html';
|
||||
$my_path_certificate = $this->certification_user_path.$name;
|
||||
$path_certificate = '/'.$name;
|
||||
|
||||
// Getting QR filename
|
||||
$file_info = pathinfo($path_certificate);
|
||||
$content = $this->generateCustomCertificate();
|
||||
|
||||
$my_new_content_html = str_replace(
|
||||
'((certificate_barcode))',
|
||||
Display::img(
|
||||
$this->certification_web_user_path.$file_info['filename'].'_qr.png',
|
||||
'QR'
|
||||
),
|
||||
$content
|
||||
);
|
||||
|
||||
$my_new_content_html = mb_convert_encoding(
|
||||
$my_new_content_html,
|
||||
'UTF-8',
|
||||
api_get_system_encoding()
|
||||
);
|
||||
|
||||
$result = @file_put_contents($my_path_certificate, $my_new_content_html);
|
||||
|
||||
if ($result) {
|
||||
// Updating the path
|
||||
self::updateUserCertificateInfo(
|
||||
0,
|
||||
$this->user_id,
|
||||
$path_certificate
|
||||
);
|
||||
$this->certificate_data['path_certificate'] = $path_certificate;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function notificationTags()
|
||||
{
|
||||
$tags = [
|
||||
'((course_title))',
|
||||
'((user_first_name))',
|
||||
'((user_last_name))',
|
||||
'((author_first_name))',
|
||||
'((author_last_name))',
|
||||
'((score))',
|
||||
'((portal_name))',
|
||||
'((certificate_link))',
|
||||
];
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $subject
|
||||
* @param string $message
|
||||
* @param array $userInfo
|
||||
* @param array $courseInfo
|
||||
* @param array $certificateInfo
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function sendNotification(
|
||||
$subject,
|
||||
$message,
|
||||
$userInfo,
|
||||
$courseInfo,
|
||||
$certificateInfo
|
||||
) {
|
||||
if (empty($userInfo) || empty($courseInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentUserInfo = api_get_user_info();
|
||||
$url = api_get_path(WEB_PATH).
|
||||
'certificates/index.php?id='.$certificateInfo['id'].'&user_id='.$certificateInfo['user_id'];
|
||||
$link = Display::url($url, $url);
|
||||
|
||||
$replace = [
|
||||
$courseInfo['title'],
|
||||
$userInfo['firstname'],
|
||||
$userInfo['lastname'],
|
||||
$currentUserInfo['firstname'],
|
||||
$currentUserInfo['lastname'],
|
||||
$certificateInfo['score_certificate'],
|
||||
api_get_setting('Institution'),
|
||||
$link,
|
||||
];
|
||||
|
||||
$message = str_replace(self::notificationTags(), $replace, $message);
|
||||
MessageManager::send_message(
|
||||
$userInfo['id'],
|
||||
$subject,
|
||||
$message,
|
||||
[],
|
||||
[],
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
$currentUserInfo['id']
|
||||
);
|
||||
|
||||
$plugin = new AppPlugin();
|
||||
$smsPlugin = $plugin->getSMSPluginLibrary();
|
||||
if ($smsPlugin) {
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::CERTIFICATE_NOTIFICATION,
|
||||
'userId' => $userInfo['id'],
|
||||
'direct_message' => $message,
|
||||
];
|
||||
$smsPlugin->send($additionalParameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user info about certificate.
|
||||
*
|
||||
* @param int $categoryId category id
|
||||
* @param int $user_id user id
|
||||
* @param string $path_certificate the path name of the certificate
|
||||
* @param bool $updateCertificateData
|
||||
*/
|
||||
public function updateUserCertificateInfo(
|
||||
$categoryId,
|
||||
$user_id,
|
||||
$path_certificate,
|
||||
$updateCertificateData = true
|
||||
) {
|
||||
$categoryId = (int) $categoryId;
|
||||
$user_id = (int) $user_id;
|
||||
|
||||
if ($updateCertificateData &&
|
||||
!UserManager::is_user_certified($categoryId, $user_id)
|
||||
) {
|
||||
$table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
|
||||
$now = api_get_utc_datetime();
|
||||
$sql = 'UPDATE '.$table.' SET
|
||||
path_certificate="'.Database::escape_string($path_certificate).'",
|
||||
created_at = "'.$now.'"
|
||||
WHERE cat_id = "'.$categoryId.'" AND user_id="'.$user_id.'" ';
|
||||
Database::query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file was generated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isHtmlFileGenerated()
|
||||
{
|
||||
if (empty($this->certification_user_path)) {
|
||||
return false;
|
||||
}
|
||||
if (!empty($this->certificate_data) &&
|
||||
isset($this->certificate_data['path_certificate']) &&
|
||||
!empty($this->certificate_data['path_certificate'])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a QR code for the certificate. The QR code embeds the text given.
|
||||
*
|
||||
* @param string $text Text to be added in the QR code
|
||||
* @param string $path file path of the image
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function generateQRImage($text, $path)
|
||||
{
|
||||
if (!empty($text) && !empty($path)) {
|
||||
$qrCode = new QrCode($text);
|
||||
//$qrCode->setEncoding('UTF-8');
|
||||
$qrCode->setSize(120);
|
||||
$qrCode->setMargin(5);
|
||||
$qrCode->setWriterByName('png');
|
||||
$qrCode->setErrorCorrectionLevel(ErrorCorrectionLevel::MEDIUM);
|
||||
$qrCode->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0]);
|
||||
$qrCode->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);
|
||||
$qrCode->setValidateResult(false);
|
||||
$qrCode->writeFile($path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms certificate tags into text values. This function is very static
|
||||
* (it doesn't allow for much flexibility in terms of what tags are printed).
|
||||
*
|
||||
* @param array $array Contains two array entries: first are the headers,
|
||||
* second is an array of contents
|
||||
*
|
||||
* @return string The translated string
|
||||
*/
|
||||
public function parseCertificateVariables($array)
|
||||
{
|
||||
$headers = $array[0];
|
||||
$content = $array[1];
|
||||
$final_content = [];
|
||||
|
||||
if (!empty($content)) {
|
||||
foreach ($content as $key => $value) {
|
||||
$my_header = str_replace(['((', '))'], '', $headers[$key]);
|
||||
$final_content[$my_header] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Certificate tags
|
||||
*
|
||||
0 => string '((user_firstname))' (length=18)
|
||||
1 => string '((user_lastname))' (length=17)
|
||||
2 => string '((gradebook_institution))' (length=25)
|
||||
3 => string '((gradebook_sitename))' (length=22)
|
||||
4 => string '((teacher_firstname))' (length=21)
|
||||
5 => string '((teacher_lastname))' (length=20)
|
||||
6 => string '((official_code))' (length=17)
|
||||
7 => string '((date_certificate))' (length=20)
|
||||
8 => string '((course_code))' (length=15)
|
||||
9 => string '((course_title))' (length=16)
|
||||
10 => string '((gradebook_grade))' (length=19)
|
||||
11 => string '((certificate_link))' (length=20)
|
||||
12 => string '((certificate_link_html))' (length=25)
|
||||
13 => string '((certificate_barcode))' (length=23)
|
||||
*/
|
||||
|
||||
$break_space = " \n\r ";
|
||||
$text =
|
||||
$final_content['gradebook_institution'].' - '.
|
||||
$final_content['gradebook_sitename'].' - '.
|
||||
get_lang('Certification').$break_space.
|
||||
get_lang('Student').': '.$final_content['user_firstname'].' '.$final_content['user_lastname'].$break_space.
|
||||
get_lang('Teacher').': '.$final_content['teacher_firstname'].' '.$final_content['teacher_lastname'].$break_space.
|
||||
get_lang('Date').': '.$final_content['date_certificate'].$break_space.
|
||||
get_lang('Score').': '.$final_content['gradebook_grade'].$break_space.
|
||||
'URL'.': '.$final_content['certificate_link'];
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the certificate is visible for the current user
|
||||
* If the global setting allow_public_certificates is set to 'false', no certificate can be printed.
|
||||
* If the global allow_public_certificates is set to 'true' and the course setting allow_public_certificates
|
||||
* is set to 0, no certificate *in this course* can be printed (for anonymous users).
|
||||
* Connected users can always print them.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isVisible()
|
||||
{
|
||||
if (!api_is_anonymous()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (api_get_setting('allow_public_certificates') != 'true') {
|
||||
// The "non-public" setting is set, so do not print
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($this->certificate_data, $this->certificate_data['cat_id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$gradeBook = new Gradebook();
|
||||
$gradeBookInfo = $gradeBook->get($this->certificate_data['cat_id']);
|
||||
|
||||
if (empty($gradeBookInfo['course_code'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$setting = api_get_course_setting(
|
||||
'allow_public_certificates',
|
||||
api_get_course_info($gradeBookInfo['course_code'])
|
||||
);
|
||||
|
||||
if ($setting == 0) {
|
||||
// Printing not allowed
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the certificate is available.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
if (empty($this->certificate_data['path_certificate'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$userCertificate = $this->certification_user_path.basename($this->certificate_data['path_certificate']);
|
||||
|
||||
if (!file_exists($userCertificate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the student's certificate (HTML file).
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
$user_certificate = $this->certification_user_path.basename($this->certificate_data['path_certificate']);
|
||||
if (file_exists($user_certificate)) {
|
||||
// Needed in order to browsers don't add custom CSS
|
||||
$certificateContent = '<!DOCTYPE html>';
|
||||
$certificateContent .= (string) file_get_contents($user_certificate);
|
||||
|
||||
// Remove media=screen to be available when printing a document
|
||||
$certificateContent = str_replace(
|
||||
' media="screen"',
|
||||
'',
|
||||
$certificateContent
|
||||
);
|
||||
|
||||
if ($this->user_id == api_get_user_id() &&
|
||||
!empty($this->certificate_data) &&
|
||||
isset($this->certificate_data['id'])
|
||||
) {
|
||||
$certificateId = $this->certificate_data['id'];
|
||||
$extraFieldValue = new ExtraFieldValue('user_certificate');
|
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable(
|
||||
$certificateId,
|
||||
'downloaded_at'
|
||||
);
|
||||
if (empty($value)) {
|
||||
$params = [
|
||||
'item_id' => $this->certificate_data['id'],
|
||||
'extra_downloaded_at' => api_get_utc_datetime(),
|
||||
];
|
||||
$extraFieldValue->saveFieldValues($params);
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: text/html; charset='.api_get_system_encoding());
|
||||
echo $certificateContent;
|
||||
|
||||
return;
|
||||
}
|
||||
api_not_allowed(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function generateCustomCertificate()
|
||||
{
|
||||
$myCertificate = GradebookUtils::get_certificate_by_user_id(
|
||||
0,
|
||||
$this->user_id
|
||||
);
|
||||
if (empty($myCertificate)) {
|
||||
GradebookUtils::registerUserInfoAboutCertificate(
|
||||
0,
|
||||
$this->user_id,
|
||||
100,
|
||||
api_get_utc_datetime()
|
||||
);
|
||||
}
|
||||
|
||||
$userInfo = api_get_user_info($this->user_id);
|
||||
$extraFieldValue = new ExtraFieldValue('user');
|
||||
$value = $extraFieldValue->get_values_by_handler_and_field_variable($this->user_id, 'legal_accept');
|
||||
$termsValidationDate = '';
|
||||
if (isset($value) && !empty($value['value'])) {
|
||||
list($id, $id2, $termsValidationDate) = explode(':', $value['value']);
|
||||
}
|
||||
|
||||
$sessions = SessionManager::get_sessions_by_user($this->user_id, false, true);
|
||||
$totalTimeInLearningPaths = 0;
|
||||
$sessionsApproved = [];
|
||||
$coursesApproved = [];
|
||||
$courseList = [];
|
||||
|
||||
if ($sessions) {
|
||||
foreach ($sessions as $session) {
|
||||
$allCoursesApproved = [];
|
||||
foreach ($session['courses'] as $course) {
|
||||
$courseInfo = api_get_course_info_by_id($course['real_id']);
|
||||
$courseCode = $courseInfo['code'];
|
||||
$gradebookCategories = Category::load(
|
||||
null,
|
||||
null,
|
||||
$courseCode,
|
||||
null,
|
||||
false,
|
||||
$session['session_id']
|
||||
);
|
||||
|
||||
if (isset($gradebookCategories[0])) {
|
||||
/** @var Category $category */
|
||||
$category = $gradebookCategories[0];
|
||||
$result = Category::userFinishedCourse(
|
||||
$this->user_id,
|
||||
$category,
|
||||
true
|
||||
);
|
||||
|
||||
// Find time spent in LP
|
||||
$timeSpent = Tracking::get_time_spent_in_lp(
|
||||
$this->user_id,
|
||||
$courseCode,
|
||||
[],
|
||||
$session['session_id']
|
||||
);
|
||||
|
||||
if (!isset($courseList[$course['real_id']])) {
|
||||
$courseList[$course['real_id']]['approved'] = false;
|
||||
$courseList[$course['real_id']]['time_spent'] = 0;
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$courseList[$course['real_id']]['approved'] = true;
|
||||
$coursesApproved[$course['real_id']] = $courseInfo['title'];
|
||||
|
||||
// Find time spent in LP
|
||||
//$totalTimeInLearningPaths += $timeSpent;
|
||||
$allCoursesApproved[] = true;
|
||||
}
|
||||
$courseList[$course['real_id']]['time_spent'] += $timeSpent;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($allCoursesApproved) == count($session['courses'])) {
|
||||
$sessionsApproved[] = $session;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$totalTimeInLearningPaths = 0;
|
||||
foreach ($courseList as $courseId => $courseData) {
|
||||
if ($courseData['approved'] === true) {
|
||||
$totalTimeInLearningPaths += $courseData['time_spent'];
|
||||
}
|
||||
}
|
||||
|
||||
$skill = new Skill();
|
||||
// Ofaj
|
||||
$skills = $skill->getStudentSkills($this->user_id, 2);
|
||||
$timeInSeconds = Tracking::get_time_spent_on_the_platform(
|
||||
$this->user_id,
|
||||
'ever'
|
||||
);
|
||||
$time = api_time_to_hms($timeInSeconds);
|
||||
|
||||
$tplContent = new Template(null, false, false, false, false, false);
|
||||
|
||||
// variables for the default template
|
||||
$tplContent->assign('complete_name', $userInfo['complete_name']);
|
||||
$tplContent->assign('time_in_platform', $time);
|
||||
$tplContent->assign('certificate_generated_date', api_get_local_time($myCertificate['created_at']));
|
||||
if (!empty($termsValidationDate)) {
|
||||
$termsValidationDate = api_get_local_time($termsValidationDate);
|
||||
}
|
||||
$tplContent->assign('terms_validation_date', $termsValidationDate);
|
||||
|
||||
// Ofaj
|
||||
$tplContent->assign('time_in_platform_in_hours', round($timeInSeconds / 3600, 1));
|
||||
$tplContent->assign(
|
||||
'certificate_generated_date_no_time',
|
||||
api_get_local_time(
|
||||
$myCertificate['created_at'],
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
'd-m-Y'
|
||||
)
|
||||
);
|
||||
$tplContent->assign(
|
||||
'terms_validation_date_no_time',
|
||||
api_get_local_time(
|
||||
$termsValidationDate,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
'd-m-Y'
|
||||
)
|
||||
);
|
||||
$tplContent->assign('skills', $skills);
|
||||
$tplContent->assign('sessions', $sessionsApproved);
|
||||
$tplContent->assign('courses', $coursesApproved);
|
||||
$tplContent->assign('time_spent_in_lps', api_time_to_hms($totalTimeInLearningPaths));
|
||||
$tplContent->assign('time_spent_in_lps_in_hours', round($totalTimeInLearningPaths / 3600, 1));
|
||||
|
||||
$layoutContent = $tplContent->get_template('gradebook/custom_certificate.tpl');
|
||||
$content = $tplContent->fetch($layoutContent);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ofaj.
|
||||
*/
|
||||
public function generatePdfFromCustomCertificate()
|
||||
{
|
||||
$orientation = api_get_configuration_value('certificate_pdf_orientation');
|
||||
|
||||
$params['orientation'] = 'landscape';
|
||||
if (!empty($orientation)) {
|
||||
$params['orientation'] = $orientation;
|
||||
}
|
||||
|
||||
$params['left'] = 0;
|
||||
$params['right'] = 0;
|
||||
$params['top'] = 0;
|
||||
$params['bottom'] = 0;
|
||||
$page_format = $params['orientation'] == 'landscape' ? 'A4-L' : 'A4';
|
||||
$pdf = new PDF($page_format, $params['orientation'], $params);
|
||||
|
||||
$pdf->html_to_pdf(
|
||||
$this->html_file,
|
||||
get_lang('Certificates'),
|
||||
null,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCertificateByUser($userId)
|
||||
{
|
||||
$userId = (int) $userId;
|
||||
if (empty($userId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE user_id= $userId";
|
||||
$rs = Database::query($sql);
|
||||
|
||||
return Database::store_result($rs, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
*/
|
||||
public static function generateUserSkills($userId)
|
||||
{
|
||||
$controller = new IndexManager(get_lang('MyCourses'));
|
||||
$courseAndSessions = $controller->returnCoursesAndSessions($userId, true, null, true, false);
|
||||
|
||||
if (isset($courseAndSessions['courses']) && !empty($courseAndSessions['courses'])) {
|
||||
foreach ($courseAndSessions['courses'] as $course) {
|
||||
$cats = Category::load(
|
||||
null,
|
||||
null,
|
||||
$course['code'],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
if (isset($cats[0]) && !empty($cats[0])) {
|
||||
Category::generateUserCertificate(
|
||||
$cats[0]->get_id(),
|
||||
$userId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($courseAndSessions['sessions']) && !empty($courseAndSessions['sessions'])) {
|
||||
foreach ($courseAndSessions['sessions'] as $sessionCategory) {
|
||||
if (isset($sessionCategory['sessions'])) {
|
||||
foreach ($sessionCategory['sessions'] as $sessionData) {
|
||||
if (!empty($sessionData['courses'])) {
|
||||
$sessionId = $sessionData['session_id'];
|
||||
foreach ($sessionData['courses'] as $courseData) {
|
||||
$cats = Category::load(
|
||||
null,
|
||||
null,
|
||||
$courseData['course_code'],
|
||||
null,
|
||||
null,
|
||||
$sessionId,
|
||||
false
|
||||
);
|
||||
|
||||
if (isset($cats[0]) && !empty($cats[0])) {
|
||||
Category::generateUserCertificate(
|
||||
$cats[0]->get_id(),
|
||||
$userId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
main/inc/lib/chamilo_session.class.php
Normal file
162
main/inc/lib/chamilo_session.class.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
|
||||
/**
|
||||
* Chamilo session (i.e. the session that maintains the connection open after usr login).
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
*
|
||||
* use ChamiloSession as Session;
|
||||
*
|
||||
* Session::read('name');
|
||||
*
|
||||
* Or
|
||||
*
|
||||
* Chamilo::session()->...
|
||||
* session()->...
|
||||
*
|
||||
* @license see /license.txt
|
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
|
||||
*/
|
||||
/**
|
||||
* @todo use session symfony component
|
||||
* @todo replace all $_SESSION calls with this class.
|
||||
* @todo remove System\Session class
|
||||
* ChamiloSession class definition
|
||||
*/
|
||||
class ChamiloSession extends System\Session
|
||||
{
|
||||
public const NAME = 'ch_sid';
|
||||
|
||||
/**
|
||||
* Generate new session instance.
|
||||
*
|
||||
* @return ChamiloSession
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
static $result = null;
|
||||
if (empty($result)) {
|
||||
$result = new ChamiloSession();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the session lifetime.
|
||||
*
|
||||
* @return int The session lifetime as defined in the config file, in seconds
|
||||
*/
|
||||
public static function session_lifetime()
|
||||
{
|
||||
return api_get_configuration_value('session_lifetime');
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the Chamilo session.
|
||||
*
|
||||
* The default lifetime for session is set here. It is not possible to have it
|
||||
* as a database setting as it is used before the database connection has been made.
|
||||
* It is taken from the configuration file, and if it doesn't exist there, it is set
|
||||
* to 360000 seconds
|
||||
*
|
||||
* @author Olivier Brouckaert
|
||||
*
|
||||
* @param string variable - the variable name to save into the session
|
||||
*/
|
||||
public static function start($already_installed = true)
|
||||
{
|
||||
/*
|
||||
* Prevent Session fixation bug fixes
|
||||
* See http://support.chamilo.org/issues/3600
|
||||
* http://php.net/manual/en/session.configuration.php
|
||||
* @todo use session_set_cookie_params with some custom admin parameters
|
||||
*/
|
||||
|
||||
//session.cookie_lifetime
|
||||
//the session ID is only accepted from a cookie
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
|
||||
//HTTPS only if possible
|
||||
//ini_set('session.cookie_secure', 1);
|
||||
//session ID in the cookie is only readable by the server
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
if (api_is_https()) {
|
||||
ini_set('session.cookie_secure', 1);
|
||||
}
|
||||
|
||||
if (api_get_configuration_value('security_session_cookie_samesite_none')) {
|
||||
if (PHP_VERSION_ID < 70300) {
|
||||
$sessionCookieParams = session_get_cookie_params();
|
||||
session_set_cookie_params($sessionCookieParams['lifetime'], '/; samesite=None',
|
||||
$sessionCookieParams['domain'], true, $sessionCookieParams['httponly']);
|
||||
} else {
|
||||
ini_set('session.cookie_samesite', 'None');
|
||||
}
|
||||
}
|
||||
|
||||
//Use entropy file
|
||||
//session.entropy_file
|
||||
//ini_set('session.entropy_length', 128);
|
||||
//Do not include the identifier in the URL, and not to read the URL for
|
||||
// identifiers.
|
||||
ini_set('session.use_trans_sid', 0);
|
||||
|
||||
session_name(self::NAME);
|
||||
session_start();
|
||||
$session = self::instance();
|
||||
if ($already_installed) {
|
||||
if (!isset($session['checkChamiloURL'])) {
|
||||
$session['checkChamiloURL'] = api_get_path(WEB_PATH);
|
||||
} elseif ($session['checkChamiloURL'] != api_get_path(WEB_PATH)) {
|
||||
self::clear();
|
||||
}
|
||||
}
|
||||
|
||||
// If the session time has expired, refresh the starttime value,
|
||||
// so we're starting to count down from a later time
|
||||
if (self::has('starttime') && $session->is_expired()) {
|
||||
self::destroy();
|
||||
} else {
|
||||
//error_log('Time not expired, extend session for a bit more');
|
||||
self::write('starttime', time());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Session start time: that is the last time the user loaded a page (before this time).
|
||||
*
|
||||
* @return int timestamp
|
||||
*/
|
||||
public function start_time()
|
||||
{
|
||||
return self::read('starttime');
|
||||
}
|
||||
|
||||
/**
|
||||
* Session end time: when the session expires. This is made of the last page
|
||||
* load time + a number of seconds.
|
||||
*
|
||||
* @return int UNIX timestamp (server's timezone)
|
||||
*/
|
||||
public function end_time()
|
||||
{
|
||||
$start_time = $this->start_time();
|
||||
$lifetime = self::session_lifetime();
|
||||
|
||||
return $start_time + $lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the session is expired.
|
||||
*
|
||||
* @return bool True if the session is expired, false if it is still valid
|
||||
*/
|
||||
public function is_expired()
|
||||
{
|
||||
return $this->end_time() < time();
|
||||
}
|
||||
}
|
||||
530
main/inc/lib/chat.lib.php
Normal file
530
main/inc/lib/chat.lib.php
Normal file
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use ChamiloSession as Session;
|
||||
|
||||
/**
|
||||
* Class Chat.
|
||||
*
|
||||
* @todo ChamiloSession instead of $_SESSION
|
||||
*/
|
||||
class Chat extends Model
|
||||
{
|
||||
public $columns = [
|
||||
'id',
|
||||
'from_user',
|
||||
'to_user',
|
||||
'message',
|
||||
'sent',
|
||||
'recd',
|
||||
];
|
||||
public $window_list = [];
|
||||
|
||||
/**
|
||||
* The contructor sets the chat table name and the window_list attribute.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->table = Database::get_main_table(TABLE_MAIN_CHAT);
|
||||
$this->window_list = Session::read('window_list');
|
||||
Session::write('window_list', $this->window_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user chat status.
|
||||
*
|
||||
* @return int 0 if disconnected, 1 if connected
|
||||
*/
|
||||
public function getUserStatus()
|
||||
{
|
||||
$status = UserManager::get_extra_user_data_by_field(
|
||||
api_get_user_id(),
|
||||
'user_chat_status',
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
return $status['user_chat_status'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user chat status.
|
||||
*
|
||||
* @param int $status 0 if disconnected, 1 if connected
|
||||
*/
|
||||
public function setUserStatus($status)
|
||||
{
|
||||
UserManager::update_extra_field_value(
|
||||
api_get_user_id(),
|
||||
'user_chat_status',
|
||||
$status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $currentUserId
|
||||
* @param int $userId
|
||||
* @param bool $latestMessages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLatestChat($currentUserId, $userId, $latestMessages)
|
||||
{
|
||||
$items = $this->getPreviousMessages(
|
||||
$currentUserId,
|
||||
$userId,
|
||||
0,
|
||||
$latestMessages
|
||||
);
|
||||
|
||||
return array_reverse($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getContacts()
|
||||
{
|
||||
$html = SocialManager::listMyFriendsBlock(
|
||||
api_get_user_id(),
|
||||
'',
|
||||
true
|
||||
);
|
||||
|
||||
echo $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $chatHistory
|
||||
* @param int $latestMessages
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAllLatestChats($chatHistory, $latestMessages = 5)
|
||||
{
|
||||
$currentUserId = api_get_user_id();
|
||||
|
||||
if (empty($chatHistory)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$chats = [];
|
||||
foreach ($chatHistory as $userId => $time) {
|
||||
$total = $this->getCountMessagesExchangeBetweenUsers($userId, $currentUserId);
|
||||
$start = $total - $latestMessages;
|
||||
if ($start < 0) {
|
||||
$start = 0;
|
||||
}
|
||||
$items = $this->getMessages($userId, $currentUserId, $start, $latestMessages);
|
||||
$chats[$userId]['items'] = $items;
|
||||
$chats[$userId]['window_user_info'] = api_get_user_info($userId);
|
||||
}
|
||||
|
||||
return $chats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a chat session and returns JSON array of status and chat history.
|
||||
*
|
||||
* @return bool (prints output in JSON format)
|
||||
*/
|
||||
public function startSession()
|
||||
{
|
||||
// ofaj
|
||||
// $chat = new Chat();
|
||||
// $chat->setUserStatus(1);
|
||||
|
||||
$chatList = Session::read('openChatBoxes');
|
||||
$chats = $this->getAllLatestChats($chatList);
|
||||
$return = [
|
||||
'user_status' => $this->getUserStatus(),
|
||||
'me' => get_lang('Me'),
|
||||
'user_id' => api_get_user_id(),
|
||||
'items' => $chats,
|
||||
'sec_token' => Security::get_token('chat'),
|
||||
];
|
||||
echo json_encode($return);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fromUserId
|
||||
* @param int $toUserId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCountMessagesExchangeBetweenUsers($fromUserId, $toUserId)
|
||||
{
|
||||
$row = Database::select(
|
||||
'count(*) as count',
|
||||
$this->table,
|
||||
[
|
||||
'where' => [
|
||||
'(from_user = ? AND to_user = ?) OR (from_user = ? AND to_user = ?) ' => [
|
||||
$fromUserId,
|
||||
$toUserId,
|
||||
$toUserId,
|
||||
$fromUserId,
|
||||
],
|
||||
],
|
||||
],
|
||||
'first'
|
||||
);
|
||||
|
||||
return (int) $row['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fromUserId
|
||||
* @param int $toUserId
|
||||
* @param int $visibleMessages
|
||||
* @param int $previousMessageCount messages to show
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPreviousMessages(
|
||||
$fromUserId,
|
||||
$toUserId,
|
||||
$visibleMessages = 1,
|
||||
$previousMessageCount = 5,
|
||||
$orderBy = ''
|
||||
) {
|
||||
$toUserId = (int) $toUserId;
|
||||
$fromUserId = (int) $fromUserId;
|
||||
$visibleMessages = (int) $visibleMessages;
|
||||
$previousMessageCount = (int) $previousMessageCount;
|
||||
|
||||
$total = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $toUserId);
|
||||
$show = $total - $visibleMessages;
|
||||
|
||||
if ($show < $previousMessageCount) {
|
||||
$show = $previousMessageCount;
|
||||
}
|
||||
$from = $show - $previousMessageCount;
|
||||
|
||||
if ($from < 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->getMessages($fromUserId, $toUserId, $from, $previousMessageCount, $orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $fromUserId
|
||||
* @param int $toUserId
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMessages($fromUserId, $toUserId, $start, $end, $orderBy = '')
|
||||
{
|
||||
$toUserId = (int) $toUserId;
|
||||
$fromUserId = (int) $fromUserId;
|
||||
$start = (int) $start;
|
||||
$end = (int) $end;
|
||||
|
||||
if (empty($toUserId) || empty($fromUserId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$orderBy = Database::escape_string($orderBy);
|
||||
if (empty($orderBy)) {
|
||||
$orderBy = 'ORDER BY id ASC';
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM ".$this->table."
|
||||
WHERE
|
||||
(
|
||||
to_user = $toUserId AND
|
||||
from_user = $fromUserId
|
||||
)
|
||||
OR
|
||||
(
|
||||
from_user = $toUserId AND
|
||||
to_user = $fromUserId
|
||||
)
|
||||
$orderBy
|
||||
LIMIT $start, $end
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
$rows = Database::store_result($result);
|
||||
$fromUserInfo = api_get_user_info($fromUserId, true);
|
||||
$toUserInfo = api_get_user_info($toUserId, true);
|
||||
$users = [
|
||||
$fromUserId => $fromUserInfo,
|
||||
$toUserId => $toUserInfo,
|
||||
];
|
||||
$items = [];
|
||||
$rows = array_reverse($rows);
|
||||
foreach ($rows as $chat) {
|
||||
$fromUserId = $chat['from_user'];
|
||||
$userInfo = $users[$fromUserId];
|
||||
$toUserInfo = $users[$toUserId];
|
||||
|
||||
$items[$chat['id']] = [
|
||||
'id' => $chat['id'],
|
||||
'message' => Security::remove_XSS($chat['message']),
|
||||
'date' => api_strtotime($chat['sent'], 'UTC'),
|
||||
'recd' => $chat['recd'],
|
||||
'from_user_info' => $userInfo,
|
||||
'to_user_info' => $toUserInfo,
|
||||
];
|
||||
$_SESSION['openChatBoxes'][$fromUserId] = api_strtotime($chat['sent'], 'UTC');
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the chat windows (usually called every x seconds through AJAX).
|
||||
*/
|
||||
public function heartbeat()
|
||||
{
|
||||
$chatHistory = Session::read('chatHistory');
|
||||
$currentUserId = api_get_user_id();
|
||||
|
||||
// update current chats
|
||||
if (!empty($chatHistory) && is_array($chatHistory)) {
|
||||
foreach ($chatHistory as $fromUserId => &$data) {
|
||||
$userInfo = api_get_user_info($fromUserId, true);
|
||||
$count = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $currentUserId);
|
||||
$chatItems = $this->getLatestChat($fromUserId, $currentUserId, 5);
|
||||
$data['window_user_info'] = $userInfo;
|
||||
$data['items'] = $chatItems;
|
||||
$data['total_messages'] = $count;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM ".$this->table."
|
||||
WHERE
|
||||
to_user = '".$currentUserId."' AND recd = 0
|
||||
ORDER BY id ASC";
|
||||
$result = Database::query($sql);
|
||||
|
||||
$chatList = [];
|
||||
while ($chat = Database::fetch_array($result, 'ASSOC')) {
|
||||
$chatList[$chat['from_user']][] = $chat;
|
||||
}
|
||||
|
||||
foreach ($chatList as $fromUserId => $messages) {
|
||||
$userInfo = api_get_user_info($fromUserId, true);
|
||||
$count = $this->getCountMessagesExchangeBetweenUsers($fromUserId, $currentUserId);
|
||||
$chatItems = $this->getLatestChat($fromUserId, $currentUserId, 5);
|
||||
|
||||
// Cleaning tsChatBoxes
|
||||
unset($_SESSION['tsChatBoxes'][$fromUserId]);
|
||||
|
||||
foreach ($messages as $chat) {
|
||||
$_SESSION['openChatBoxes'][$fromUserId] = api_strtotime($chat['sent'], 'UTC');
|
||||
}
|
||||
|
||||
$chatHistory[$fromUserId] = [
|
||||
'window_user_info' => $userInfo,
|
||||
'total_messages' => $count,
|
||||
'items' => $chatItems,
|
||||
];
|
||||
}
|
||||
|
||||
Session::write('chatHistory', $chatHistory);
|
||||
|
||||
$sql = "UPDATE ".$this->table."
|
||||
SET recd = 1
|
||||
WHERE to_user = $currentUserId AND recd = 0";
|
||||
Database::query($sql);
|
||||
|
||||
echo json_encode(['items' => $chatHistory]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves into session the fact that a chat window exists with the given user.
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public function saveWindow($userId)
|
||||
{
|
||||
$this->window_list[$userId] = true;
|
||||
Session::write('window_list', $this->window_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message from one user to another user.
|
||||
*
|
||||
* @param int $fromUserId The ID of the user sending the message
|
||||
* @param int $to_user_id The ID of the user receiving the message
|
||||
* @param string $message Message
|
||||
* @param bool $printResult Optional. Whether print the result
|
||||
* @param bool $sanitize Optional. Whether sanitize the message
|
||||
*/
|
||||
public function send(
|
||||
$fromUserId,
|
||||
$to_user_id,
|
||||
$message,
|
||||
$printResult = true,
|
||||
$sanitize = true
|
||||
) {
|
||||
$relation = SocialManager::get_relation_between_contacts($fromUserId, $to_user_id);
|
||||
|
||||
if (!Security::check_token('post', null, 'chat')) {
|
||||
if ($printResult) {
|
||||
echo '0';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (USER_RELATION_TYPE_FRIEND == $relation) {
|
||||
$now = api_get_utc_datetime();
|
||||
$user_info = api_get_user_info($to_user_id, true);
|
||||
$this->saveWindow($to_user_id);
|
||||
$_SESSION['openChatBoxes'][$to_user_id] = api_strtotime($now, 'UTC');
|
||||
|
||||
if ($sanitize) {
|
||||
$messagesan = $this->sanitize($message);
|
||||
} else {
|
||||
$messagesan = $message;
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['chatHistory'][$to_user_id])) {
|
||||
$_SESSION['chatHistory'][$to_user_id] = [];
|
||||
}
|
||||
$item = [
|
||||
's' => '1',
|
||||
'f' => $fromUserId,
|
||||
'm' => $messagesan,
|
||||
'date' => api_strtotime($now, 'UTC'),
|
||||
'username' => get_lang('Me'),
|
||||
];
|
||||
$_SESSION['chatHistory'][$to_user_id]['items'][] = $item;
|
||||
$_SESSION['chatHistory'][$to_user_id]['user_info']['user_name'] = $user_info['complete_name'];
|
||||
$_SESSION['chatHistory'][$to_user_id]['user_info']['online'] = $user_info['user_is_online'];
|
||||
$_SESSION['chatHistory'][$to_user_id]['user_info']['avatar'] = $user_info['avatar_small'];
|
||||
$_SESSION['chatHistory'][$to_user_id]['user_info']['user_id'] = $user_info['user_id'];
|
||||
|
||||
unset($_SESSION['tsChatBoxes'][$to_user_id]);
|
||||
|
||||
$params = [];
|
||||
$params['from_user'] = (int) $fromUserId;
|
||||
$params['to_user'] = (int) $to_user_id;
|
||||
$params['message'] = $messagesan;
|
||||
$params['sent'] = api_get_utc_datetime();
|
||||
|
||||
if (!empty($fromUserId) && !empty($to_user_id)) {
|
||||
$messageId = $this->save($params);
|
||||
|
||||
if ($printResult) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['id' => $messageId, 'sec_token' => Security::get_token('chat')]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($printResult) {
|
||||
echo '0';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a specific chat box (user ID taken from $_POST['chatbox']).
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public function closeWindow($userId)
|
||||
{
|
||||
if (empty($userId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = Session::read('openChatBoxes');
|
||||
if (isset($list[$userId])) {
|
||||
unset($list[$userId]);
|
||||
Session::write('openChatBoxes', $list);
|
||||
}
|
||||
|
||||
$list = Session::read('chatHistory');
|
||||
if (isset($list[$userId])) {
|
||||
unset($list[$userId]);
|
||||
Session::write('chatHistory', $list);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close chat - disconnects the user.
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
Session::erase('tsChatBoxes');
|
||||
Session::erase('openChatBoxes');
|
||||
Session::erase('chatHistory');
|
||||
Session::erase('window_list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter chat messages to avoid XSS or other JS.
|
||||
*
|
||||
* @param string $text Unfiltered message
|
||||
*
|
||||
* @return string Filtered message
|
||||
*/
|
||||
public function sanitize($text)
|
||||
{
|
||||
$text = htmlspecialchars($text, ENT_QUOTES);
|
||||
$text = str_replace("\n\r", "\n", $text);
|
||||
$text = str_replace("\r\n", "\n", $text);
|
||||
$text = str_replace("\n", "<br>", $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* SET Disable Chat.
|
||||
*
|
||||
* @param bool $status to disable chat
|
||||
*/
|
||||
public static function setDisableChat($status = true)
|
||||
{
|
||||
Session::write('disable_chat', $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Chat - disable the chat.
|
||||
*
|
||||
* @return bool - return true if setDisableChat status is true
|
||||
*/
|
||||
public static function disableChat()
|
||||
{
|
||||
$status = Session::read('disable_chat');
|
||||
if (!empty($status)) {
|
||||
if ($status == true) {
|
||||
Session::write('disable_chat', null);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isChatBlockedByExercises()
|
||||
{
|
||||
$currentExercises = Session::read('current_exercises');
|
||||
if (!empty($currentExercises)) {
|
||||
foreach ($currentExercises as $attempt_status) {
|
||||
if ($attempt_status == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
44
main/inc/lib/conditional_login.class.php
Normal file
44
main/inc/lib/conditional_login.class.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Conditional login
|
||||
* Used to implement the loading of custom pages
|
||||
* 2011, Noel Dieschburg <noel@cblue.be>.
|
||||
*/
|
||||
class ConditionalLogin
|
||||
{
|
||||
/**
|
||||
* Check conditions based in the $login_conditions see conditional_login.php file.
|
||||
*
|
||||
* @param array $user
|
||||
*/
|
||||
public static function check_conditions($user)
|
||||
{
|
||||
$file = api_get_path(SYS_CODE_PATH).'auth/conditional_login/conditional_login.php';
|
||||
if (file_exists($file)) {
|
||||
include_once $file;
|
||||
if (isset($login_conditions)) {
|
||||
foreach ($login_conditions as $condition) {
|
||||
//If condition fails we redirect to the URL defined by the condition
|
||||
if (isset($condition['conditional_function'])) {
|
||||
$function = $condition['conditional_function'];
|
||||
$result = $function($user);
|
||||
if (false == $result) {
|
||||
$_SESSION['conditional_login']['uid'] = $user['user_id'];
|
||||
$_SESSION['conditional_login']['can_login'] = false;
|
||||
header("Location: ".$condition['url']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function login()
|
||||
{
|
||||
$_SESSION['conditional_login']['can_login'] = true;
|
||||
LoginRedirection::redirect();
|
||||
}
|
||||
}
|
||||
7516
main/inc/lib/course.lib.php
Normal file
7516
main/inc/lib/course.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
914
main/inc/lib/course_category.lib.php
Normal file
914
main/inc/lib/course_category.lib.php
Normal file
@@ -0,0 +1,914 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class CourseCategory.
|
||||
*/
|
||||
class CourseCategory
|
||||
{
|
||||
/**
|
||||
* Returns the category fields from the database from an int ID.
|
||||
*
|
||||
* @param int $categoryId The category ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategoryById($categoryId)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$categoryId = (int) $categoryId;
|
||||
$sql = "SELECT * FROM $table WHERE id = $categoryId";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result)) {
|
||||
return Database::fetch_array($result, 'ASSOC');
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category details from a simple category code.
|
||||
*
|
||||
* @param string $categoryCode The literal category code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategory($categoryCode)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$categoryCode = Database::escape_string($categoryCode);
|
||||
$sql = "SELECT * FROM $table WHERE code ='$categoryCode'";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result)) {
|
||||
$category = Database::fetch_array($result, 'ASSOC');
|
||||
if ($category) {
|
||||
// Get access url id
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$sql = "SELECT * FROM $table WHERE course_category_id = ".$category['id'];
|
||||
$result = Database::query($sql);
|
||||
$result = Database::fetch_array($result);
|
||||
if ($result) {
|
||||
$category['access_url_id'] = $result['access_url_id'];
|
||||
}
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $category Optional. Parent category code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategories($category = '')
|
||||
{
|
||||
$tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$category = Database::escape_string($category);
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
|
||||
$whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
|
||||
$allowBaseCategories = api_get_configuration_value('allow_base_course_category');
|
||||
if ($allowBaseCategories) {
|
||||
$whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
|
||||
}
|
||||
|
||||
$parentIdCondition = " AND (t1.parent_id IS NULL OR t1.parent_id = '' )";
|
||||
if (!empty($category)) {
|
||||
$parentIdCondition = " AND t1.parent_id = '$category' ";
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
t1.id,
|
||||
t1.name,
|
||||
t1.code,
|
||||
t1.parent_id,
|
||||
t1.tree_pos,
|
||||
t1.children_count,
|
||||
COUNT(DISTINCT t3.code) AS nbr_courses,
|
||||
a.access_url_id
|
||||
FROM $tbl_category t1
|
||||
$conditions
|
||||
LEFT JOIN $tbl_category t2
|
||||
ON t1.code = t2.parent_id
|
||||
LEFT JOIN $tbl_course t3
|
||||
ON t3.category_code=t1.code
|
||||
WHERE
|
||||
1 = 1
|
||||
$parentIdCondition
|
||||
$whereCondition
|
||||
GROUP BY t1.name,
|
||||
t1.code,
|
||||
t1.parent_id,
|
||||
t1.tree_pos,
|
||||
t1.children_count
|
||||
ORDER BY t1.tree_pos";
|
||||
|
||||
$result = Database::query($sql);
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flat list of all course categories in this URL. If the
|
||||
* allow_base_course_category option is true, then also show the
|
||||
* course categories of the base URL.
|
||||
*
|
||||
* @return array [id, name, code, parent_id, tree_pos, children_count, number_courses]
|
||||
*/
|
||||
public static function getAllCategories()
|
||||
{
|
||||
$tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
|
||||
$whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
|
||||
$allowBaseCategories = api_get_configuration_value('allow_base_course_category');
|
||||
if ($allowBaseCategories) {
|
||||
$whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
t1.id,
|
||||
t1.name,
|
||||
t1.code,
|
||||
t1.parent_id,
|
||||
t1.tree_pos,
|
||||
t1.children_count,
|
||||
COUNT(DISTINCT t3.code) AS number_courses
|
||||
FROM $tbl_category t1
|
||||
$conditions
|
||||
LEFT JOIN $tbl_course t3
|
||||
ON t3.category_code=t1.code
|
||||
WHERE 1=1
|
||||
$whereCondition
|
||||
GROUP BY
|
||||
t1.name,
|
||||
t1.code,
|
||||
t1.parent_id,
|
||||
t1.tree_pos,
|
||||
t1.children_count
|
||||
ORDER BY t1.parent_id, t1.tree_pos";
|
||||
|
||||
$result = Database::query($sql);
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
* @param string $name
|
||||
* @param string $canHaveCourses
|
||||
* @param int $parent_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function addNode($code, $name, $canHaveCourses, $parent_id)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$code = trim($code);
|
||||
$name = trim($name);
|
||||
$parent_id = trim($parent_id);
|
||||
|
||||
$code = CourseManager::generate_course_code($code);
|
||||
$sql = "SELECT 1 FROM $table
|
||||
WHERE code = '".Database::escape_string($code)."'";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result)) {
|
||||
return false;
|
||||
}
|
||||
$result = Database::query("SELECT MAX(tree_pos) AS maxTreePos FROM $table");
|
||||
$row = Database::fetch_array($result);
|
||||
$tree_pos = $row['maxTreePos'] + 1;
|
||||
|
||||
$params = [
|
||||
'name' => html_filter($name),
|
||||
'code' => $code,
|
||||
'parent_id' => empty($parent_id) ? null : $parent_id,
|
||||
'tree_pos' => $tree_pos,
|
||||
'children_count' => 0,
|
||||
'auth_course_child' => $canHaveCourses,
|
||||
'auth_cat_child' => 'TRUE',
|
||||
];
|
||||
|
||||
$categoryId = Database::insert($table, $params);
|
||||
if ($categoryId) {
|
||||
self::updateParentCategoryChildrenCount($parent_id, 1);
|
||||
UrlManager::addCourseCategoryListToUrl(
|
||||
[$categoryId],
|
||||
[api_get_current_access_url_id()]
|
||||
);
|
||||
|
||||
return $categoryId;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive function that updates the count of children in the parent.
|
||||
*
|
||||
* @param string $categoryId Category ID
|
||||
* @param int $delta The number to add or delete (1 to add one, -1 to remove one)
|
||||
*/
|
||||
public static function updateParentCategoryChildrenCount($categoryId, $delta = 1)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$categoryId = Database::escape_string($categoryId);
|
||||
$delta = (int) $delta;
|
||||
// First get to the highest level possible in the tree
|
||||
$result = Database::query("SELECT parent_id FROM $table WHERE code = '$categoryId'");
|
||||
$row = Database::fetch_array($result);
|
||||
if ($row !== false and $row['parent_id'] != 0) {
|
||||
// if a parent was found, enter there to see if he's got one more parent
|
||||
self::updateParentCategoryChildrenCount($row['parent_id'], $delta);
|
||||
}
|
||||
// Now we're at the top, get back down to update each child
|
||||
$sql = "UPDATE $table SET children_count = (children_count - ".abs($delta).") WHERE code = '$categoryId'";
|
||||
if ($delta >= 0) {
|
||||
$sql = "UPDATE $table SET children_count = (children_count + $delta) WHERE code = '$categoryId'";
|
||||
}
|
||||
Database::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $node
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteNode($node)
|
||||
{
|
||||
$category = self::getCategory($node);
|
||||
|
||||
if (empty($category)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$node = Database::escape_string($node);
|
||||
$result = Database::query("SELECT parent_id, tree_pos FROM $tbl_category WHERE code='$node'");
|
||||
|
||||
if ($row = Database::fetch_array($result)) {
|
||||
if (!empty($row['parent_id'])) {
|
||||
Database::query(
|
||||
"UPDATE $tbl_course SET category_code = '".$row['parent_id']."' WHERE category_code='$node'"
|
||||
);
|
||||
Database::query("UPDATE $tbl_category SET parent_id='".$row['parent_id']."' WHERE parent_id='$node'");
|
||||
} else {
|
||||
Database::query("UPDATE $tbl_course SET category_code='' WHERE category_code='$node'");
|
||||
Database::query("UPDATE $tbl_category SET parent_id=NULL WHERE parent_id='$node'");
|
||||
}
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$sql = "DELETE FROM $table WHERE course_category_id = ".$category['id'];
|
||||
|
||||
Database::query($sql);
|
||||
Database::query("UPDATE $tbl_category SET tree_pos=tree_pos-1 WHERE tree_pos > '".$row['tree_pos']."'");
|
||||
Database::query("DELETE FROM $tbl_category WHERE code='$node'");
|
||||
|
||||
if (!empty($row['parent_id'])) {
|
||||
self::updateParentCategoryChildrenCount($row['parent_id'], -1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
* @param string $name
|
||||
* @param string $canHaveCourses
|
||||
* @param string $old_code
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function editNode(
|
||||
$code,
|
||||
$name,
|
||||
$canHaveCourses,
|
||||
$old_code,
|
||||
?string $newParentCode = null,
|
||||
?string $oldParentCode = null
|
||||
) {
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
|
||||
$code = CourseManager::generate_course_code($code);
|
||||
$name = html_filter($name);
|
||||
|
||||
$code = CourseManager::generate_course_code($code);
|
||||
// Updating category
|
||||
Database::update(
|
||||
$tbl_category,
|
||||
[
|
||||
'name' => $name,
|
||||
'code' => $code,
|
||||
'auth_course_child' => $canHaveCourses,
|
||||
],
|
||||
['code = ?' => $old_code]
|
||||
);
|
||||
|
||||
// Updating children
|
||||
Database::update(
|
||||
$tbl_category,
|
||||
['parent_id' => $code],
|
||||
['parent_id = ?' => $old_code]
|
||||
);
|
||||
|
||||
// Updating course category
|
||||
Database::update(
|
||||
$tbl_course,
|
||||
['category_code' => $code],
|
||||
['category_code = ?' => $old_code]
|
||||
);
|
||||
|
||||
Database::update(
|
||||
$tbl_category,
|
||||
['parent_id' => $newParentCode ?: null],
|
||||
['code = ?' => $code]
|
||||
);
|
||||
|
||||
self::updateParentCategoryChildrenCount($oldParentCode, -1);
|
||||
self::updateParentCategoryChildrenCount($newParentCode, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a node up on display.
|
||||
*
|
||||
* @param string $code
|
||||
* @param int $tree_pos
|
||||
* @param string $parent_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function moveNodeUp($code, $tree_pos, $parent_id)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$code = Database::escape_string($code);
|
||||
$tree_pos = (int) $tree_pos;
|
||||
$parent_id = Database::escape_string($parent_id);
|
||||
|
||||
$parentIdCondition = " AND (parent_id IS NULL OR parent_id = '' )";
|
||||
if (!empty($parent_id)) {
|
||||
$parentIdCondition = " AND parent_id = '$parent_id' ";
|
||||
}
|
||||
|
||||
$sql = "SELECT code,tree_pos
|
||||
FROM $table
|
||||
WHERE
|
||||
tree_pos < $tree_pos
|
||||
$parentIdCondition
|
||||
ORDER BY tree_pos DESC
|
||||
LIMIT 0,1";
|
||||
|
||||
$result = Database::query($sql);
|
||||
if (!$row = Database::fetch_array($result)) {
|
||||
$sql = "SELECT code, tree_pos
|
||||
FROM $table
|
||||
WHERE
|
||||
tree_pos > $tree_pos
|
||||
$parentIdCondition
|
||||
ORDER BY tree_pos DESC
|
||||
LIMIT 0,1";
|
||||
$result2 = Database::query($sql);
|
||||
if (!$row = Database::fetch_array($result2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "UPDATE $table
|
||||
SET tree_pos ='".$row['tree_pos']."'
|
||||
WHERE code='$code'";
|
||||
Database::query($sql);
|
||||
|
||||
$sql = "UPDATE $table
|
||||
SET tree_pos = '$tree_pos'
|
||||
WHERE code= '".$row['code']."'";
|
||||
Database::query($sql);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getChildren(string $categoryCode, bool $getChildren = true): array
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$categoryCode = Database::escape_string($categoryCode);
|
||||
$sql = "SELECT name, code, id FROM $table
|
||||
WHERE parent_id = '$categoryCode'";
|
||||
$result = Database::query($sql);
|
||||
$children = [];
|
||||
while ($row = Database::fetch_array($result, 'ASSOC')) {
|
||||
$children[] = $row;
|
||||
if ($getChildren) {
|
||||
$subChildren = self::getChildren($row['code']);
|
||||
$children = array_merge($children, $subChildren);
|
||||
}
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $categoryCode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getParents($categoryCode)
|
||||
{
|
||||
if (empty($categoryCode)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$categoryCode = Database::escape_string($categoryCode);
|
||||
$sql = "SELECT code, parent_id
|
||||
FROM $table
|
||||
WHERE code = '$categoryCode'";
|
||||
|
||||
$result = Database::query($sql);
|
||||
$children = [];
|
||||
while ($row = Database::fetch_array($result, 'ASSOC')) {
|
||||
$parent = self::getCategory($row['parent_id']);
|
||||
$children[] = $row;
|
||||
$subChildren = self::getParents($parent ? $parent['code'] : null);
|
||||
$children = array_merge($children, $subChildren);
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $categoryCode
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getParentsToString($categoryCode)
|
||||
{
|
||||
$parents = self::getParents($categoryCode);
|
||||
|
||||
if (!empty($parents)) {
|
||||
$parents = array_reverse($parents);
|
||||
$categories = [];
|
||||
foreach ($parents as $category) {
|
||||
$categories[] = $category['code'];
|
||||
}
|
||||
|
||||
return implode(' > ', $categories).' > ';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $categorySource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function listCategories($categorySource)
|
||||
{
|
||||
$categories = self::getCategories($categorySource);
|
||||
$categorySource = Security::remove_XSS($categorySource);
|
||||
|
||||
if (count($categories) > 0) {
|
||||
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
|
||||
$column = 0;
|
||||
$row = 0;
|
||||
$headers = [
|
||||
get_lang('Category'),
|
||||
get_lang('SubCat'),
|
||||
get_lang('Courses'),
|
||||
get_lang('Actions'),
|
||||
];
|
||||
foreach ($headers as $header) {
|
||||
$table->setHeaderContents($row, $column, $header);
|
||||
$column++;
|
||||
}
|
||||
$row++;
|
||||
$mainUrl = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$categorySource;
|
||||
$ajaxUrl = api_get_path(WEB_AJAX_PATH).'course_category.ajax.php';
|
||||
$editIcon = Display::return_icon(
|
||||
'edit.png',
|
||||
get_lang('EditNode'),
|
||||
null,
|
||||
ICON_SIZE_SMALL
|
||||
);
|
||||
$exportIcon = Display::return_icon('export_csv.png', get_lang('ExportAsCSV'));
|
||||
|
||||
$deleteIcon = Display::return_icon(
|
||||
'delete.png',
|
||||
get_lang('DeleteNode'),
|
||||
null,
|
||||
ICON_SIZE_SMALL
|
||||
);
|
||||
$moveIcon = Display::return_icon(
|
||||
'up.png',
|
||||
get_lang('UpInSameLevel'),
|
||||
null,
|
||||
ICON_SIZE_SMALL
|
||||
);
|
||||
|
||||
$showCoursesIcon = Display::return_icon(
|
||||
'course.png',
|
||||
get_lang('Courses'),
|
||||
null,
|
||||
ICON_SIZE_SMALL
|
||||
);
|
||||
|
||||
$urlId = api_get_current_access_url_id();
|
||||
foreach ($categories as $category) {
|
||||
$categoryId = $category['id'];
|
||||
$editUrl = $mainUrl.'&id='.$category['code'].'&action=edit';
|
||||
$moveUrl = $mainUrl.'&id='.$category['code'].'&action=moveUp&tree_pos='.$category['tree_pos'];
|
||||
$deleteUrl = $mainUrl.'&id='.$category['code'].'&action=delete';
|
||||
$exportUrl = $mainUrl.'&id='.$categoryId.'&action=export';
|
||||
$showCoursesUrl = $ajaxUrl.'?id='.$categoryId.'&a=show_courses';
|
||||
|
||||
$actions = [];
|
||||
if ($urlId == $category['access_url_id']) {
|
||||
$actions[] = Display::url(
|
||||
$showCoursesIcon,
|
||||
$showCoursesUrl,
|
||||
['onclick' => 'showCourses(this, '.$categoryId.')']
|
||||
);
|
||||
$actions[] = Display::url($editIcon, $editUrl);
|
||||
$actions[] = Display::url($moveIcon, $moveUrl);
|
||||
$actions[] = Display::url($exportIcon, $exportUrl);
|
||||
$actions[] = Display::url(
|
||||
$deleteIcon,
|
||||
$deleteUrl,
|
||||
['onclick' => 'javascript: if (!confirm(\''.addslashes(api_htmlentities(sprintf(get_lang('ConfirmYourChoice')), ENT_QUOTES)).'\')) return false;']
|
||||
);
|
||||
}
|
||||
|
||||
$url = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$category['code'];
|
||||
$title = Display::url(
|
||||
Display::return_icon(
|
||||
'folder_document.gif',
|
||||
get_lang('OpenNode'),
|
||||
null,
|
||||
ICON_SIZE_SMALL
|
||||
).' '.$category['name'].' ('.$category['code'].')',
|
||||
$url
|
||||
);
|
||||
|
||||
$countCourses = self::countCoursesInCategory($category['code'], null, false, false);
|
||||
|
||||
$content = [
|
||||
$title,
|
||||
$category['children_count'],
|
||||
$countCourses,
|
||||
implode('', $actions),
|
||||
];
|
||||
$column = 0;
|
||||
foreach ($content as $value) {
|
||||
$table->setCellContents($row, $column, $value);
|
||||
$column++;
|
||||
}
|
||||
$row++;
|
||||
}
|
||||
|
||||
return $table->toHtml();
|
||||
}
|
||||
|
||||
return Display::return_message(get_lang('NoCategories'), 'warning');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategoriesToDisplayInHomePage()
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$sql = "SELECT name, code FROM $table
|
||||
WHERE parent_id IS NULL
|
||||
ORDER BY tree_pos";
|
||||
|
||||
return Database::store_result(Database::query($sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $categoryCode
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategoriesCanBeAddedInCourse($categoryCode)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
|
||||
$whereCondition = ' AND a.access_url_id = '.api_get_current_access_url_id();
|
||||
|
||||
$tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$sql = "SELECT code, name
|
||||
FROM $tbl_category c
|
||||
$conditions
|
||||
WHERE (auth_course_child = 'TRUE' OR code = '".Database::escape_string($categoryCode)."')
|
||||
$whereCondition
|
||||
ORDER BY tree_pos";
|
||||
$res = Database::query($sql);
|
||||
|
||||
$categoryToAvoid = '';
|
||||
if (!api_is_platform_admin()) {
|
||||
$categoryToAvoid = api_get_configuration_value('course_category_code_to_use_as_model');
|
||||
}
|
||||
|
||||
$categories[''] = '-';
|
||||
while ($cat = Database::fetch_array($res)) {
|
||||
$categoryCode = $cat['code'];
|
||||
if (!empty($categoryToAvoid) && $categoryToAvoid == $categoryCode) {
|
||||
continue;
|
||||
}
|
||||
$categories[$categoryCode] = '('.$categoryCode.') '.$cat['name'];
|
||||
ksort($categories);
|
||||
}
|
||||
|
||||
return $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $category_code
|
||||
* @param string $keyword
|
||||
* @param bool $avoidCourses
|
||||
* @param bool $checkHidePrivate
|
||||
* @param array $conditions
|
||||
* @param string $courseLanguageFilter
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function countCoursesInCategory(
|
||||
$category_code = '',
|
||||
$keyword = '',
|
||||
$avoidCourses = true,
|
||||
$checkHidePrivate = true,
|
||||
$conditions = [],
|
||||
$courseLanguageFilter = null,
|
||||
$filterShowInCatalogue = false
|
||||
) {
|
||||
return self::getCoursesInCategory(
|
||||
$category_code,
|
||||
$keyword,
|
||||
$avoidCourses,
|
||||
$checkHidePrivate,
|
||||
$conditions,
|
||||
true,
|
||||
$courseLanguageFilter,
|
||||
$filterShowInCatalogue
|
||||
);
|
||||
}
|
||||
|
||||
public static function getCoursesInCategory(
|
||||
$category_code = '',
|
||||
$keyword = '',
|
||||
$avoidCourses = true,
|
||||
$checkHidePrivate = true,
|
||||
$conditions = [],
|
||||
$getCount = false,
|
||||
$courseLanguageFilter = null,
|
||||
$filterShowInCatalogue = false
|
||||
) {
|
||||
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
|
||||
$categoryCode = Database::escape_string($category_code);
|
||||
$keyword = Database::escape_string($keyword);
|
||||
|
||||
$avoidCoursesCondition = '';
|
||||
if ($avoidCourses) {
|
||||
$avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition();
|
||||
}
|
||||
$visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true, $checkHidePrivate);
|
||||
|
||||
$showInCatalogueCondition = '';
|
||||
if ($filterShowInCatalogue) {
|
||||
$showInCatalogueCondition = CoursesAndSessionsCatalog::getCoursesToShowInCatalogueCondition();
|
||||
}
|
||||
|
||||
$sqlInjectJoins = '';
|
||||
$courseLanguageWhere = '';
|
||||
$where = ' AND 1 = 1 ';
|
||||
$sqlInjectWhere = '';
|
||||
if (!empty($conditions)) {
|
||||
$sqlInjectJoins = $conditions['inject_joins'];
|
||||
$where = $conditions['where'];
|
||||
$sqlInjectWhere = $conditions['inject_where'];
|
||||
}
|
||||
|
||||
// If have courseLanguageFilter, search for it
|
||||
if (!empty($courseLanguageFilter)) {
|
||||
$courseLanguageFilter = Database::escape_string($courseLanguageFilter);
|
||||
$courseLanguageWhere = "AND course.course_language = '$courseLanguageFilter'";
|
||||
}
|
||||
|
||||
$categoryFilter = '';
|
||||
if ($categoryCode === 'ALL' || empty($categoryCode)) {
|
||||
// Nothing to do
|
||||
} elseif ($categoryCode === 'NONE') {
|
||||
$categoryFilter = ' AND category_code = "" ';
|
||||
} else {
|
||||
$categoryFilter = ' AND category_code = "'.$categoryCode.'" ';
|
||||
}
|
||||
|
||||
$searchFilter = '';
|
||||
if (!empty($keyword)) {
|
||||
$searchFilter = ' AND (
|
||||
code LIKE "%'.$keyword.'%" OR
|
||||
title LIKE "%'.$keyword.'%" OR
|
||||
tutor_name LIKE "%'.$keyword.'%"
|
||||
) ';
|
||||
}
|
||||
|
||||
$urlCondition = ' access_url_id = '.api_get_current_access_url_id().' AND';
|
||||
$tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
|
||||
$select = " DISTINCT course.id, course.code, course.title, course.category_code, course.directory ";
|
||||
if ($getCount) {
|
||||
$select = "count(DISTINCT course.id) as count";
|
||||
}
|
||||
$sql = "SELECT $select
|
||||
FROM $tbl_course as course
|
||||
INNER JOIN $tbl_url_rel_course as url_rel_course
|
||||
ON (url_rel_course.c_id = course.id)
|
||||
$sqlInjectJoins
|
||||
WHERE
|
||||
$urlCondition
|
||||
course.visibility != '0' AND
|
||||
course.visibility != '4'
|
||||
$courseLanguageWhere
|
||||
$categoryFilter
|
||||
$searchFilter
|
||||
$avoidCoursesCondition
|
||||
$showInCatalogueCondition
|
||||
$visibilityCondition
|
||||
$where
|
||||
$sqlInjectWhere
|
||||
";
|
||||
|
||||
$result = Database::query($sql);
|
||||
|
||||
if ($getCount) {
|
||||
$row = Database::fetch_array($result);
|
||||
|
||||
return (int) $row['count'];
|
||||
}
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCourseCategoryNotInList($list)
|
||||
{
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
|
||||
if (empty($list)) {
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE (parent_id IS NULL) ";
|
||||
$result = Database::query($sql);
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
$list = array_map('intval', $list);
|
||||
$listToString = implode("','", $list);
|
||||
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE id NOT IN ('$listToString') AND (parent_id IS NULL) ";
|
||||
$result = Database::query($sql);
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $keyword
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public static function searchCategoryByKeyword($keyword)
|
||||
{
|
||||
if (empty($keyword)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tableCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
$table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
|
||||
$conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
|
||||
$whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
|
||||
|
||||
$allowBaseCategories = api_get_configuration_value('allow_base_course_category');
|
||||
if ($allowBaseCategories) {
|
||||
$whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
|
||||
}
|
||||
|
||||
$keyword = Database::escape_string($keyword);
|
||||
|
||||
$sql = "SELECT c.*, c.name as text
|
||||
FROM $tableCategory c $conditions
|
||||
WHERE
|
||||
(
|
||||
c.code LIKE '%$keyword%' OR name LIKE '%$keyword%'
|
||||
) AND auth_course_child = 'TRUE'
|
||||
$whereCondition ";
|
||||
$result = Database::query($sql);
|
||||
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name tool by action.
|
||||
*
|
||||
* @param string $action
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCourseCatalogNameTools($action)
|
||||
{
|
||||
$nameTools = get_lang('MyCourses');
|
||||
if (empty($action)) {
|
||||
return $nameTools; //should never happen
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'subscribe':
|
||||
case 'subscribe_user_with_password':
|
||||
case 'display_random_courses':
|
||||
case 'display_courses':
|
||||
$nameTools = get_lang('CourseManagement');
|
||||
break;
|
||||
case 'display_sessions':
|
||||
$nameTools = get_lang('Sessions');
|
||||
break;
|
||||
default:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
return $nameTools;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save image for a course category.
|
||||
*
|
||||
* @param int $categoryId Course category ID
|
||||
* @param array $fileData File data from $_FILES
|
||||
*/
|
||||
public static function saveImage($categoryId, $fileData)
|
||||
{
|
||||
$categoryInfo = self::getCategoryById($categoryId);
|
||||
if (empty($categoryInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($fileData['error'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$extension = getextension($fileData['name']);
|
||||
$dirName = 'course_category/';
|
||||
$fileDir = api_get_path(SYS_UPLOAD_PATH).$dirName;
|
||||
$fileName = "cc_$categoryId.{$extension[0]}";
|
||||
|
||||
if (!file_exists($fileDir)) {
|
||||
mkdir($fileDir, api_get_permissions_for_new_directories(), true);
|
||||
}
|
||||
|
||||
$image = new Image($fileData['tmp_name']);
|
||||
$image->send_image($fileDir.$fileName);
|
||||
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
Database::update(
|
||||
$table,
|
||||
['image' => $dirName.$fileName],
|
||||
['id = ?' => $categoryId]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $categoryId
|
||||
* @param string $description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function saveDescription($categoryId, $description)
|
||||
{
|
||||
$categoryInfo = self::getCategoryById($categoryId);
|
||||
if (empty($categoryInfo)) {
|
||||
return false;
|
||||
}
|
||||
$table = Database::get_main_table(TABLE_MAIN_CATEGORY);
|
||||
Database::update(
|
||||
$table,
|
||||
['description' => $description],
|
||||
['id = ?' => $categoryId]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
550
main/inc/lib/course_description.lib.php
Normal file
550
main/inc/lib/course_description.lib.php
Normal file
@@ -0,0 +1,550 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* This file contains a class used like library provides functions for
|
||||
* course description tool. It's also used like model to
|
||||
* course_description_controller (MVC pattern).
|
||||
*
|
||||
* @author Christian Fasanando <christian1827@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CourseDescription course descriptions.
|
||||
*/
|
||||
class CourseDescription
|
||||
{
|
||||
private $id;
|
||||
private $course_id;
|
||||
private $title;
|
||||
private $content;
|
||||
private $session_id;
|
||||
private $description_type;
|
||||
private $progress;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects of type CourseDescription corresponding to
|
||||
* a specific course, without session ids (session id = 0).
|
||||
*
|
||||
* @param int $course_id
|
||||
*
|
||||
* @return array Array of CourseDescriptions
|
||||
*/
|
||||
public static function get_descriptions($course_id)
|
||||
{
|
||||
$course_id = (int) $course_id;
|
||||
// Get course code
|
||||
$course_info = api_get_course_info_by_id($course_id);
|
||||
if (!empty($course_info)) {
|
||||
$course_id = $course_info['real_id'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE c_id = $course_id AND session_id = '0'";
|
||||
$sql_result = Database::query($sql);
|
||||
$results = [];
|
||||
while ($row = Database::fetch_array($sql_result)) {
|
||||
$desc_tmp = new CourseDescription();
|
||||
$desc_tmp->set_id($row['id']);
|
||||
$desc_tmp->set_title($row['title']);
|
||||
$desc_tmp->set_content($row['content']);
|
||||
$desc_tmp->set_session_id($row['session_id']);
|
||||
$desc_tmp->set_description_type($row['description_type']);
|
||||
$desc_tmp->set_progress($row['progress']);
|
||||
$results[] = $desc_tmp;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data of course description by session id,
|
||||
* first you must set session_id property with the object CourseDescription.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_description_data()
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$condition_session = api_get_session_condition(
|
||||
$this->session_id,
|
||||
true,
|
||||
true
|
||||
);
|
||||
$course_id = $this->course_id ?: api_get_course_int_id();
|
||||
|
||||
if (empty($course_id)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE c_id = $course_id $condition_session
|
||||
ORDER BY id ";
|
||||
$rs = Database::query($sql);
|
||||
$data = [];
|
||||
while ($description = Database::fetch_array($rs)) {
|
||||
$data['descriptions'][$description['id']] = $description;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data by description and session id,
|
||||
* first you must set session_id property with the object CourseDescription.
|
||||
*
|
||||
* @param int $description_type Description type
|
||||
* @param string $courseId Course code (optional)
|
||||
* @param int $session_id Session id (optional)
|
||||
*
|
||||
* @return array List of fields from the descriptions found of the given type
|
||||
*/
|
||||
public function get_data_by_description_type(
|
||||
$description_type,
|
||||
$courseId = null,
|
||||
$session_id = null
|
||||
) {
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$courseId = (int) $courseId;
|
||||
|
||||
if (empty($courseId)) {
|
||||
$courseId = api_get_course_int_id();
|
||||
}
|
||||
|
||||
if (!isset($session_id)) {
|
||||
$session_id = $this->session_id;
|
||||
}
|
||||
$condition_session = api_get_session_condition($session_id);
|
||||
$description_type = (int) $description_type;
|
||||
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE
|
||||
c_id = $courseId AND
|
||||
description_type = '$description_type'
|
||||
$condition_session ";
|
||||
$rs = Database::query($sql);
|
||||
$data = [];
|
||||
if ($description = Database::fetch_array($rs)) {
|
||||
$data['description_title'] = $description['title'];
|
||||
$data['description_content'] = $description['content'];
|
||||
$data['progress'] = $description['progress'];
|
||||
$data['id'] = $description['id'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $course_code
|
||||
* @param int $session_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data_by_id($id, $course_code = '', $session_id = null)
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$course_id = api_get_course_int_id();
|
||||
$id = (int) $id;
|
||||
|
||||
if (!isset($session_id)) {
|
||||
$session_id = $this->session_id;
|
||||
}
|
||||
$condition_session = api_get_session_condition($session_id);
|
||||
if (!empty($course_code)) {
|
||||
$course_info = api_get_course_info($course_code);
|
||||
$course_id = $course_info['real_id'];
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM $table
|
||||
WHERE c_id = $course_id AND id='$id' $condition_session ";
|
||||
$rs = Database::query($sql);
|
||||
$data = [];
|
||||
if ($description = Database::fetch_array($rs)) {
|
||||
$data['description_type'] = $description['description_type'];
|
||||
$data['description_title'] = $description['title'];
|
||||
$data['description_content'] = $description['content'];
|
||||
$data['progress'] = $description['progress'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum description type by session id,
|
||||
* first you must set session_id properties with the object CourseDescription.
|
||||
*
|
||||
* @return int maximum description time adding one
|
||||
*/
|
||||
public function get_max_description_type()
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$course_id = api_get_course_int_id();
|
||||
|
||||
$sql = "SELECT MAX(description_type) as MAX
|
||||
FROM $table
|
||||
WHERE c_id = $course_id AND session_id='".$this->session_id."'";
|
||||
$rs = Database::query($sql);
|
||||
$max = Database::fetch_array($rs);
|
||||
|
||||
if ($max['MAX'] >= 8) {
|
||||
$description_type = 8;
|
||||
} else {
|
||||
$description_type = $max['MAX'] + 1;
|
||||
}
|
||||
|
||||
if ($description_type < ADD_BLOCK) {
|
||||
$description_type = ADD_BLOCK;
|
||||
}
|
||||
|
||||
return $description_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a description to the course_description table,
|
||||
* first you must set description_type, title, content, progress and
|
||||
* session_id properties with the object CourseDescription.
|
||||
*
|
||||
* @return int affected rows
|
||||
*/
|
||||
public function insert()
|
||||
{
|
||||
if (empty($this->course_id)) {
|
||||
$course_id = api_get_course_int_id();
|
||||
} else {
|
||||
$course_id = $this->course_id;
|
||||
}
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
|
||||
$params = [
|
||||
'c_id' => $course_id,
|
||||
'description_type' => $this->description_type,
|
||||
'title' => $this->title,
|
||||
'content' => $this->content,
|
||||
'progress' => intval($this->progress),
|
||||
'session_id' => $this->session_id,
|
||||
];
|
||||
|
||||
$last_id = Database::insert($table, $params);
|
||||
|
||||
if ($last_id > 0) {
|
||||
$sql = "UPDATE $table SET id = iid WHERE iid = $last_id";
|
||||
Database::query($sql);
|
||||
|
||||
// insert into item_property
|
||||
api_item_property_update(
|
||||
api_get_course_info(),
|
||||
TOOL_COURSE_DESCRIPTION,
|
||||
$last_id,
|
||||
'CourseDescriptionAdded',
|
||||
api_get_user_id()
|
||||
);
|
||||
}
|
||||
|
||||
return $last_id > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a description, first you must set description_type, title, content, progress
|
||||
* and session_id properties with the object CourseDescription.
|
||||
*
|
||||
* @return int affected rows
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$params = [
|
||||
'title' => $this->title,
|
||||
'content' => $this->content,
|
||||
'progress' => intval($this->progress),
|
||||
];
|
||||
|
||||
Database::update(
|
||||
$table,
|
||||
$params,
|
||||
[
|
||||
'id = ? AND session_id = ? AND c_id = ?' => [
|
||||
$this->id,
|
||||
$this->session_id,
|
||||
$this->course_id ? $this->course_id : api_get_course_int_id(),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
if ($this->id > 0) {
|
||||
// Insert into item_property
|
||||
api_item_property_update(
|
||||
api_get_course_info(),
|
||||
TOOL_COURSE_DESCRIPTION,
|
||||
$this->id,
|
||||
'CourseDescriptionUpdated',
|
||||
api_get_user_id()
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a description, first you must set description_type and session_id
|
||||
* properties with the object CourseDescription.
|
||||
*
|
||||
* @return int affected rows
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
|
||||
$course_id = api_get_course_int_id();
|
||||
$sql = "DELETE FROM $table
|
||||
WHERE
|
||||
c_id = $course_id AND
|
||||
id = '".intval($this->id)."' AND
|
||||
session_id = '".intval($this->session_id)."'";
|
||||
$result = Database::query($sql);
|
||||
$affected_rows = Database::affected_rows($result);
|
||||
if ($this->id > 0) {
|
||||
//insert into item_property
|
||||
api_item_property_update(
|
||||
api_get_course_info(),
|
||||
TOOL_COURSE_DESCRIPTION,
|
||||
$this->id,
|
||||
'CourseDescriptionDeleted',
|
||||
api_get_user_id()
|
||||
);
|
||||
}
|
||||
|
||||
return $affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description titles by default.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_description_title()
|
||||
{
|
||||
$default_description_titles = [];
|
||||
$default_description_titles[1] = get_lang('GeneralDescription');
|
||||
$default_description_titles[2] = get_lang('Objectives');
|
||||
$default_description_titles[3] = get_lang('Topics');
|
||||
$default_description_titles[4] = get_lang('Methodology');
|
||||
$default_description_titles[5] = get_lang('CourseMaterial');
|
||||
$default_description_titles[6] = get_lang('HumanAndTechnicalResources');
|
||||
$default_description_titles[7] = get_lang('Assessment');
|
||||
$default_description_titles[8] = get_lang('Other');
|
||||
|
||||
return $default_description_titles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description titles editable by default.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_description_title_editable()
|
||||
{
|
||||
$default_description_title_editable = [];
|
||||
$default_description_title_editable[1] = true;
|
||||
$default_description_title_editable[2] = true;
|
||||
$default_description_title_editable[3] = true;
|
||||
$default_description_title_editable[4] = true;
|
||||
$default_description_title_editable[5] = true;
|
||||
$default_description_title_editable[6] = true;
|
||||
$default_description_title_editable[7] = true;
|
||||
|
||||
return $default_description_title_editable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get description icons by default.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_description_icon()
|
||||
{
|
||||
$default_description_icon = [];
|
||||
$default_description_icon[1] = 'info.png';
|
||||
$default_description_icon[2] = 'objective.png';
|
||||
$default_description_icon[3] = 'topics.png';
|
||||
$default_description_icon[4] = 'strategy.png';
|
||||
$default_description_icon[5] = 'laptop.png';
|
||||
$default_description_icon[6] = 'teacher.png';
|
||||
$default_description_icon[7] = 'assessment.png';
|
||||
$default_description_icon[8] = 'wizard.png';
|
||||
|
||||
return $default_description_icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get questions by default for help.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_question()
|
||||
{
|
||||
$question = [];
|
||||
$question[1] = get_lang('GeneralDescriptionQuestions');
|
||||
$question[2] = get_lang('ObjectivesQuestions');
|
||||
$question[3] = get_lang('TopicsQuestions');
|
||||
$question[4] = get_lang('MethodologyQuestions');
|
||||
$question[5] = get_lang('CourseMaterialQuestions');
|
||||
$question[6] = get_lang('HumanAndTechnicalResourcesQuestions');
|
||||
$question[7] = get_lang('AssessmentQuestions');
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get informations by default for help.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_information()
|
||||
{
|
||||
$information = [];
|
||||
$information[1] = get_lang('GeneralDescriptionInformation');
|
||||
$information[2] = get_lang('ObjectivesInformation');
|
||||
$information[3] = get_lang('TopicsInformation');
|
||||
$information[4] = get_lang('MethodologyInformation');
|
||||
$information[5] = get_lang('CourseMaterialInformation');
|
||||
$information[6] = get_lang('HumanAndTechnicalResourcesInformation');
|
||||
$information[7] = get_lang('AssessmentInformation');
|
||||
|
||||
return $information;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description id.
|
||||
*/
|
||||
public function set_id($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description's course id.
|
||||
*
|
||||
* @param int $id Course ID
|
||||
*/
|
||||
public function set_course_id($id)
|
||||
{
|
||||
$this->course_id = intval($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description title.
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function set_title($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description content.
|
||||
*
|
||||
* @param string $content
|
||||
*/
|
||||
public function set_content($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description session id.
|
||||
*
|
||||
* @param int $session_id
|
||||
*/
|
||||
public function set_session_id($session_id)
|
||||
{
|
||||
$this->session_id = $session_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set description type.
|
||||
*/
|
||||
public function set_description_type($description_type)
|
||||
{
|
||||
$this->description_type = $description_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set progress of a description.
|
||||
*
|
||||
* @param string $progress
|
||||
*/
|
||||
public function set_progress($progress)
|
||||
{
|
||||
$this->progress = $progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* get description id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_id()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* get description title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* get description content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_content()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* get session id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_session_id()
|
||||
{
|
||||
return $this->session_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* get description type.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_description_type()
|
||||
{
|
||||
return $this->description_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* get progress of a description.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_progress()
|
||||
{
|
||||
return $this->progress;
|
||||
}
|
||||
}
|
||||
2027
main/inc/lib/course_home.lib.php
Normal file
2027
main/inc/lib/course_home.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
770
main/inc/lib/course_request.lib.php
Normal file
770
main/inc/lib/course_request.lib.php
Normal file
@@ -0,0 +1,770 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Course request manager.
|
||||
*
|
||||
* @author José Manuel Abuin Mosquera <chema@cesga.es>, 2010
|
||||
* @author Bruno Rubio Gayo <brubio@cesga.es>, 2010
|
||||
* Centro de Supercomputacion de Galicia (CESGA)
|
||||
* @author Ivan Tcholakov <ivantcholakov@gmail.com> (technical adaptation for Chamilo 1.8.8), 2010
|
||||
*/
|
||||
class CourseRequestManager
|
||||
{
|
||||
/**
|
||||
* Checks whether a given course code has been already occupied.
|
||||
*
|
||||
* @param string $wanted_course_code the code to be checked
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if there is created:
|
||||
* - a course with the same code OR visual_code (visualcode).
|
||||
* - a course request with the same code as the given one, or
|
||||
* Othewise returns FALSE.
|
||||
*/
|
||||
public static function course_code_exists($wanted_course_code)
|
||||
{
|
||||
if ($code_exists = CourseManager::course_code_exists($wanted_course_code)) {
|
||||
return $code_exists;
|
||||
}
|
||||
$table_course_request = Database::get_main_table(TABLE_MAIN_COURSE_REQUEST);
|
||||
$wanted_course_code = Database::escape_string($wanted_course_code);
|
||||
$sql = sprintf(
|
||||
'SELECT COUNT(id) AS number FROM %s WHERE visual_code = "%s"',
|
||||
$table_course_request,
|
||||
$wanted_course_code
|
||||
);
|
||||
$result = Database::fetch_array(Database::query($sql));
|
||||
|
||||
return $result['number'] > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new course request within the database.
|
||||
*
|
||||
* @param string $wanted_code the code for the created in the future course
|
||||
* @param string $title
|
||||
* @param string $description
|
||||
* @param string $category_code
|
||||
* @param string $course_language
|
||||
* @param string $objectives
|
||||
* @param string $target_audience
|
||||
* @param int $user_id
|
||||
*
|
||||
* @return mixed the database id of the newly created course request or FALSE on failure
|
||||
*/
|
||||
public static function create_course_request(
|
||||
$wanted_code,
|
||||
$title,
|
||||
$description,
|
||||
$category_code,
|
||||
$course_language,
|
||||
$objectives,
|
||||
$target_audience,
|
||||
$user_id,
|
||||
$exemplary_content
|
||||
) {
|
||||
$wanted_code = trim($wanted_code);
|
||||
$user_id = (int) $user_id;
|
||||
$exemplary_content = (bool) $exemplary_content ? 1 : 0;
|
||||
|
||||
if ('' == $wanted_code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self::course_code_exists($wanted_code)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (!is_array($user_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tutor_name = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $course_language);
|
||||
|
||||
$request_date = api_get_utc_datetime();
|
||||
$status = COURSE_REQUEST_PENDING;
|
||||
$info = 0;
|
||||
$keys = AddCourse::define_course_keys($wanted_code, '');
|
||||
if (!count($keys)) {
|
||||
return false;
|
||||
}
|
||||
$visual_code = $keys['currentCourseCode'];
|
||||
$code = $keys['currentCourseId'];
|
||||
$db_name = isset($keys['currentCourseDbName']) ? $keys['currentCourseDbName'] : null;
|
||||
$directory = $keys['currentCourseRepository'];
|
||||
// @todo user entity
|
||||
$sql = sprintf(
|
||||
'INSERT INTO %s (
|
||||
code, user_id, directory, db_name,
|
||||
course_language, title, description, category_code,
|
||||
tutor_name, visual_code, request_date,
|
||||
objetives, target_audience, status, info, exemplary_content)
|
||||
VALUES (
|
||||
"%s", "%s", "%s", "%s",
|
||||
"%s", "%s", "%s", "%s",
|
||||
"%s", "%s", "%s",
|
||||
"%s", "%s", "%s", "%s", "%s");',
|
||||
Database::get_main_table(TABLE_MAIN_COURSE_REQUEST),
|
||||
Database::escape_string($code),
|
||||
Database::escape_string($user_id),
|
||||
Database::escape_string($directory),
|
||||
Database::escape_string($db_name),
|
||||
Database::escape_string($course_language),
|
||||
Database::escape_string($title),
|
||||
Database::escape_string($description),
|
||||
Database::escape_string($category_code),
|
||||
Database::escape_string($tutor_name),
|
||||
Database::escape_string($visual_code),
|
||||
Database::escape_string($request_date),
|
||||
Database::escape_string($objectives),
|
||||
Database::escape_string($target_audience),
|
||||
Database::escape_string($status),
|
||||
Database::escape_string($info),
|
||||
Database::escape_string($exemplary_content)
|
||||
);
|
||||
|
||||
$result_sql = Database::query($sql);
|
||||
|
||||
if (!$result_sql) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$last_insert_id = Database::insert_id();
|
||||
|
||||
// E-mail notifications.
|
||||
|
||||
$email_language = $user_info['language'];
|
||||
$email_language_admin = api_get_setting('platformLanguage');
|
||||
|
||||
$email_subject = sprintf(get_lang('CourseRequestEmailSubject', null, $email_language), '['.api_get_setting('siteName').']', $code);
|
||||
|
||||
$email_body = get_lang('CourseRequestMailOpening', null, $email_language)."\n\n";
|
||||
$email_body .= get_lang('CourseName', null, $email_language).': '.$title."\n";
|
||||
$email_body .= get_lang('Fac', null, $email_language).': '.$category_code."\n";
|
||||
$email_body .= get_lang('CourseCode', null, $email_language).': '.$code."\n";
|
||||
$email_body .= get_lang('Professor', null, $email_language).': '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language)."\n";
|
||||
$email_body .= get_lang('Email', null, $email_language).': '.$user_info['mail']."\n";
|
||||
$email_body .= get_lang('Description', null, $email_language).': '.$description."\n";
|
||||
$email_body .= get_lang('Objectives', null, $email_language).': '.$objectives."\n";
|
||||
$email_body .= get_lang('TargetAudience', null, $email_language).': '.$target_audience."\n";
|
||||
$email_body .= get_lang('Ln', null, $email_language).': '.$course_language."\n";
|
||||
$email_body .= get_lang('FillWithExemplaryContent', null, $email_language).': '.($exemplary_content ? get_lang('Yes', null, $email_language) : get_lang('No', null, $email_language))."\n";
|
||||
$email_body = nl2br($email_body);
|
||||
|
||||
// Sending an e-mail to the platform administrator.
|
||||
$email_body_admin = $email_body;
|
||||
$email_body_admin .= "\n".get_lang('CourseRequestPageForApproval', null, $email_language_admin).' '.api_get_path(WEB_CODE_PATH).'admin/course_request_edit.php?id='.$last_insert_id."\n";
|
||||
$email_body_admin .= "\n".get_lang('CourseRequestLegalNote', null, $email_language_admin)."\n";
|
||||
$email_body_admin = nl2br($email_body_admin);
|
||||
|
||||
$sender_name_teacher = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
|
||||
$sender_email_teacher = $user_info['mail'];
|
||||
$recipient_name_admin = api_get_person_name(
|
||||
api_get_setting('administratorName'),
|
||||
api_get_setting('administratorSurname'),
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$recipient_email_admin = api_get_setting('emailAdministrator');
|
||||
|
||||
$userInfo = api_get_user_info($user_id);
|
||||
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::NEW_COURSE_SUGGESTED_TEACHER,
|
||||
'userId' => $user_id,
|
||||
'userUsername' => $userInfo['username'],
|
||||
];
|
||||
|
||||
api_mail_html(
|
||||
$recipient_name_admin,
|
||||
$recipient_email_admin,
|
||||
$email_subject,
|
||||
$email_body_admin,
|
||||
$sender_name_teacher,
|
||||
$sender_email_teacher,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
// Sending an e-mail to the requestor.
|
||||
|
||||
$email_body_teacher = get_lang('Dear', null, $email_language).' ';
|
||||
$email_body_teacher .= api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language).",\n\n";
|
||||
$email_body_teacher .= $email_body;
|
||||
$email_body_teacher .= "\n".get_lang('SignatureFormula', null, $email_language)."\n";
|
||||
$email_body_teacher .= api_get_person_name(
|
||||
api_get_setting('administratorName'),
|
||||
api_get_setting('administratorSurname'),
|
||||
null,
|
||||
null,
|
||||
$email_language
|
||||
)."\n";
|
||||
$email_body_teacher .= get_lang('Manager', null, $email_language).' '.api_get_setting('siteName')."\n";
|
||||
$email_body_teacher .= get_lang('Phone', null, $email_language).': '.api_get_setting('administratorTelephone')."\n";
|
||||
$email_body_teacher .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
|
||||
$email_body_teacher .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
|
||||
$email_body_teacher = nl2br($email_body_teacher);
|
||||
|
||||
// Swap the sender and the recipient.
|
||||
$sender_name_admin = $recipient_name_admin;
|
||||
$sender_email_admin = $recipient_email_admin;
|
||||
$recipient_name_teacher = $sender_name_teacher;
|
||||
$recipient_email_teacher = $sender_email_teacher;
|
||||
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::COURSE_OPENING_REQUEST_CODE_REGISTERED,
|
||||
'userId' => $user_info['user_id'],
|
||||
'courseCode' => $wanted_code,
|
||||
];
|
||||
|
||||
api_mail_html(
|
||||
$recipient_name_teacher,
|
||||
$recipient_email_teacher,
|
||||
$email_subject,
|
||||
$email_body_teacher,
|
||||
$sender_name_admin,
|
||||
$sender_email_admin,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
return $last_insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a given course request in the database.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
* @param string $wanted_code the code for the created in the future course
|
||||
* @param string $title
|
||||
* @param string $description
|
||||
* @param string $category_code
|
||||
* @param string $course_language
|
||||
* @param string $objectives
|
||||
* @param string $target_audience
|
||||
* @param int $user_id
|
||||
*
|
||||
* @return bool returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public static function update_course_request(
|
||||
$id,
|
||||
$wanted_code,
|
||||
$title,
|
||||
$description,
|
||||
$category_code,
|
||||
$course_language,
|
||||
$objectives,
|
||||
$target_audience,
|
||||
$user_id,
|
||||
$exemplary_content
|
||||
) {
|
||||
$id = (int) $id;
|
||||
$wanted_code = trim($wanted_code);
|
||||
$user_id = (int) $user_id;
|
||||
$exemplary_content = (bool) $exemplary_content ? 1 : 0;
|
||||
|
||||
if ('' == $wanted_code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve request data
|
||||
$course_request_info = self::get_course_request_info($id);
|
||||
if (!is_array($course_request_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = $wanted_code;
|
||||
$tutor_name = $course_request_info['tutor_name'];
|
||||
$directory = $course_request_info['directory'];
|
||||
$visual_code = $course_request_info['visual_code'];
|
||||
$request_date = $course_request_info['request_date'];
|
||||
$status = $course_request_info['status'];
|
||||
$info = $course_request_info['info'];
|
||||
|
||||
if ($wanted_code != $course_request_info['code']) {
|
||||
if (self::course_code_exists($wanted_code)) {
|
||||
return false;
|
||||
}
|
||||
$keys = AddCourse::define_course_keys($wanted_code, '');
|
||||
if (count($keys)) {
|
||||
$visual_code = $keys['currentCourseCode'];
|
||||
$code = $keys['currentCourseId'];
|
||||
$db_name = $keys['currentCourseDbName'];
|
||||
$directory = $keys['currentCourseRepository'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($user_id != $course_request_info['code']) {
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (is_array($user_info)) {
|
||||
$tutor_name = api_get_person_name(
|
||||
$user_info['firstname'],
|
||||
$user_info['lastname'],
|
||||
null,
|
||||
null,
|
||||
$course_language
|
||||
);
|
||||
} else {
|
||||
$user_id = $course_request_info['code'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($course_language != $course_request_info['course_language']) {
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (is_array($user_info)) {
|
||||
$tutor_name = api_get_person_name(
|
||||
$user_info['firstname'],
|
||||
$user_info['lastname'],
|
||||
null,
|
||||
null,
|
||||
$course_language
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// @todo use entity
|
||||
$sql = sprintf(
|
||||
'UPDATE %s SET
|
||||
code = "%s", user_id = "%s", directory = "%s", db_name = "%s",
|
||||
course_language = "%s", title = "%s", description = "%s", category_code = "%s",
|
||||
tutor_name = "%s", visual_code = "%s", request_date = "%s",
|
||||
objetives = "%s", target_audience = "%s", status = "%s", info = "%s", exemplary_content = "%s"
|
||||
WHERE id = '.$id,
|
||||
Database::get_main_table(TABLE_MAIN_COURSE_REQUEST),
|
||||
Database::escape_string($code),
|
||||
intval($user_id),
|
||||
Database::escape_string($directory),
|
||||
Database::escape_string($db_name),
|
||||
Database::escape_string($course_language),
|
||||
Database::escape_string($title),
|
||||
Database::escape_string($description),
|
||||
Database::escape_string($category_code),
|
||||
Database::escape_string($tutor_name),
|
||||
Database::escape_string($visual_code),
|
||||
Database::escape_string($request_date),
|
||||
Database::escape_string($objectives),
|
||||
Database::escape_string($target_audience),
|
||||
Database::escape_string($status),
|
||||
Database::escape_string($info),
|
||||
Database::escape_string($exemplary_content)
|
||||
);
|
||||
$result_sql = Database::query($sql);
|
||||
|
||||
return false !== $result_sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a given course request.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
*
|
||||
* @return bool returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public static function delete_course_request($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
$sql = "DELETE FROM ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
WHERE id = ".$id;
|
||||
$result = Database::query($sql);
|
||||
|
||||
return false !== $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of course requests in the course_request table (optionally matching a status).
|
||||
*
|
||||
* @param int $status
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function count_course_requests($status = null)
|
||||
{
|
||||
$course_table = Database::get_main_table(TABLE_MAIN_COURSE_REQUEST);
|
||||
if (is_null($status)) {
|
||||
$sql = "SELECT COUNT(id) AS number FROM ".$course_table;
|
||||
} else {
|
||||
$status = (int) $status;
|
||||
$sql = "SELECT COUNT(id) AS number FROM ".$course_table."
|
||||
WHERE status = ".$status;
|
||||
}
|
||||
$result = Database::fetch_array(Database::query($sql));
|
||||
if (is_array($result)) {
|
||||
return $result['number'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the information about a course request using its database id as an access key.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
*
|
||||
* @return string|bool returns the requested data as an array or FALSE on failure
|
||||
*/
|
||||
public static function get_course_request_info($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
$sql = "SELECT *
|
||||
FROM ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
WHERE id = ".$id;
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result) > 0) {
|
||||
return Database::fetch_array($result);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the code of a given course request using its database id as an access key.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
*
|
||||
* @return string|bool returns the requested requested code or FALSE on failure
|
||||
*/
|
||||
public static function get_course_request_code($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
$sql = "SELECT code
|
||||
FROM ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
WHERE id = ".$id;
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result) > 0) {
|
||||
$result_array = Database::fetch_array($result, 'NUM');
|
||||
if (is_array($result_array)) {
|
||||
return $result_array[0];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a given by its id course request. The requested course gets created immediately after the request acceptance.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
*
|
||||
* @return string|bool returns the code of the newly created course or FALSE on failure
|
||||
*/
|
||||
public static function accept_course_request($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
|
||||
// Retrieve request's data
|
||||
$course_request_info = self::get_course_request_info($id);
|
||||
if (!is_array($course_request_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make all the checks again before the new course creation.
|
||||
/*if (CourseManager::course_code_exists($wanted_code)) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
$user_id = (int) $course_request_info['user_id'];
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (!is_array($user_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the requested course
|
||||
$params = [];
|
||||
|
||||
$params['title'] = $course_request_info['title'];
|
||||
$params['course_category'] = $course_request_info['category_code'];
|
||||
$params['course_language'] = $course_request_info['course_language'];
|
||||
$params['exemplary_content'] = intval($course_request_info['exemplary_content']) > 0;
|
||||
$params['wanted_code'] = $course_request_info['code'];
|
||||
$params['user_id'] = $course_request_info['user_id'];
|
||||
$params['tutor_name'] = api_get_person_name($user_info['firstname'], $user_info['lastname']);
|
||||
|
||||
$course_info = CourseManager::create_course($params);
|
||||
if (!empty($course_info)) {
|
||||
// Mark the request as accepted.
|
||||
$sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
SET status = ".COURSE_REQUEST_ACCEPTED."
|
||||
WHERE id = ".$id;
|
||||
Database::query($sql);
|
||||
|
||||
// E-mail notification.
|
||||
|
||||
// E-mail language: The user language seems to be the best choice
|
||||
$email_language = $user_info['language'];
|
||||
$email_subject = sprintf(get_lang('CourseRequestAcceptedEmailSubject', null, $email_language), '['.api_get_setting('siteName').']', $course_info['code']);
|
||||
|
||||
$email_body = get_lang('Dear', null, $email_language).' ';
|
||||
$email_body .= api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language).",\n\n";
|
||||
$email_body .= sprintf(
|
||||
get_lang(
|
||||
'CourseRequestAcceptedEmailText',
|
||||
null,
|
||||
$email_language
|
||||
),
|
||||
$course_info['code'],
|
||||
$course_info['code'],
|
||||
api_get_path(WEB_COURSE_PATH).$course_info['directory'].'/'
|
||||
)."\n";
|
||||
$email_body .= "\n".get_lang('SignatureFormula', null, $email_language)."\n";
|
||||
$email_body .= api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, null, $email_language)."\n";
|
||||
$email_body .= get_lang('Manager', null, $email_language).' '.api_get_setting('siteName')."\n";
|
||||
$email_body .= get_lang('Phone', null, $email_language).': '.api_get_setting('administratorTelephone')."\n";
|
||||
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
|
||||
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
|
||||
$email_body = nl2br($email_body);
|
||||
|
||||
$sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
|
||||
$sender_email = api_get_setting('emailAdministrator');
|
||||
$recipient_name = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
|
||||
$recipient_email = $user_info['mail'];
|
||||
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::COURSE_OPENING_REQUEST_CODE_APPROVED,
|
||||
'userId' => $user_id,
|
||||
'courseCode' => $course_info['code'],
|
||||
];
|
||||
|
||||
api_mail_html(
|
||||
$recipient_name,
|
||||
$recipient_email,
|
||||
$email_subject,
|
||||
$email_body,
|
||||
$sender_name,
|
||||
$sender_email,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
return $course_info['code'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects a given course request.
|
||||
*
|
||||
* @param int $id the id (an integer number) of the corresponding database record
|
||||
*
|
||||
* @return bool returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public static function reject_course_request($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
// Retrieve request's data
|
||||
$course_request_info = self::get_course_request_info($id);
|
||||
if (!is_array($course_request_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_id = intval($course_request_info['user_id']);
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (!is_array($user_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = $course_request_info['code'];
|
||||
|
||||
$sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
SET status = ".COURSE_REQUEST_REJECTED."
|
||||
WHERE id = ".$id;
|
||||
if (false === Database::query($sql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// E-mail notification.
|
||||
|
||||
// E-mail language: The user language seems to be the best choice.
|
||||
$email_language = $user_info['language'];
|
||||
|
||||
$email_subject = sprintf(get_lang('CourseRequestRejectedEmailSubject', null, $email_language), '['.api_get_setting('siteName').']', $code);
|
||||
|
||||
$email_body = get_lang('Dear', null, $email_language).' ';
|
||||
$email_body .= api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language).",\n\n";
|
||||
$email_body .= sprintf(get_lang('CourseRequestRejectedEmailText', null, $email_language), $code)."\n";
|
||||
$email_body .= "\n".get_lang('SignatureFormula', null, $email_language)."\n";
|
||||
$email_body .= api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, null, $email_language)."\n";
|
||||
$email_body .= get_lang('Manager', null, $email_language).' '.api_get_setting('siteName')."\n";
|
||||
$email_body .= get_lang('Phone', null, $email_language).': '.api_get_setting('administratorTelephone')."\n";
|
||||
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";
|
||||
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
|
||||
$email_body = nl2br($email_body);
|
||||
|
||||
$sender_name = api_get_person_name(
|
||||
api_get_setting('administratorName'),
|
||||
api_get_setting('administratorSurname'),
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$sender_email = api_get_setting('emailAdministrator');
|
||||
$recipient_name = api_get_person_name(
|
||||
$user_info['firstname'],
|
||||
$user_info['lastname'],
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$recipient_email = $user_info['mail'];
|
||||
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::COURSE_OPENING_REQUEST_CODE_REJECTED,
|
||||
'userId' => $user_id,
|
||||
'courseCode' => $code,
|
||||
];
|
||||
|
||||
api_mail_html(
|
||||
$recipient_name,
|
||||
$recipient_email,
|
||||
$email_subject,
|
||||
$email_body,
|
||||
$sender_name,
|
||||
$sender_email,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the author (through e-mail) for additional information about the given course request.
|
||||
*
|
||||
* @param int $id the database primary id of the given request
|
||||
*
|
||||
* @return bool returns TRUE on success or FALSE on failure
|
||||
*/
|
||||
public static function ask_for_additional_info($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
|
||||
// Retrieve request's data
|
||||
$course_request_info = self::get_course_request_info($id);
|
||||
if (!is_array($course_request_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_id = intval($course_request_info['user_id']);
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_info = api_get_user_info($user_id);
|
||||
if (!is_array($user_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = $course_request_info['code'];
|
||||
$info = intval($course_request_info['info']);
|
||||
|
||||
// Error is to be returned on a repeated attempt for asking additional information.
|
||||
if (!empty($info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// E-mail notification.
|
||||
|
||||
// E-mail language: The user language seems to be the best choice.
|
||||
$email_language = $user_info['language'];
|
||||
$email_subject = sprintf(get_lang('CourseRequestAskInfoEmailSubject', null, $email_language), '['.api_get_setting('siteName').']', $code);
|
||||
|
||||
$email_body = get_lang('Dear', null, $email_language).' ';
|
||||
$email_body .= api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language).",\n\n";
|
||||
$email_body .= sprintf(get_lang('CourseRequestAskInfoEmailText', null, $email_language), $code)."\n";
|
||||
$email_body .= "\n".get_lang('SignatureFormula', null, $email_language)."\n";
|
||||
$email_body .= api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n";
|
||||
$email_body .= get_lang('Manager', null, $email_language).' '.api_get_setting('siteName')."\n";
|
||||
$email_body .= get_lang('Phone', null, $email_language).': '.api_get_setting('administratorTelephone')."\n";
|
||||
$email_body .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator')."\n";
|
||||
$email_body .= "\n".get_lang('CourseRequestLegalNote', null, $email_language)."\n";
|
||||
$email_body = nl2br($email_body);
|
||||
|
||||
$sender_name = api_get_person_name(
|
||||
api_get_setting('administratorName'),
|
||||
api_get_setting('administratorSurname'),
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$sender_email = api_get_setting('emailAdministrator');
|
||||
$recipient_name = api_get_person_name(
|
||||
$user_info['firstname'],
|
||||
$user_info['lastname'],
|
||||
null,
|
||||
PERSON_NAME_EMAIL_ADDRESS
|
||||
);
|
||||
$recipient_email = $user_info['mail'];
|
||||
|
||||
$additionalParameters = [
|
||||
'smsType' => SmsPlugin::COURSE_OPENING_REQUEST_CODE,
|
||||
'userId' => $user_id,
|
||||
'courseCode' => $code,
|
||||
];
|
||||
|
||||
$result = api_mail_html(
|
||||
$recipient_name,
|
||||
$recipient_email,
|
||||
$email_subject,
|
||||
$email_body,
|
||||
$sender_name,
|
||||
$sender_email,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$additionalParameters
|
||||
);
|
||||
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Marking the fact that additional information about the request has been asked.
|
||||
$sql = "UPDATE ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
SET info = 1 WHERE id = ".$id;
|
||||
$result = false !== Database::query($sql);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether additional information about the given course request has been asked.
|
||||
*
|
||||
* @param int $id the database primary id of the given request
|
||||
*
|
||||
* @return bool returns TRUE if additional information has been asked or FALSE otherwise
|
||||
*/
|
||||
public static function additional_info_asked($id)
|
||||
{
|
||||
$id = (int) $id;
|
||||
$sql = "SELECT id FROM ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)."
|
||||
WHERE (id = ".$id." AND info > 0)";
|
||||
$result = Database::num_rows(Database::query($sql));
|
||||
|
||||
return !empty($result);
|
||||
}
|
||||
}
|
||||
103
main/inc/lib/custom_pages.class.php
Normal file
103
main/inc/lib/custom_pages.class.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Used to implement the loading of custom pages.
|
||||
*
|
||||
* @license see /license.txt
|
||||
* @author 2011, Jean-Karim Bockstael <jeankarim@cblue.be>
|
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva
|
||||
*/
|
||||
class CustomPages
|
||||
{
|
||||
public const INDEX_LOGGED = 'index-logged';
|
||||
public const INDEX_UNLOGGED = 'index-unlogged';
|
||||
public const LOGGED_OUT = 'loggedout';
|
||||
public const REGISTRATION_FEEDBACK = 'registration-feedback';
|
||||
public const REGISTRATION = 'registration';
|
||||
public const LOST_PASSWORD = 'lostpassword';
|
||||
|
||||
/**
|
||||
* Returns true if custom pages are enabled. False otherwise.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function enabled()
|
||||
{
|
||||
return api_get_setting('use_custom_pages') == 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to a custom page.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function path($name = '')
|
||||
{
|
||||
return api_get_path(SYS_PATH).'custompages/'.$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled display a custom page and exist. Otherwise log error and returns.
|
||||
*
|
||||
* @param string $pageName
|
||||
* @param array $content used to pass data to the custom page
|
||||
*
|
||||
* @return bool False if custom pages is not enabled or file could not be found. Void otherwise.
|
||||
*/
|
||||
public static function display($pageName, $content = [])
|
||||
{
|
||||
if (!self::enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = self::path($pageName.'.php');
|
||||
// Only include file if it exists, otherwise do nothing
|
||||
if (file_exists($file)) {
|
||||
include $file;
|
||||
exit; //finish the execution here - do not return
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not look like this function is being used is being used.
|
||||
*
|
||||
* @param int $url_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getURLImages($url_id = null)
|
||||
{
|
||||
if (is_null($url_id)) {
|
||||
$url = 'http://'.$_SERVER['HTTP_HOST'].'/';
|
||||
$url_id = UrlManager::get_url_id($url);
|
||||
}
|
||||
$url_images_dir = api_get_path(SYS_PATH).'custompages/url-images/';
|
||||
$images = [];
|
||||
for ($img_id = 1; $img_id <= 3; $img_id++) {
|
||||
if (file_exists($url_images_dir.$url_id.'_url_image_'.$img_id.'.png')) {
|
||||
$images[] = api_get_path(WEB_PATH).'custompages/url-images/'.$url_id.'_url_image_'.$img_id.'.png';
|
||||
}
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if exists the file for custom page.
|
||||
*
|
||||
* @param string $pageName The name of custom page
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function exists($pageName)
|
||||
{
|
||||
$fileName = self::path("$pageName.php");
|
||||
|
||||
return file_exists($fileName);
|
||||
}
|
||||
}
|
||||
552
main/inc/lib/dashboard.lib.php
Normal file
552
main/inc/lib/dashboard.lib.php
Normal file
@@ -0,0 +1,552 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* DashboardManager can be used to manage dashboard
|
||||
* author Christian Fasanando <christian1827@gmail.com>.
|
||||
*
|
||||
* @package chamilo.dashboard
|
||||
*/
|
||||
class DashboardManager
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This function allows easy activating and inactivating of dashboard plugins.
|
||||
*/
|
||||
public static function handle_dashboard_plugins()
|
||||
{
|
||||
$token = Security::get_existing_token();
|
||||
$tokenCondition = '&sec_token='.$token;
|
||||
|
||||
/* We scan the plugin directory. Each folder is a potential plugin. */
|
||||
$dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
|
||||
$possiblePlugins = self::getPossibleDashboardPluginsPath();
|
||||
|
||||
$table_cols = ['name', 'version', 'description'];
|
||||
echo Display::page_subheader(get_lang('DashboardPlugins'));
|
||||
echo '<form name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).$tokenCondition.'">';
|
||||
echo '<table class="table table-hover table-striped data_table">';
|
||||
echo '<tr>';
|
||||
echo '<th width="50px">'.get_lang('Enabled').'</th>';
|
||||
echo '<th width="250px">'.get_lang('Name').'</th>';
|
||||
echo '<th width="100px">'.get_lang('Version').'</th>';
|
||||
echo '<th>'.get_lang('Description').'</th>';
|
||||
echo '</tr>';
|
||||
|
||||
$disabled_blocks_data = self::get_block_data_without_plugin();
|
||||
|
||||
// We display all the possible enabled or disabled plugins
|
||||
foreach ($possiblePlugins as $testplugin) {
|
||||
$plugin_info_file = $dashboard_pluginpath.$testplugin."/$testplugin.info";
|
||||
if (file_exists($plugin_info_file) && is_readable($plugin_info_file)) {
|
||||
$plugin_info = api_parse_info_file($plugin_info_file);
|
||||
|
||||
// change index to lower case
|
||||
$plugin_info = array_change_key_case($plugin_info);
|
||||
|
||||
echo '<tr>';
|
||||
self::display_dashboard_plugin_checkboxes($testplugin);
|
||||
for ($i = 0; $i < count($table_cols); $i++) {
|
||||
if (isset($plugin_info[strtolower($table_cols[$i])])) {
|
||||
echo '<td>';
|
||||
echo $plugin_info[$table_cols[$i]];
|
||||
echo '</td>';
|
||||
} else {
|
||||
echo '<td></td>';
|
||||
}
|
||||
}
|
||||
echo '</tr>';
|
||||
} else {
|
||||
if ($testplugin != 'css') {
|
||||
echo Display::tag(
|
||||
'tr',
|
||||
Display::tag(
|
||||
'td',
|
||||
get_lang('CheckFilePermissions').' '.Security::remove_XSS($plugin_info_file),
|
||||
['colspan' => '3']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// display all disabled block data
|
||||
if (count($disabled_blocks_data) > 0) {
|
||||
foreach ($disabled_blocks_data as $disabled_block) {
|
||||
echo '<tr style="background-color:#eee">';
|
||||
echo '<td><center><input type="checkbox" name="disabled_block" value="true" checked disabled /></center>';
|
||||
for ($j = 0; $j < count($table_cols); $j++) {
|
||||
if (isset($disabled_block[strtolower($table_cols[$j])])) {
|
||||
if ($j == 2) {
|
||||
echo '<td>';
|
||||
echo '<font color="#aaa">'.$disabled_block[$table_cols[$j]].'</font><br />';
|
||||
echo '<font color="red">'.get_lang('ThisPluginHasbeenDeletedFromDashboardPluginDirectory').'</font>';
|
||||
echo '</td>';
|
||||
} else {
|
||||
echo '<td>';
|
||||
echo '<font color="#aaa">'.$disabled_block[$table_cols[$j]].'</font>';
|
||||
echo '</td>';
|
||||
}
|
||||
} else {
|
||||
echo '<td> </td>';
|
||||
}
|
||||
}
|
||||
echo '</tr>';
|
||||
}
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
echo '<br />';
|
||||
echo '<button class="btn btn-default" type="submit" name="submit_dashboard_plugins" value="'.get_lang('EnableDashboardPlugins').'">'.
|
||||
get_lang('EnableDashboardPlugins').'</button></form>';
|
||||
}
|
||||
|
||||
/**
|
||||
* display checkboxes for dashboard plugin list.
|
||||
*
|
||||
* @param string $plugin_path
|
||||
*/
|
||||
public static function display_dashboard_plugin_checkboxes($plugin_path)
|
||||
{
|
||||
$tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
|
||||
|
||||
$sql = "SELECT * FROM $tbl_block
|
||||
WHERE path = '".Database::escape_string($plugin_path)."' AND active = 1";
|
||||
$rs = Database::query($sql);
|
||||
|
||||
$checked = '';
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
$checked = "checked";
|
||||
}
|
||||
|
||||
echo "<td align=\"center\">";
|
||||
echo '<input type="checkbox" name="'.$plugin_path.'" value="true" '.$checked.'/>';
|
||||
echo "</td>";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function allows easy activating and inactivating
|
||||
* of plugins and save them inside db.
|
||||
*
|
||||
* @param array $plugin_paths dashboard plugin paths
|
||||
* return int affected rows
|
||||
*/
|
||||
public static function store_dashboard_plugins($plugin_paths)
|
||||
{
|
||||
$tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
|
||||
$affected_rows = 0;
|
||||
|
||||
// get all plugins path inside plugin directory
|
||||
$dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
|
||||
$possiblePlugins = self::getPossibleDashboardPluginsPath();
|
||||
|
||||
if (count($possiblePlugins) > 0) {
|
||||
$selected_plugins = array_intersect(array_keys($plugin_paths), $possiblePlugins);
|
||||
$not_selected_plugins = array_diff($possiblePlugins, array_keys($plugin_paths));
|
||||
|
||||
// get blocks id from not selected path
|
||||
$not_selected_blocks_id = [];
|
||||
foreach ($not_selected_plugins as $plugin) {
|
||||
$block_data = self::get_enabled_dashboard_blocks($plugin);
|
||||
if (!empty($block_data[$plugin])) {
|
||||
$not_selected_blocks_id[] = $block_data[$plugin]['id'];
|
||||
}
|
||||
}
|
||||
|
||||
/* clean not selected plugins for extra user data and block data */
|
||||
// clean from extra user data
|
||||
$field_variable = 'dashboard';
|
||||
$extra_user_data = UserManager::get_extra_user_data_by_field_variable($field_variable);
|
||||
if (!empty($extra_user_data) && count($extra_user_data) > 0) {
|
||||
foreach ($extra_user_data as $key => $user_data) {
|
||||
$user_id = $key;
|
||||
$user_block_data = self::get_user_block_data($user_id);
|
||||
$user_block_id = array_keys($user_block_data);
|
||||
|
||||
// clean disabled block data
|
||||
foreach ($user_block_id as $block_id) {
|
||||
if (in_array($block_id, $not_selected_blocks_id)) {
|
||||
unset($user_block_data[$block_id]);
|
||||
}
|
||||
}
|
||||
|
||||
// get columns and blocks id for updating extra user data
|
||||
$columns = [];
|
||||
$user_blocks_id = [];
|
||||
foreach ($user_block_data as $data) {
|
||||
$user_blocks_id[$data['block_id']] = true;
|
||||
$columns[$data['block_id']] = $data['column'];
|
||||
}
|
||||
|
||||
// update extra user blocks data
|
||||
self::store_user_blocks($user_id, $user_blocks_id, $columns);
|
||||
}
|
||||
}
|
||||
// clean from block data
|
||||
if (!empty($not_selected_blocks_id)) {
|
||||
$sql_check = "SELECT id FROM $tbl_block
|
||||
WHERE id IN(".implode(',', $not_selected_blocks_id).")";
|
||||
$rs_check = Database::query($sql_check);
|
||||
if (Database::num_rows($rs_check) > 0) {
|
||||
$del = "DELETE FROM $tbl_block WHERE id IN(".implode(',', $not_selected_blocks_id).")";
|
||||
Database::query($del);
|
||||
}
|
||||
}
|
||||
|
||||
// store selected plugins
|
||||
if (!empty($selected_plugins) && count($selected_plugins) > 0) {
|
||||
foreach ($selected_plugins as $testplugin) {
|
||||
$selected_path = Database::escape_string($testplugin);
|
||||
|
||||
// check if the path already stored inside block table for updating or adding it
|
||||
$sql = "SELECT path FROM $tbl_block WHERE path = '$selected_path'";
|
||||
$rs = Database::query($sql);
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
// update
|
||||
$upd = "UPDATE $tbl_block SET active = 1 WHERE path = '$selected_path'";
|
||||
$result = Database::query($upd);
|
||||
$affected_rows = Database::affected_rows($result);
|
||||
} else {
|
||||
// insert
|
||||
$plugin_info_file = $dashboard_pluginpath.$testplugin."/$testplugin.info";
|
||||
$plugin_info = [];
|
||||
if (file_exists($plugin_info_file)) {
|
||||
$plugin_info = api_parse_info_file($plugin_info_file);
|
||||
}
|
||||
|
||||
// change keys to lower case
|
||||
$plugin_info = array_change_key_case($plugin_info);
|
||||
|
||||
// setting variables
|
||||
$plugin_name = $testplugin;
|
||||
$plugin_description = '';
|
||||
$plugin_controller = '';
|
||||
$plugin_path = $testplugin;
|
||||
|
||||
if (isset($plugin_info['name'])) {
|
||||
$plugin_name = Database::escape_string($plugin_info['name']);
|
||||
}
|
||||
if (isset($plugin_info['description'])) {
|
||||
$plugin_description = Database::escape_string($plugin_info['description']);
|
||||
}
|
||||
if (isset($plugin_info['controller'])) {
|
||||
$plugin_controller = Database::escape_string($plugin_info['controller']);
|
||||
}
|
||||
|
||||
$ins = "INSERT INTO $tbl_block(name, description, path, controller)
|
||||
VALUES ('$plugin_name', '$plugin_description', '$plugin_path', '$plugin_controller')";
|
||||
$result = Database::query($ins);
|
||||
$affected_rows = Database::affected_rows($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plugins path inside dashboard directory.
|
||||
*
|
||||
* @return array name plugins directories
|
||||
*/
|
||||
public static function getPossibleDashboardPluginsPath()
|
||||
{
|
||||
// get all plugins path inside plugin directory
|
||||
/* We scan the plugin directory. Each folder is a potential plugin. */
|
||||
$possiblePlugins = [];
|
||||
$dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
|
||||
$handle = @opendir($dashboard_pluginpath);
|
||||
while (false !== ($file = readdir($handle))) {
|
||||
if ($file != '.' && $file != '..' && is_dir($dashboard_pluginpath.$file)) {
|
||||
$possiblePlugins[] = $file;
|
||||
}
|
||||
}
|
||||
@closedir($handle);
|
||||
|
||||
return $possiblePlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all blocks data without plugin directory.
|
||||
*
|
||||
* @return array Block data
|
||||
*/
|
||||
public static function get_block_data_without_plugin()
|
||||
{
|
||||
$tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
|
||||
$possiblePlugins = self::getPossibleDashboardPluginsPath();
|
||||
|
||||
// We check if plugin exists inside directory for updating active field
|
||||
$sql = "SELECT * FROM $tbl_block";
|
||||
$rs = Database::query($sql);
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
while ($row = Database::fetch_array($rs)) {
|
||||
if (!in_array($row['path'], $possiblePlugins)) {
|
||||
$active = 0;
|
||||
} else {
|
||||
$active = 1;
|
||||
}
|
||||
// update active
|
||||
$upd = "UPDATE $tbl_block SET active = '$active'
|
||||
WHERE path = '".$row['path']."'";
|
||||
Database::query($upd);
|
||||
}
|
||||
}
|
||||
|
||||
// get disabled block data
|
||||
$block_data = [];
|
||||
$sql = "SELECT * FROM $tbl_block WHERE active = 0";
|
||||
$rs_block = Database::query($sql);
|
||||
if (Database::num_rows($rs_block) > 0) {
|
||||
while ($row_block = Database::fetch_array($rs_block)) {
|
||||
$block_data[] = $row_block;
|
||||
}
|
||||
}
|
||||
|
||||
return $block_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get data about enabled dashboard block (stored insise block table).
|
||||
*
|
||||
* @param string $path plugin path
|
||||
*
|
||||
* @return array data
|
||||
*/
|
||||
public static function get_enabled_dashboard_blocks($path = '')
|
||||
{
|
||||
$tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
|
||||
$condition_path = '';
|
||||
if (!empty($path)) {
|
||||
$path = Database::escape_string($path);
|
||||
$condition_path = ' AND path = "'.$path.'" ';
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM $tbl_block WHERE active = 1 $condition_path ";
|
||||
$rs = Database::query($sql);
|
||||
$block_data = [];
|
||||
if (Database::num_rows($rs) > 0) {
|
||||
while ($row = Database::fetch_array($rs)) {
|
||||
$block_data[$row['path']] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $block_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* display user dashboard list.
|
||||
*
|
||||
* @param int User id
|
||||
*/
|
||||
public static function display_user_dashboard_list($user_id)
|
||||
{
|
||||
$enabled_dashboard_plugins = self::get_enabled_dashboard_blocks();
|
||||
$user_block_data = self::get_user_block_data($user_id);
|
||||
$html = '';
|
||||
if (count($enabled_dashboard_plugins) > 0) {
|
||||
$html .= '<div style="margin-top:20px">';
|
||||
$html .= '<div><strong>'.get_lang('SelectBlockForDisplayingInsideBlocksDashboardView').'</strong></div><br />';
|
||||
$html .= '<form name="dashboard_list" method="post" action="index.php?action=store_user_block">';
|
||||
$html .= '<table class="table table-hover table-striped data_table">';
|
||||
$html .= '<tr>';
|
||||
$html .= '<th width="5%">';
|
||||
$html .= get_lang('Enabled');
|
||||
$html .= '</th>';
|
||||
$html .= '<th width="30%">';
|
||||
$html .= get_lang('Name');
|
||||
$html .= '</th>';
|
||||
$html .= '<th width="40%">';
|
||||
$html .= get_lang('Description');
|
||||
$html .= '</th>';
|
||||
$html .= '<th>';
|
||||
$html .= get_lang('ColumnPosition');
|
||||
$html .= '</th>';
|
||||
$html .= '</tr>';
|
||||
|
||||
// We display all enabled plugins and the checkboxes
|
||||
foreach ($enabled_dashboard_plugins as $block) {
|
||||
$path = $block['path'];
|
||||
$controller_class = $block['controller'];
|
||||
$filename_controller = $path.'.class.php';
|
||||
$dashboard_plugin_path = api_get_path(SYS_PLUGIN_PATH).'dashboard/'.$path.'/';
|
||||
require_once $dashboard_plugin_path.$filename_controller;
|
||||
if (class_exists($controller_class)) {
|
||||
$obj_block = new $controller_class($user_id);
|
||||
|
||||
// check if user is allowed to see the block
|
||||
if (method_exists($obj_block, 'is_block_visible_for_user')) {
|
||||
$is_block_visible_for_user = $obj_block->is_block_visible_for_user($user_id);
|
||||
if (!$is_block_visible_for_user) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '<tr>';
|
||||
// checkboxes
|
||||
$html .= self::display_user_dashboard_list_checkboxes($user_id, $block['id']);
|
||||
$html .= '<td>'.$block['name'].'</td>';
|
||||
$html .= '<td>'.$block['description'].'</td>';
|
||||
$html .= '<td>
|
||||
<select class="selectpicker form-control" name="columns['.$block['id'].']">
|
||||
<option value="1" '.(isset($user_block_data[$block['id']]) && $user_block_data[$block['id']]['column'] == 1 ? 'selected' : '').' >1</option>
|
||||
<option value="2" '.(isset($user_block_data[$block['id']]) && $user_block_data[$block['id']]['column'] == 2 ? 'selected' : '').' >2</option>
|
||||
</select>
|
||||
</td>';
|
||||
$html .= '</tr>';
|
||||
} else {
|
||||
$html .= Display::tag('tr', Display::tag('td', get_lang('Error').' '.$controller_class, ['colspan' => '3']));
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</table>';
|
||||
$html .= '<div class="row"><div class="col-md-12">';
|
||||
$html .= '<button class="btn btn-default" type="submit" name="submit_dashboard_list" value="'.get_lang('EnableDashboardBlock').'"><em class="fa fa-check-square"></em> '.
|
||||
get_lang('EnableDashboardBlock').'</button></form>';
|
||||
$html .= '</div></div>';
|
||||
} else {
|
||||
$html .= '<div style="margin-top:20px">'.get_lang('ThereAreNoEnabledDashboardPlugins').'</div>';
|
||||
if (api_is_platform_admin()) {
|
||||
$html .= '<a class="btn btn-default" href="'.api_get_path(WEB_CODE_PATH).'admin/settings.php?category=Plugins">'.
|
||||
get_lang('ConfigureDashboardPlugin').'</a>';
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* display checkboxes for user dashboard list.
|
||||
*
|
||||
* @param int User id
|
||||
* @param int Block id
|
||||
*/
|
||||
public static function display_user_dashboard_list_checkboxes($user_id, $block_id)
|
||||
{
|
||||
$user_id = intval($user_id);
|
||||
$user_block_data = self::get_user_block_data($user_id);
|
||||
$enabled_blocks_id = array_keys($user_block_data);
|
||||
|
||||
$checked = '';
|
||||
if (in_array($block_id, $enabled_blocks_id)) {
|
||||
$checked = "checked";
|
||||
}
|
||||
|
||||
$html = "<td align=\"center\">";
|
||||
$html .= '<input type="checkbox" name="enabled_blocks['.$block_id.']" value="true" '.$checked.'/>';
|
||||
$html .= "</td>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function store enabled blocks id with its column position (block_id1:colum;block_id2:colum; ...)
|
||||
* inside extra user fields.
|
||||
*
|
||||
* @param int $user_id User id
|
||||
* @param array $enabled_blocks selected blocks
|
||||
* @param array $columns columns position
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function store_user_blocks($user_id, $enabled_blocks, $columns)
|
||||
{
|
||||
$selected_blocks_id = [];
|
||||
if (is_array($enabled_blocks) && count($enabled_blocks) > 0) {
|
||||
$selected_blocks_id = array_keys($enabled_blocks);
|
||||
}
|
||||
|
||||
// build data for storing inside extra user field
|
||||
$fname = 'dashboard';
|
||||
$fvalue = [];
|
||||
foreach ($selected_blocks_id as $block_id) {
|
||||
$fvalue[] = $block_id.':'.$columns[$block_id];
|
||||
}
|
||||
$upd_extra_field = UserManager::update_extra_field_value(
|
||||
$user_id,
|
||||
$fname,
|
||||
$fvalue
|
||||
);
|
||||
|
||||
return $upd_extra_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get user block data (block id with its number of column) from extra user data.
|
||||
*
|
||||
* @param int User id
|
||||
*
|
||||
* @return array data (block_id,column)
|
||||
*/
|
||||
public static function get_user_block_data($user_id)
|
||||
{
|
||||
$user_id = intval($user_id);
|
||||
$field_variable = 'dashboard';
|
||||
$extra_user_data = UserManager::get_extra_user_data_by_field($user_id, $field_variable);
|
||||
|
||||
if (!isset($extra_user_data[$field_variable])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$extra_user_data = explode(';', $extra_user_data[$field_variable]);
|
||||
$data = [];
|
||||
foreach ($extra_user_data as $extra) {
|
||||
$split_extra = explode(':', $extra);
|
||||
if (!empty($split_extra)) {
|
||||
$block_id = $split_extra[0];
|
||||
$column = isset($split_extra[1]) ? $split_extra[1] : null;
|
||||
$data[$block_id] = ['block_id' => $block_id, 'column' => $column];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function update extra user blocks data after closing a dashboard block.
|
||||
*
|
||||
* @param int $user_id User id
|
||||
* @param string plugin path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function close_user_block($user_id, $path)
|
||||
{
|
||||
$enabled_dashboard_blocks = self::get_enabled_dashboard_blocks($path);
|
||||
$user_block_data = self::get_user_block_data($user_id);
|
||||
|
||||
foreach ($enabled_dashboard_blocks as $enabled_block) {
|
||||
unset($user_block_data[$enabled_block['id']]);
|
||||
}
|
||||
|
||||
// get columns and blocks id for updating extra user data
|
||||
$columns = [];
|
||||
$user_blocks_id = [];
|
||||
foreach ($user_block_data as $data) {
|
||||
$user_blocks_id[$data['block_id']] = true;
|
||||
$columns[$data['block_id']] = $data['column'];
|
||||
}
|
||||
|
||||
// update extra user blocks data
|
||||
$upd_extra_field = self::store_user_blocks($user_id, $user_blocks_id, $columns);
|
||||
|
||||
return $upd_extra_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* get links for styles from dashboard plugins.
|
||||
*
|
||||
* @return string links
|
||||
*/
|
||||
public static function getStyleSheet()
|
||||
{
|
||||
return '<link rel="stylesheet" href="'.api_get_path(WEB_PLUGIN_PATH).'dashboard/css/default.css" type="text/css" />'.PHP_EOL;
|
||||
}
|
||||
}
|
||||
353
main/inc/lib/database.constants.inc.php
Normal file
353
main/inc/lib/database.constants.inc.php
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Database constants definition for Chamilo
|
||||
* This file is called by database.lib.php.
|
||||
*
|
||||
* @todo the table constants have all to start with TABLE_
|
||||
* This is because of the analogy with the tool constants TOOL_
|
||||
*/
|
||||
|
||||
//See #3910 defines the default prefix for the single course database
|
||||
// Modified by hubert.borderiou 2011-10-21 Add course category
|
||||
define('DB_COURSE_PREFIX', 'c_');
|
||||
|
||||
// Main database tables
|
||||
define('TABLE_MAIN_COURSE', 'course');
|
||||
define('TABLE_MAIN_USER', 'user');
|
||||
define('TABLE_MAIN_CLASS', 'class_item');
|
||||
define('TABLE_MAIN_ADMIN', 'admin');
|
||||
define('TABLE_MAIN_COURSE_CLASS', 'course_rel_class');
|
||||
define('TABLE_MAIN_COURSE_USER', 'course_rel_user');
|
||||
define('TABLE_MAIN_COURSE_CATALOGUE_USER', 'course_rel_user_catalogue');
|
||||
define('TABLE_MAIN_CLASS_USER', 'class_user');
|
||||
define('TABLE_MAIN_CATEGORY', 'course_category');
|
||||
define('TABLE_MAIN_COURSE_MODULE', 'course_module');
|
||||
define('TABLE_MAIN_SYSTEM_ANNOUNCEMENTS', 'sys_announcement');
|
||||
define('TABLE_MAIN_SYSTEM_ANNOUNCEMENTS_GROUPS', 'announcement_rel_group');
|
||||
define('TABLE_MAIN_LANGUAGE', 'language');
|
||||
define('TABLE_MAIN_SETTINGS_OPTIONS', 'settings_options');
|
||||
define('TABLE_MAIN_SETTINGS_CURRENT', 'settings_current');
|
||||
define('TABLE_MAIN_SESSION', 'session');
|
||||
define('TABLE_MAIN_SESSION_CATEGORY', 'session_category');
|
||||
define('TABLE_MAIN_SESSION_COURSE', 'session_rel_course');
|
||||
define('TABLE_MAIN_SESSION_USER', 'session_rel_user');
|
||||
define('TABLE_MAIN_SESSION_CLASS', 'session_rel_class');
|
||||
define('TABLE_MAIN_SESSION_COURSE_USER', 'session_rel_course_rel_user');
|
||||
define('TABLE_MAIN_SHARED_SURVEY', 'shared_survey');
|
||||
define('TABLE_MAIN_SHARED_SURVEY_QUESTION', 'shared_survey_question');
|
||||
define('TABLE_MAIN_SHARED_SURVEY_QUESTION_OPTION', 'shared_survey_question_option');
|
||||
define('TABLE_MAIN_TEMPLATES', 'templates');
|
||||
define('TABLE_MAIN_SYSTEM_TEMPLATE', 'system_template');
|
||||
define('TABLE_MAIN_OPENID_ASSOCIATION', 'openid_association');
|
||||
define('TABLE_MAIN_COURSE_REQUEST', 'course_request');
|
||||
|
||||
// Gradebook.
|
||||
define('TABLE_MAIN_GRADEBOOK_CATEGORY', 'gradebook_category');
|
||||
define('TABLE_MAIN_GRADEBOOK_EVALUATION', 'gradebook_evaluation');
|
||||
define('TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG', 'gradebook_linkeval_log');
|
||||
define('TABLE_MAIN_GRADEBOOK_RESULT', 'gradebook_result');
|
||||
define('TABLE_MAIN_GRADEBOOK_RESULT_LOG', 'gradebook_result_log');
|
||||
define('TABLE_MAIN_GRADEBOOK_LINK', 'gradebook_link');
|
||||
define('TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY', 'gradebook_score_display');
|
||||
define('TABLE_MAIN_GRADEBOOK_CERTIFICATE', 'gradebook_certificate');
|
||||
define('TABLE_MAIN_GRADEBOOK_SCORE_LOG', 'gradebook_score_log');
|
||||
define('TABLE_MAIN_GRADEBOOK_RESULT_ATTEMPT', 'gradebook_result_attempt');
|
||||
define('TABLE_MAIN_GRADEBOOK_COMMENT', 'gradebook_comment');
|
||||
|
||||
// Extra fields.
|
||||
define('TABLE_EXTRA_FIELD', 'extra_field');
|
||||
define('TABLE_EXTRA_FIELD_OPTIONS', 'extra_field_options');
|
||||
define('TABLE_EXTRA_FIELD_VALUES', 'extra_field_values');
|
||||
|
||||
define('TABLE_MAIN_USER_FIELD', 'user_field');
|
||||
define('TABLE_MAIN_USER_FIELD_OPTIONS', 'user_field_options');
|
||||
define('TABLE_MAIN_USER_FIELD_VALUES', 'user_field_values');
|
||||
|
||||
/*define('TABLE_MAIN_LP_FIELD', 'lp_field');
|
||||
define('TABLE_MAIN_LP_FIELD_OPTIONS', 'lp_field_options');
|
||||
define('TABLE_MAIN_LP_FIELD_VALUES', 'lp_field_values');*/
|
||||
|
||||
/*define('TABLE_MAIN_CALENDAR_EVENT_FIELD', 'calendar_event_field');
|
||||
define('TABLE_MAIN_CALENDAR_EVENT_OPTIONS', 'calendar_event_options');
|
||||
define('TABLE_MAIN_CALENDAR_EVENT_VALUES', 'calendar_event_values');*/
|
||||
|
||||
//User tags
|
||||
define('TABLE_MAIN_TAG', 'tag');
|
||||
define('TABLE_MAIN_USER_REL_TAG', 'user_rel_tag');
|
||||
define('TABLE_MAIN_EXTRA_FIELD_REL_TAG', 'extra_field_rel_tag');
|
||||
|
||||
// Search engine
|
||||
define('TABLE_MAIN_SPECIFIC_FIELD', 'specific_field');
|
||||
define('TABLE_MAIN_SPECIFIC_FIELD_VALUES', 'specific_field_values');
|
||||
define('TABLE_MAIN_SEARCH_ENGINE_REF', 'search_engine_ref');
|
||||
|
||||
// Access URLs
|
||||
define('TABLE_MAIN_ACCESS_URL', 'access_url');
|
||||
define('TABLE_MAIN_ACCESS_URL_REL_USER', 'access_url_rel_user');
|
||||
define('TABLE_MAIN_ACCESS_URL_REL_COURSE', 'access_url_rel_course');
|
||||
define('TABLE_MAIN_ACCESS_URL_REL_SESSION', 'access_url_rel_session');
|
||||
define('TABLE_MAIN_ACCESS_URL_REL_USERGROUP', 'access_url_rel_usergroup');
|
||||
// This table seems not to be use
|
||||
define('TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY', 'access_url_rel_course_category');
|
||||
|
||||
// Global calendar
|
||||
define('TABLE_MAIN_SYSTEM_CALENDAR', 'sys_calendar');
|
||||
|
||||
// Social networking
|
||||
define('TABLE_MAIN_USER_REL_USER', 'user_rel_user');
|
||||
define('TABLE_MAIN_USER_FRIEND_RELATION_TYPE', 'user_friend_relation_type');
|
||||
|
||||
define('TABLE_MAIN_COURSE_FIELD', 'course_field');
|
||||
define('TABLE_MAIN_COURSE_FIELD_OPTIONS', 'course_field_options');
|
||||
define('TABLE_MAIN_COURSE_FIELD_VALUES', 'course_field_values');
|
||||
define('TABLE_MAIN_SESSION_FIELD', 'session_field');
|
||||
define('TABLE_MAIN_SESSION_FIELD_OPTIONS', 'session_field_options');
|
||||
define('TABLE_MAIN_SESSION_FIELD_VALUES', 'session_field_values');
|
||||
|
||||
// Web services
|
||||
define('TABLE_MAIN_USER_API_KEY', 'user_api_key');
|
||||
|
||||
// Term and conditions
|
||||
define('TABLE_MAIN_LEGAL', 'legal');
|
||||
|
||||
// Dashboard blocks plugin
|
||||
define('TABLE_MAIN_BLOCK', 'block');
|
||||
|
||||
// Statistic database tables
|
||||
define('TABLE_STATISTIC_TRACK_E_LASTACCESS', 'track_e_lastaccess');
|
||||
// Access to specific tools inside a course
|
||||
define('TABLE_STATISTIC_TRACK_E_ACCESS', 'track_e_access');
|
||||
define('TABLE_STATISTIC_TRACK_E_LOGIN', 'track_e_login');
|
||||
define('TABLE_STATISTIC_TRACK_E_DOWNLOADS', 'track_e_downloads');
|
||||
define('TABLE_STATISTIC_TRACK_E_LINKS', 'track_e_links');
|
||||
define('TABLE_STATISTIC_TRACK_E_ONLINE', 'track_e_online');
|
||||
define('TABLE_STATISTIC_TRACK_E_HOTPOTATOES', 'track_e_hotpotatoes');
|
||||
// Access date data (in and out dates in course)
|
||||
define('TABLE_STATISTIC_TRACK_E_COURSE_ACCESS', 'track_e_course_access');
|
||||
define('TABLE_STATISTIC_TRACK_E_EXERCISES', 'track_e_exercises');
|
||||
define('TABLE_STATISTIC_TRACK_E_ATTEMPT', 'track_e_attempt');
|
||||
define('TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING', 'track_e_attempt_recording');
|
||||
define('TABLE_STATISTIC_TRACK_E_DEFAULT', 'track_e_default');
|
||||
define('TABLE_STATISTIC_TRACK_E_UPLOADS', 'track_e_uploads');
|
||||
define('TABLE_STATISTIC_TRACK_E_HOTSPOT', 'track_e_hotspot');
|
||||
define('TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY', 'track_e_item_property');
|
||||
define('TABLE_STATISTIC_TRACK_FILTERED_TERMS', 'track_filtered_terms');
|
||||
|
||||
// Course catalog stats see #4191
|
||||
define('TABLE_STATISTIC_TRACK_COURSE_RANKING', 'track_course_ranking');
|
||||
define('TABLE_MAIN_USER_REL_COURSE_VOTE', 'user_rel_course_vote');
|
||||
|
||||
// Course tables
|
||||
define('TABLE_AGENDA', 'calendar_event');
|
||||
define('TABLE_AGENDA_REPEAT', 'calendar_event_repeat');
|
||||
define('TABLE_AGENDA_REPEAT_NOT', 'calendar_event_repeat_not');
|
||||
define('TABLE_AGENDA_ATTACHMENT', 'calendar_event_attachment');
|
||||
define('TABLE_ANNOUNCEMENT', 'announcement');
|
||||
define('TABLE_ANNOUNCEMENT_ATTACHMENT', 'announcement_attachment');
|
||||
define('TABLE_CHAT_CONNECTED', 'chat_connected');
|
||||
define('TABLE_COURSE_DESCRIPTION', 'course_description');
|
||||
define('TABLE_DOCUMENT', 'document');
|
||||
define('TABLE_ITEM_PROPERTY', 'item_property');
|
||||
define('TABLE_LINK', 'link');
|
||||
define('TABLE_LINK_CATEGORY', 'link_category');
|
||||
define('TABLE_TOOL_LIST', 'tool');
|
||||
define('TABLE_TOOL_INTRO', 'tool_intro');
|
||||
define('TABLE_SCORMDOC', 'scormdocument');
|
||||
define('TABLE_STUDENT_PUBLICATION', 'student_publication');
|
||||
define('TABLE_STUDENT_PUBLICATION_ASSIGNMENT', 'student_publication_assignment');
|
||||
define('TABLE_STUDENT_PUBLICATION_REL_DOCUMENT', 'student_publication_rel_document');
|
||||
define('TABLE_STUDENT_PUBLICATION_REL_USER', 'student_publication_rel_user');
|
||||
define('TABLE_STUDENT_PUBLICATION_ASSIGNMENT_COMMENT', 'student_publication_comment');
|
||||
define('TABLE_PLAGIARISM', 'plagiarism_compilatio_docs');
|
||||
|
||||
// Course forum tables
|
||||
define('TABLE_FORUM_CATEGORY', 'forum_category');
|
||||
define('TABLE_FORUM', 'forum_forum');
|
||||
define('TABLE_FORUM_THREAD', 'forum_thread');
|
||||
define('TABLE_FORUM_POST', 'forum_post');
|
||||
define('TABLE_FORUM_ATTACHMENT', 'forum_attachment');
|
||||
define('TABLE_FORUM_MAIL_QUEUE', 'forum_mailcue');
|
||||
define('TABLE_FORUM_THREAD_QUALIFY', 'forum_thread_qualify');
|
||||
define('TABLE_FORUM_THREAD_QUALIFY_LOG', 'forum_thread_qualify_log');
|
||||
define('TABLE_FORUM_NOTIFICATION', 'forum_notification');
|
||||
|
||||
// Course group tables
|
||||
define('TABLE_GROUP', 'group_info');
|
||||
define('TABLE_GROUP_USER', 'group_rel_user');
|
||||
define('TABLE_GROUP_TUTOR', 'group_rel_tutor');
|
||||
define('TABLE_GROUP_CATEGORY', 'group_category');
|
||||
|
||||
// Course dropbox tables
|
||||
define('TABLE_DROPBOX_CATEGORY', 'dropbox_category');
|
||||
define('TABLE_DROPBOX_FEEDBACK', 'dropbox_feedback');
|
||||
define('TABLE_DROPBOX_POST', 'dropbox_post');
|
||||
define('TABLE_DROPBOX_FILE', 'dropbox_file');
|
||||
define('TABLE_DROPBOX_PERSON', 'dropbox_person');
|
||||
|
||||
// Course quiz (or test, or exercise) tables
|
||||
define('TABLE_QUIZ_QUESTION', 'quiz_question');
|
||||
define('TABLE_QUIZ_TEST', 'quiz');
|
||||
define('TABLE_QUIZ_ORDER', 'quiz_order');
|
||||
define('TABLE_QUIZ_ANSWER', 'quiz_answer');
|
||||
define('TABLE_QUIZ_TEST_QUESTION', 'quiz_rel_question');
|
||||
define('TABLE_QUIZ_QUESTION_OPTION', 'quiz_question_option');
|
||||
define('TABLE_QUIZ_QUESTION_CATEGORY', 'quiz_question_category');
|
||||
define('TABLE_QUIZ_QUESTION_REL_CATEGORY', 'quiz_question_rel_category');
|
||||
define('TABLE_QUIZ_REL_CATEGORY', 'quiz_rel_category');
|
||||
define('TABLE_LP_MAIN', 'lp');
|
||||
define('TABLE_LP_ITEM', 'lp_item');
|
||||
define('TABLE_LP_VIEW', 'lp_view');
|
||||
define('TABLE_LP_ITEM_VIEW', 'lp_item_view');
|
||||
define('TABLE_LP_IV_INTERACTION', 'lp_iv_interaction'); // IV = Item View
|
||||
define('TABLE_LP_IV_OBJECTIVE', 'lp_iv_objective'); // IV = Item View
|
||||
define('TABLE_LP_CATEGORY', 'lp_category');
|
||||
define('TABLE_LP_REL_USERGROUP', 'lp_rel_usergroup');
|
||||
define('TABLE_LP_CATEGORY_REL_USERGROUP', 'lp_category_rel_usergroup');
|
||||
|
||||
// Smartblogs (Kevin Van Den Haute::kevin@develop-it.be)
|
||||
// Permission tables
|
||||
define('TABLE_PERMISSION_USER', 'permission_user');
|
||||
define('TABLE_PERMISSION_TASK', 'permission_task');
|
||||
define('TABLE_PERMISSION_GROUP', 'permission_group');
|
||||
// Role tables
|
||||
define('TABLE_ROLE', 'role');
|
||||
define('TABLE_ROLE_PERMISSION', 'role_permissions');
|
||||
define('TABLE_ROLE_USER', 'role_user');
|
||||
define('TABLE_ROLE_GROUP', 'role_group');
|
||||
// Blog tables
|
||||
define('TABLE_BLOGS', 'blog');
|
||||
define('TABLE_BLOGS_POSTS', 'blog_post');
|
||||
define('TABLE_BLOGS_COMMENTS', 'blog_comment');
|
||||
define('TABLE_BLOGS_REL_USER', 'blog_rel_user');
|
||||
define('TABLE_BLOGS_TASKS', 'blog_task');
|
||||
define('TABLE_BLOGS_TASKS_REL_USER', 'blog_task_rel_user');
|
||||
define('TABLE_BLOGS_RATING', 'blog_rating');
|
||||
define('TABLE_BLOGS_ATTACHMENT', 'blog_attachment');
|
||||
define('TABLE_BLOGS_TASKS_PERMISSIONS', 'permission_task');
|
||||
|
||||
// Course settings table
|
||||
define('TABLE_COURSE_SETTING', 'course_setting');
|
||||
|
||||
// Course online tables
|
||||
define('TABLE_ONLINE_LINK', 'online_link');
|
||||
define('TABLE_ONLINE_CONNECTED', 'online_connected');
|
||||
|
||||
// User database
|
||||
define('TABLE_PERSONAL_AGENDA', 'personal_agenda');
|
||||
define('TABLE_PERSONAL_AGENDA_REPEAT', 'personal_agenda_repeat');
|
||||
define('TABLE_PERSONAL_AGENDA_REPEAT_NOT', 'personal_agenda_repeat_not');
|
||||
define('TABLE_USER_COURSE_CATEGORY', 'user_course_category');
|
||||
|
||||
// Survey
|
||||
// @TODO: Are these MAIN tables or course tables?
|
||||
// @TODO: Probably these constants are obsolete.
|
||||
define('TABLE_MAIN_SURVEY', 'survey');
|
||||
define('TABLE_MAIN_SURVEYQUESTION', 'questions');
|
||||
|
||||
// Survey
|
||||
define('TABLE_SURVEY', 'survey');
|
||||
define('TABLE_SURVEY_QUESTION', 'survey_question');
|
||||
define('TABLE_SURVEY_QUESTION_OPTION', 'survey_question_option');
|
||||
define('TABLE_SURVEY_INVITATION', 'survey_invitation');
|
||||
define('TABLE_SURVEY_ANSWER', 'survey_answer');
|
||||
define('TABLE_SURVEY_QUESTION_GROUP', 'survey_group');
|
||||
define('TABLE_SURVEY_REPORT', 'survey_report');
|
||||
|
||||
// Wiki tables
|
||||
define('TABLE_WIKI', 'wiki');
|
||||
define('TABLE_WIKI_CONF', 'wiki_conf');
|
||||
define('TABLE_WIKI_DISCUSS', 'wiki_discuss');
|
||||
define('TABLE_WIKI_MAILCUE', 'wiki_mailcue');
|
||||
|
||||
// Glossary
|
||||
define('TABLE_GLOSSARY', 'glossary');
|
||||
|
||||
// Notebook
|
||||
define('TABLE_NOTEBOOK', 'notebook');
|
||||
|
||||
// Message
|
||||
define('TABLE_MESSAGE', 'message');
|
||||
define('TABLE_MESSAGE_ATTACHMENT', 'message_attachment');
|
||||
|
||||
// Attendance Sheet
|
||||
define('TABLE_ATTENDANCE', 'attendance');
|
||||
define('TABLE_ATTENDANCE_CALENDAR', 'attendance_calendar');
|
||||
define('TABLE_ATTENDANCE_CALENDAR_REL_GROUP', 'attendance_calendar_rel_group');
|
||||
define('TABLE_ATTENDANCE_SHEET_LOG', 'attendance_sheet_log');
|
||||
define('TABLE_ATTENDANCE_SHEET', 'attendance_sheet');
|
||||
define('TABLE_ATTENDANCE_RESULT', 'attendance_result');
|
||||
|
||||
// Thematic
|
||||
define('TABLE_THEMATIC', 'thematic');
|
||||
define('TABLE_THEMATIC_PLAN', 'thematic_plan');
|
||||
define('TABLE_THEMATIC_ADVANCE', 'thematic_advance');
|
||||
|
||||
// Careers, promotions, Usergroups
|
||||
define('TABLE_CAREER', 'career');
|
||||
define('TABLE_PROMOTION', 'promotion');
|
||||
|
||||
define('TABLE_USERGROUP', 'usergroup');
|
||||
define('TABLE_USERGROUP_REL_USER', 'usergroup_rel_user');
|
||||
define('TABLE_USERGROUP_REL_COURSE', 'usergroup_rel_course');
|
||||
define('TABLE_USERGROUP_REL_SESSION', 'usergroup_rel_session');
|
||||
define('TABLE_USERGROUP_REL_USERGROUP', 'usergroup_rel_usergroup');
|
||||
|
||||
// Mail notifications
|
||||
define('TABLE_NOTIFICATION', 'notification');
|
||||
|
||||
//Storage api tables
|
||||
define('TABLE_TRACK_STORED_VALUES', 'track_stored_values');
|
||||
define('TABLE_TRACK_STORED_VALUES_STACK', 'track_stored_values_stack');
|
||||
|
||||
//Event tables
|
||||
define('TABLE_EVENT_EMAIL_TEMPLATE', 'event_email_template');
|
||||
define('TABLE_EVENT_TYPE_REL_USER', 'user_rel_event_type');
|
||||
define('TABLE_EVENT_SENT', 'event_sent');
|
||||
|
||||
define('TABLE_MAIN_SKILL', 'skill');
|
||||
define('TABLE_MAIN_SKILL_REL_SKILL', 'skill_rel_skill');
|
||||
define('TABLE_MAIN_SKILL_REL_GRADEBOOK', 'skill_rel_gradebook');
|
||||
define('TABLE_MAIN_SKILL_REL_USER', 'skill_rel_user');
|
||||
|
||||
define('TABLE_MAIN_SKILL_PROFILE', 'skill_profile');
|
||||
define('TABLE_MAIN_SKILL_REL_PROFILE', 'skill_rel_profile');
|
||||
|
||||
define('TABLE_MAIN_CHAT', 'chat');
|
||||
define('TABLE_TIMELINE', 'timeline');
|
||||
define('TABLE_MAIN_CHAT_VIDEO', 'chat_video');
|
||||
|
||||
// Gradebook model
|
||||
define('TABLE_GRADE_MODEL', 'grade_model');
|
||||
define('TABLE_GRADE_MODEL_COMPONENTS', 'grade_components');
|
||||
|
||||
// Hook tables
|
||||
define('TABLE_HOOK_OBSERVER', 'hook_observer');
|
||||
define('TABLE_HOOK_CALL', 'hook_call');
|
||||
define('TABLE_HOOK_EVENT', 'hook_event');
|
||||
|
||||
define('TABLE_TICKET_ASSIGNED_LOG', 'ticket_assigned_log');
|
||||
define('TABLE_TICKET_CATEGORY', 'ticket_category');
|
||||
define('TABLE_TICKET_MESSAGE', 'ticket_message');
|
||||
define('TABLE_TICKET_PRIORITY', 'ticket_priority');
|
||||
define('TABLE_TICKET_PROJECT', 'ticket_project');
|
||||
define('TABLE_TICKET_STATUS', 'ticket_status');
|
||||
define('TABLE_TICKET_TICKET', 'ticket_ticket');
|
||||
define('TABLE_TICKET_CATEGORY_REL_USER', 'ticket_category_rel_user');
|
||||
define('TABLE_TICKET_MESSAGE_ATTACHMENTS', 'ticket_message_attachments');
|
||||
|
||||
define('TABLE_BRANCH', 'branch_sync');
|
||||
define('TABLE_BRANCH_TRANSACTION', 'branch_transaction');
|
||||
define('TABLE_BRANCH_TRANSACTION_STATUS', 'branch_transaction_status');
|
||||
|
||||
// main/extra @todo after code is finished remove constants not used
|
||||
define('TABLE_CAL_DATE', 'cal_dates');
|
||||
define('TABLE_CAL_HORAIRE', 'cal_horaire');
|
||||
define('TABLE_CAL_TEMP', 'cal_temp');
|
||||
define('TABLE_STATISTIC_TRACK_E_EXERCICES_TEMP', 'track_e_exercices_temp');
|
||||
|
||||
define('TABLE_USER_INFO_DEF', 'userinfo_def');
|
||||
define('TABLE_USER_INFO_CONTENT', 'userinfo_content');
|
||||
|
||||
define('TABLE_MAIN_USER_CAREER', 'user_career');
|
||||
851
main/inc/lib/database.lib.php
Normal file
851
main/inc/lib/database.lib.php
Normal file
@@ -0,0 +1,851 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Proxy\AbstractProxyFactory;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver\Statement;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
|
||||
/**
|
||||
* Class Database.
|
||||
*/
|
||||
class Database
|
||||
{
|
||||
public static $utcDateTimeClass;
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private static $em;
|
||||
private static $connection;
|
||||
|
||||
/**
|
||||
* Set the DB manager instance.
|
||||
*
|
||||
* @param EntityManager $em
|
||||
*/
|
||||
public function setManager($em)
|
||||
{
|
||||
self::$em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB connection instance.
|
||||
*/
|
||||
public function setConnection(Connection $connection)
|
||||
{
|
||||
self::$connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DB connection instance.
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return self::$connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DB manager instance.
|
||||
*
|
||||
* @return EntityManager
|
||||
*/
|
||||
public static function getManager()
|
||||
{
|
||||
return self::$em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main database.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_main_database()
|
||||
{
|
||||
return self::getManager()->getConnection()->getDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get main table.
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_main_table($table)
|
||||
{
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get course table.
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_course_table($table)
|
||||
{
|
||||
return DB_COURSE_PREFIX.$table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of rows in a table.
|
||||
*
|
||||
* @param string $table The table of which the rows should be counted
|
||||
*
|
||||
* @return int the number of rows in the given table
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public static function count_rows($table)
|
||||
{
|
||||
$obj = self::fetch_object(self::query("SELECT COUNT(*) AS n FROM $table"));
|
||||
|
||||
return $obj->n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of affected rows in the last database operation.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function affected_rows($result)
|
||||
{
|
||||
return $result->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getUTCDateTimeTypeClass()
|
||||
{
|
||||
return isset(self::$utcDateTimeClass) ? self::$utcDateTimeClass : 'Application\DoctrineExtensions\DBAL\Types\UTCDateTimeType';
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the database sets the entity manager.
|
||||
*
|
||||
* @param array $params
|
||||
* @param string $sysPath
|
||||
* @param string $entityRootPath
|
||||
* @param bool $returnConnection
|
||||
* @param bool $returnManager
|
||||
*
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public function connect(
|
||||
$params = [],
|
||||
$sysPath = '',
|
||||
$entityRootPath = '',
|
||||
$returnConnection = false,
|
||||
$returnManager = false
|
||||
) {
|
||||
$config = self::getDoctrineConfig($entityRootPath);
|
||||
|
||||
$params['charset'] = 'utf8';
|
||||
$entityManager = EntityManager::create($params, $config);
|
||||
$sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
|
||||
|
||||
// Registering Constraints
|
||||
/*AnnotationRegistry::registerAutoloadNamespace(
|
||||
'Symfony\Component',
|
||||
$sysPath."vendor/"
|
||||
);*/
|
||||
|
||||
AnnotationRegistry::registerLoader(
|
||||
function ($class) use ($sysPath) {
|
||||
$file = str_replace("\\", DIRECTORY_SEPARATOR, $class).".php";
|
||||
$file = str_replace('Symfony/Component/Validator', '', $file);
|
||||
$file = str_replace('Symfony\Component\Validator', '', $file);
|
||||
$fileToInclude = $sysPath.'vendor/symfony/validator/'.$file;
|
||||
|
||||
if (file_exists($fileToInclude)) {
|
||||
// file exists makes sure that the loader fails silently
|
||||
require_once $fileToInclude;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$fileToInclude = $sysPath.'vendor/symfony/validator/Constraints/'.$file;
|
||||
if (file_exists($fileToInclude)) {
|
||||
// file exists makes sure that the loader fails silently
|
||||
require_once $fileToInclude;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
AnnotationRegistry::registerFile(
|
||||
$sysPath."vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php"
|
||||
);
|
||||
|
||||
// Registering gedmo extensions
|
||||
AnnotationRegistry::registerAutoloadNamespace(
|
||||
'Gedmo\Mapping\Annotation',
|
||||
$sysPath."vendor/gedmo/doctrine-extensions/lib"
|
||||
);
|
||||
|
||||
Type::overrideType(
|
||||
Type::DATETIME,
|
||||
self::getUTCDateTimeTypeClass()
|
||||
);
|
||||
|
||||
$listener = new \Gedmo\Timestampable\TimestampableListener();
|
||||
$entityManager->getEventManager()->addEventSubscriber($listener);
|
||||
|
||||
$listener = new \Gedmo\Tree\TreeListener();
|
||||
$entityManager->getEventManager()->addEventSubscriber($listener);
|
||||
|
||||
$listener = new \Gedmo\Sortable\SortableListener();
|
||||
$entityManager->getEventManager()->addEventSubscriber($listener);
|
||||
$connection = $entityManager->getConnection();
|
||||
$connection->executeQuery('SET sql_mode = "";');
|
||||
$connection->executeQuery('SET SESSION sql_mode = ""');
|
||||
|
||||
if ($returnConnection) {
|
||||
return $connection;
|
||||
}
|
||||
|
||||
if ($returnManager) {
|
||||
return $entityManager;
|
||||
}
|
||||
|
||||
$this->setConnection($connection);
|
||||
$this->setManager($entityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape MySQL wildcards _ and % in LIKE search.
|
||||
*
|
||||
* @param string $text The string to escape
|
||||
*
|
||||
* @return string The escaped string
|
||||
*/
|
||||
public static function escape_sql_wildcards($text)
|
||||
{
|
||||
$text = api_preg_replace("/_/", "\_", $text);
|
||||
$text = api_preg_replace("/%/", "\%", $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string to insert into the database as text.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function escape_string($string)
|
||||
{
|
||||
$string = self::getManager()->getConnection()->quote($string);
|
||||
// The quote method from PDO also adds quotes around the string, which
|
||||
// is not how the legacy mysql_real_escape_string() was used in
|
||||
// Chamilo, so we need to remove the quotes around. Using trim will
|
||||
// remove more than one quote if they are sequenced, generating
|
||||
// broken queries and SQL injection risks
|
||||
return substr($string, 1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array from a SQL result (as returned by Database::query).
|
||||
*
|
||||
* @param string $option Optional: "ASSOC","NUM" or "BOTH"
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public static function fetch_array($result, $option = 'BOTH')
|
||||
{
|
||||
if ($result === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $result->fetch(self::customOptionToDoctrineOption($option));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an associative array from a SQL result (as returned by Database::query).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function fetch_assoc($result)
|
||||
{
|
||||
return $result->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next row of the result of the SQL query
|
||||
* (as returned by Database::query) in an object form.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function fetch_object($result)
|
||||
{
|
||||
return $result->fetch(PDO::FETCH_OBJ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array from a SQL result (as returned by Database::query)
|
||||
* help achieving database independence.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function fetch_row($result)
|
||||
{
|
||||
if ($result === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $result->fetch(PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees all the memory associated with the provided result identifier.
|
||||
*
|
||||
* @return bool|null Returns TRUE on success or FALSE on failure.
|
||||
* Notes: Use this method if you are concerned about how much memory is being used for queries that return large result sets.
|
||||
* Anyway, all associated result memory is automatically freed at the end of the script's execution.
|
||||
*/
|
||||
public static function free_result($result)
|
||||
{
|
||||
$result->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the last item inserted into the database.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function insert_id()
|
||||
{
|
||||
return self::getManager()->getConnection()->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for rowCount().
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function num_rows($result)
|
||||
{
|
||||
if ($result === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $result->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as the relative *_result() function of most DB drivers and fetches a
|
||||
* specific line and a field.
|
||||
*
|
||||
* @param int $row
|
||||
* @param string $field
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function result($resource, $row, $field = '')
|
||||
{
|
||||
if ($resource->rowCount() > 0) {
|
||||
$result = $resource->fetchAll(PDO::FETCH_BOTH);
|
||||
|
||||
return $result[$row][$field];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for executeQuery().
|
||||
*
|
||||
* @param string $query
|
||||
*
|
||||
* @return Statement
|
||||
*/
|
||||
public static function query($query)
|
||||
{
|
||||
$connection = self::getManager()->getConnection();
|
||||
$result = null;
|
||||
try {
|
||||
$result = $connection->executeQuery($query);
|
||||
} catch (Exception $e) {
|
||||
self::handleError($e);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with exceptions from the database extension.
|
||||
*
|
||||
* @param Exception $e
|
||||
*/
|
||||
public static function handleError($e)
|
||||
{
|
||||
$debug = api_get_setting('server_type') == 'test';
|
||||
if ($debug) {
|
||||
// We use Symfony exception handler for better error information
|
||||
$handler = new ExceptionHandler();
|
||||
$handler->handle($e);
|
||||
exit;
|
||||
} else {
|
||||
$msg = $e->getMessage();
|
||||
if (preg_match('/Serialization failure:/', $msg)) {
|
||||
//do nothing except from logging
|
||||
error_log($msg.' - Reported but otherwise ignored');
|
||||
} else {
|
||||
error_log($msg);
|
||||
api_not_allowed(false, get_lang('GeneralError'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an SQL option from Chamilo to PDO syntax.
|
||||
*
|
||||
* @param string $option
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function customOptionToDoctrineOption($option)
|
||||
{
|
||||
switch ($option) {
|
||||
case 'ASSOC':
|
||||
return PDO::FETCH_ASSOC;
|
||||
break;
|
||||
case 'NUM':
|
||||
return PDO::FETCH_NUM;
|
||||
break;
|
||||
case 'BOTH':
|
||||
default:
|
||||
return PDO::FETCH_BOTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a query result into an array.
|
||||
*
|
||||
* @author Olivier Brouckaert
|
||||
*
|
||||
* @param Statement $result - the return value of the query
|
||||
* @param string $option BOTH, ASSOC, or NUM
|
||||
*
|
||||
* @return array - the value returned by the query
|
||||
*/
|
||||
public static function store_result($result, $option = 'BOTH')
|
||||
{
|
||||
return $result->fetchAll(self::customOptionToDoctrineOption($option));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an insert query.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param array $attributes
|
||||
* @param bool $show_query
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public static function insert($table_name, $attributes, $show_query = false)
|
||||
{
|
||||
if (empty($attributes) || empty($table_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$params = array_keys($attributes);
|
||||
|
||||
if (!empty($params)) {
|
||||
$sql = 'INSERT INTO '.$table_name.' ('.implode(',', $params).')
|
||||
VALUES (:'.implode(', :', $params).')';
|
||||
|
||||
$statement = self::getManager()->getConnection()->prepare($sql);
|
||||
$result = $statement->execute($attributes);
|
||||
|
||||
if ($show_query) {
|
||||
var_dump($sql);
|
||||
error_log($sql);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
return (int) self::getManager()->getConnection()->lastInsertId();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an update query.
|
||||
*
|
||||
* @param string $tableName use Database::get_main_table
|
||||
* @param array $attributes Values to updates
|
||||
* Example: $params['name'] = 'Julio'; $params['lastname'] = 'Montoya';
|
||||
* @param array $whereConditions where conditions i.e array('id = ?' =>'4')
|
||||
* @param bool $showQuery
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
public static function update(
|
||||
$tableName,
|
||||
$attributes,
|
||||
$whereConditions = [],
|
||||
$showQuery = false
|
||||
) {
|
||||
if (!empty($tableName) && !empty($attributes)) {
|
||||
$updateSql = '';
|
||||
$count = 1;
|
||||
|
||||
foreach ($attributes as $key => $value) {
|
||||
if ($showQuery) {
|
||||
echo $key.': '.$value.PHP_EOL;
|
||||
}
|
||||
$updateSql .= "$key = :$key ";
|
||||
if ($count < count($attributes)) {
|
||||
$updateSql .= ', ';
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
|
||||
if (!empty($updateSql)) {
|
||||
//Parsing and cleaning the where conditions
|
||||
$whereReturn = self::parse_where_conditions($whereConditions);
|
||||
|
||||
$sql = "UPDATE $tableName SET $updateSql $whereReturn ";
|
||||
|
||||
$statement = self::getManager()->getConnection()->prepare($sql);
|
||||
|
||||
$result = $statement->execute($attributes);
|
||||
|
||||
if ($showQuery) {
|
||||
var_dump($sql);
|
||||
var_dump($attributes);
|
||||
var_dump($whereConditions);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
return $statement->rowCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Experimental useful database finder.
|
||||
*
|
||||
* @todo lot of stuff to do here
|
||||
* @todo known issues, it doesn't work when using LIKE conditions
|
||||
*
|
||||
* @example array('where'=> array('course_code LIKE "?%"'))
|
||||
* @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins'))
|
||||
* @example array('where'=> array('name = "Julio" AND lastname = "montoya"'))
|
||||
*
|
||||
* @param mixed $columns array (or string if only one column)
|
||||
* @param string $table_name
|
||||
* @param array $conditions
|
||||
* @param string $type_result all|first|count
|
||||
* @param string $option
|
||||
* @param bool $debug
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function select(
|
||||
$columns,
|
||||
$table_name,
|
||||
$conditions = [],
|
||||
$type_result = 'all',
|
||||
$option = 'ASSOC',
|
||||
$debug = false
|
||||
) {
|
||||
if ($type_result === 'count') {
|
||||
$conditions['LIMIT'] = null;
|
||||
$conditions['limit'] = null;
|
||||
}
|
||||
|
||||
$conditions = self::parse_conditions($conditions);
|
||||
|
||||
//@todo we could do a describe here to check the columns ...
|
||||
if (is_array($columns)) {
|
||||
$clean_columns = implode(',', $columns);
|
||||
} else {
|
||||
if ($columns === '*') {
|
||||
$clean_columns = '*';
|
||||
} else {
|
||||
$clean_columns = (string) $columns;
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_result === 'count') {
|
||||
$clean_columns = ' count(*) count ';
|
||||
}
|
||||
|
||||
$sql = "SELECT $clean_columns FROM $table_name $conditions";
|
||||
if ($debug) {
|
||||
var_dump($sql);
|
||||
}
|
||||
$result = self::query($sql);
|
||||
|
||||
if ($type_result === 'count') {
|
||||
$row = self::fetch_array($result, $option);
|
||||
if ($row) {
|
||||
return (int) $row['count'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$array = [];
|
||||
if ($type_result === 'all') {
|
||||
while ($row = self::fetch_array($result, $option)) {
|
||||
if (isset($row['iid'])) {
|
||||
$array[$row['iid']] = $row;
|
||||
} elseif (isset($row['id'])) {
|
||||
$array[$row['id']] = $row;
|
||||
} else {
|
||||
$array[] = $row;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$array = self::fetch_array($result, $option);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses WHERE/ORDER conditions i.e array('where'=>array('id = ?' =>'4'), 'order'=>'id DESC').
|
||||
*
|
||||
* @todo known issues, it doesn't work when using
|
||||
* LIKE conditions example: array('where'=>array('course_code LIKE "?%"'))
|
||||
*
|
||||
* @param array $conditions
|
||||
*
|
||||
* @return string Partial SQL string to add to longer query
|
||||
*/
|
||||
public static function parse_conditions($conditions)
|
||||
{
|
||||
if (empty($conditions)) {
|
||||
return '';
|
||||
}
|
||||
$return_value = $where_return = '';
|
||||
foreach ($conditions as $type_condition => $condition_data) {
|
||||
if ($condition_data == false) {
|
||||
continue;
|
||||
}
|
||||
$type_condition = strtolower($type_condition);
|
||||
switch ($type_condition) {
|
||||
case 'where':
|
||||
foreach ($condition_data as $condition => $value_array) {
|
||||
if (is_array($value_array)) {
|
||||
$clean_values = [];
|
||||
foreach ($value_array as $item) {
|
||||
$item = self::escape_string($item);
|
||||
$clean_values[] = $item;
|
||||
}
|
||||
} else {
|
||||
$value_array = self::escape_string($value_array);
|
||||
$clean_values = [$value_array];
|
||||
}
|
||||
|
||||
if (!empty($condition) && $clean_values != '') {
|
||||
$condition = str_replace('%', "'@percentage@'", $condition); //replace "%"
|
||||
$condition = str_replace("'?'", "%s", $condition);
|
||||
$condition = str_replace("?", "%s", $condition);
|
||||
|
||||
$condition = str_replace("@%s@", "@-@", $condition);
|
||||
$condition = str_replace("%s", "'%s'", $condition);
|
||||
$condition = str_replace("@-@", "@%s@", $condition);
|
||||
|
||||
// Treat conditions as string
|
||||
$condition = vsprintf($condition, $clean_values);
|
||||
$condition = str_replace('@percentage@', '%', $condition); //replace "%"
|
||||
$where_return .= $condition;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($where_return)) {
|
||||
$return_value = " WHERE $where_return";
|
||||
}
|
||||
break;
|
||||
case 'order':
|
||||
$order_array = $condition_data;
|
||||
|
||||
if (!empty($order_array)) {
|
||||
// 'order' => 'id desc, name desc'
|
||||
$order_array = self::escape_string($order_array);
|
||||
$new_order_array = explode(',', $order_array);
|
||||
$temp_value = [];
|
||||
|
||||
foreach ($new_order_array as $element) {
|
||||
$element = explode(' ', $element);
|
||||
$element = array_filter($element);
|
||||
$element = array_values($element);
|
||||
|
||||
if (!empty($element[1])) {
|
||||
$element[1] = strtolower($element[1]);
|
||||
$order = 'DESC';
|
||||
if (in_array($element[1], ['desc', 'asc'])) {
|
||||
$order = $element[1];
|
||||
}
|
||||
$temp_value[] = ' `'.$element[0].'` '.$order.' ';
|
||||
} else {
|
||||
//by default DESC
|
||||
$temp_value[] = ' `'.$element[0].'` DESC ';
|
||||
}
|
||||
}
|
||||
if (!empty($temp_value)) {
|
||||
$return_value .= ' ORDER BY '.implode(', ', $temp_value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'limit':
|
||||
$limit_array = explode(',', $condition_data);
|
||||
if (!empty($limit_array)) {
|
||||
if (count($limit_array) > 1) {
|
||||
$return_value .= ' LIMIT '.intval($limit_array[0]).' , '.intval($limit_array[1]);
|
||||
} else {
|
||||
$return_value .= ' LIMIT '.intval($limit_array[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conditions
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function parse_where_conditions($conditions)
|
||||
{
|
||||
return self::parse_conditions(['where' => $conditions]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a delete query.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param array $where_conditions
|
||||
* @param bool $show_query
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function delete($table_name, $where_conditions, $show_query = false)
|
||||
{
|
||||
$where_return = self::parse_where_conditions($where_conditions);
|
||||
$sql = "DELETE FROM $table_name $where_return ";
|
||||
if ($show_query) {
|
||||
echo $sql;
|
||||
echo '<br />';
|
||||
}
|
||||
$result = self::query($sql);
|
||||
$affected_rows = self::affected_rows($result);
|
||||
//@todo should return affected_rows for
|
||||
return $affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Doctrine configuration.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return \Doctrine\ORM\Configuration
|
||||
*/
|
||||
public static function getDoctrineConfig($path)
|
||||
{
|
||||
$isDevMode = true; // Forces doctrine to use ArrayCache instead of apc/xcache/memcache/redis
|
||||
$isSimpleMode = false; // related to annotations @Entity
|
||||
$cache = null;
|
||||
$path = !empty($path) ? $path : api_get_path(SYS_PATH);
|
||||
|
||||
$paths = [
|
||||
//$path.'src/Chamilo/ClassificationBundle/Entity',
|
||||
//$path.'src/Chamilo/MediaBundle/Entity',
|
||||
//$path.'src/Chamilo/PageBundle/Entity',
|
||||
$path.'src/Chamilo/CoreBundle/Entity',
|
||||
$path.'src/Chamilo/UserBundle/Entity',
|
||||
$path.'src/Chamilo/CourseBundle/Entity',
|
||||
$path.'src/Chamilo/TicketBundle/Entity',
|
||||
$path.'src/Chamilo/SkillBundle/Entity',
|
||||
$path.'src/Chamilo/PluginBundle/Entity',
|
||||
//$path.'vendor/sonata-project/user-bundle/Entity',
|
||||
//$path.'vendor/sonata-project/user-bundle/Model',
|
||||
//$path.'vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Entity',
|
||||
];
|
||||
|
||||
$proxyDir = $path.'app/cache/';
|
||||
|
||||
$config = Setup::createAnnotationMetadataConfiguration(
|
||||
$paths,
|
||||
$isDevMode,
|
||||
$proxyDir,
|
||||
$cache,
|
||||
$isSimpleMode
|
||||
);
|
||||
|
||||
$config->setAutoGenerateProxyClasses(AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS);
|
||||
|
||||
$config->setEntityNamespaces(
|
||||
[
|
||||
'ChamiloUserBundle' => 'Chamilo\UserBundle\Entity',
|
||||
'ChamiloCoreBundle' => 'Chamilo\CoreBundle\Entity',
|
||||
'ChamiloCourseBundle' => 'Chamilo\CourseBundle\Entity',
|
||||
'ChamiloSkillBundle' => 'Chamilo\SkillBundle\Entity',
|
||||
'ChamiloTicketBundle' => 'Chamilo\TicketBundle\Entity',
|
||||
'ChamiloPluginBundle' => 'Chamilo\PluginBundle\Entity',
|
||||
]
|
||||
);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given table exists.
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function tableExists($table)
|
||||
{
|
||||
return self::getManager()->getConnection()->getSchemaManager()->tablesExist($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the columns of a given table.
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return \Doctrine\DBAL\Schema\Column[]
|
||||
*/
|
||||
public static function listTableColumns($table)
|
||||
{
|
||||
return self::getManager()->getConnection()->getSchemaManager()->listTableColumns($table);
|
||||
}
|
||||
|
||||
public static function escapeField($field)
|
||||
{
|
||||
return self::escape_string(preg_replace("/[^a-zA-Z0-9_.]/", '', $field));
|
||||
}
|
||||
|
||||
public static function clearDatabaseName(string $dbName): string
|
||||
{
|
||||
return preg_replace('/[^a-zA-Z0-9_\-]/', '', $dbName);
|
||||
}
|
||||
}
|
||||
4
main/inc/lib/database.mysqli.lib.php
Normal file
4
main/inc/lib/database.mysqli.lib.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
// This file is needed to avoid the double Database class definition in 1.9.x
|
||||
// Don't remove.
|
||||
1019
main/inc/lib/diagnoser.lib.php
Normal file
1019
main/inc/lib/diagnoser.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
3122
main/inc/lib/display.lib.php
Normal file
3122
main/inc/lib/display.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
7656
main/inc/lib/document.lib.php
Normal file
7656
main/inc/lib/document.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
42
main/inc/lib/elfinder/connectorAction.php
Normal file
42
main/inc/lib/elfinder/connectorAction.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Component\Editor\Connector;
|
||||
use Chamilo\CoreBundle\Component\Editor\Finder;
|
||||
|
||||
require_once __DIR__.'/../../global.inc.php';
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
/** @var Connector $connector */
|
||||
$connector = new Connector();
|
||||
|
||||
// Check driver list in configuration
|
||||
$driverList = api_get_configuration_value('editor_driver_list');
|
||||
if (empty($driverList)) {
|
||||
$driverList = [
|
||||
'PersonalDriver',
|
||||
'CourseDriver',
|
||||
//'CourseUserDriver',
|
||||
//'HomeDriver'
|
||||
];
|
||||
$block = api_get_configuration_value('block_editor_file_manager_for_students');
|
||||
$newDriverList = [];
|
||||
if (($block) && !api_is_allowed_to_edit()) {
|
||||
foreach ($driverList as $driver) {
|
||||
if ($driver === 'CourseDriver') {
|
||||
continue;
|
||||
}
|
||||
$newDriverList[] = $driver;
|
||||
}
|
||||
$driverList = $newDriverList;
|
||||
}
|
||||
}
|
||||
|
||||
$connector->setDriverList($driverList);
|
||||
$operations = $connector->getOperations();
|
||||
|
||||
// Run elFinder
|
||||
$finder = new Finder($operations);
|
||||
$elFinderConnector = new \elFinderConnector($finder);
|
||||
$elFinderConnector->run();
|
||||
25
main/inc/lib/elfinder/filemanager.php
Normal file
25
main/inc/lib/elfinder/filemanager.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
require_once __DIR__.'/../../global.inc.php';
|
||||
|
||||
Chat::setDisableChat();
|
||||
$template = new Template();
|
||||
$template->assign('course_condition', api_get_cidreq());
|
||||
|
||||
$language = 'en';
|
||||
$platformLanguage = api_get_interface_language();
|
||||
$iso = api_get_language_isocode($platformLanguage);
|
||||
$filePart = "vendor/studio-42/elfinder/js/i18n/elfinder.$iso.js";
|
||||
$file = api_get_path(SYS_PATH).$filePart;
|
||||
$includeFile = '';
|
||||
if (file_exists($file)) {
|
||||
$includeFile = '<script type="text/javascript" src="'.api_get_path(WEB_PATH).$filePart.'"></script>';
|
||||
$language = $iso;
|
||||
}
|
||||
$questionId = isset($_REQUEST['question_id']) ? (int) $_REQUEST['question_id'] : 0;
|
||||
|
||||
$template->assign('question_id', $questionId);
|
||||
$template->assign('elfinder_lang', $language);
|
||||
$template->assign('elfinder_translation_file', $includeFile);
|
||||
$template->display('default/javascript/editor/ckeditor/elfinder.tpl');
|
||||
16
main/inc/lib/elfinder/templates.php
Normal file
16
main/inc/lib/elfinder/templates.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Component\Editor\CkEditor\CkEditor;
|
||||
|
||||
require_once __DIR__.'/../../global.inc.php';
|
||||
|
||||
$template = new Template();
|
||||
|
||||
$editor = new CkEditor();
|
||||
|
||||
$templates = $editor->simpleFormatTemplates();
|
||||
|
||||
$template->assign('templates', $templates);
|
||||
header('Content-type: application/x-javascript');
|
||||
$template->display('default/javascript/editor/ckeditor/templates.tpl');
|
||||
144
main/inc/lib/event_email_template.class.php
Normal file
144
main/inc/lib/event_email_template.class.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Class EventEmailTemplate
|
||||
*/
|
||||
class EventEmailTemplate extends Model
|
||||
{
|
||||
public $table;
|
||||
public $columns = [
|
||||
'id',
|
||||
'message',
|
||||
'subject',
|
||||
'event_type_name',
|
||||
'activated',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->table = Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $where_conditions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all($where_conditions = [])
|
||||
{
|
||||
return Database::select(
|
||||
'*',
|
||||
$this->table,
|
||||
['where' => $where_conditions, 'order' => 'name ASC']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the title + grid.
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
// action links
|
||||
$content = Display::actions(
|
||||
[
|
||||
[
|
||||
'url' => 'event_type.php',
|
||||
'content' => Display::return_icon(
|
||||
'new_document.png',
|
||||
get_lang('Add'),
|
||||
[],
|
||||
ICON_SIZE_MEDIUM
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
$content .= Display::grid_html('event_email_template');
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_status_list()
|
||||
{
|
||||
return [
|
||||
EVENT_EMAIL_TEMPLATE_ACTIVE => get_lang('Enabled'),
|
||||
EVENT_EMAIL_TEMPLATE_INACTIVE => get_lang('Disabled'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Form validator Obj.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $action add, edit
|
||||
*
|
||||
* @return FormValidator
|
||||
*/
|
||||
public function return_form($url, $action)
|
||||
{
|
||||
$form = new FormValidator('career', 'post', $url);
|
||||
// Setting the form elements
|
||||
$header = get_lang('Add');
|
||||
if ($action == 'edit') {
|
||||
$header = get_lang('Modify');
|
||||
}
|
||||
|
||||
$form->addElement('header', $header);
|
||||
$id = isset($_GET['id']) ? intval($_GET['id']) : '';
|
||||
$form->addElement('hidden', 'id', $id);
|
||||
$form->addElement('text', 'name', get_lang('Name'), ['size' => '70']);
|
||||
$form->addHtmlEditor(
|
||||
'description',
|
||||
get_lang('Description'),
|
||||
false,
|
||||
false,
|
||||
[
|
||||
'ToolbarSet' => 'careers',
|
||||
'Width' => '100%',
|
||||
'Height' => '250',
|
||||
]
|
||||
);
|
||||
$status_list = $this->get_status_list();
|
||||
$form->addElement('select', 'status', get_lang('Status'), $status_list);
|
||||
if ($action == 'edit') {
|
||||
$form->addElement('text', 'created_at', get_lang('CreatedAt'));
|
||||
$form->freeze('created_at');
|
||||
}
|
||||
|
||||
if ($action == 'edit') {
|
||||
$form->addButtonSave(get_lang('Modify'), 'submit');
|
||||
} else {
|
||||
$form->addButtonCreate(get_lang('Add'), 'submit');
|
||||
}
|
||||
|
||||
// Setting the defaults
|
||||
$defaults = $this->get($id);
|
||||
|
||||
if (!empty($defaults['created_at'])) {
|
||||
$defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
|
||||
}
|
||||
if (!empty($defaults['updated_at'])) {
|
||||
$defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
|
||||
}
|
||||
$form->setDefaults($defaults);
|
||||
|
||||
// Setting the rules
|
||||
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function get_count()
|
||||
{
|
||||
$row = Database::select('count(*) as count', $this->table, [], 'first');
|
||||
|
||||
return $row['count'];
|
||||
}
|
||||
}
|
||||
2888
main/inc/lib/events.lib.php
Normal file
2888
main/inc/lib/events.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
55
main/inc/lib/events_dispatcher.class.php
Normal file
55
main/inc/lib/events_dispatcher.class.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class EventsDispatcher
|
||||
* Entry point for every event in the application.
|
||||
*
|
||||
* @deprecated to be removed in 2.x
|
||||
* Fires the functions linked to the events according to the event's conf.
|
||||
* Every function got its own filter, it's fired inside the functiones fired
|
||||
* by this class. The filter config is next to the event config, in conf/events.conf.php
|
||||
*/
|
||||
class EventsDispatcher
|
||||
{
|
||||
/**
|
||||
* @param string $event_name
|
||||
* @param array $event_data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function events($event_name, $event_data = [])
|
||||
{
|
||||
global $event_config;
|
||||
// get the config for the event passed in parameter ($event_name)
|
||||
// and execute every actions with the values
|
||||
|
||||
foreach ($event_config[$event_name]["actions"] as $func) {
|
||||
$execute = true;
|
||||
// if the function doesn't exist, we log
|
||||
if (!function_exists($func)) {
|
||||
error_log("EventsDispatcher warning : ".$func." does not exist.");
|
||||
$execute = false;
|
||||
}
|
||||
|
||||
// check if the event's got a filter
|
||||
if (function_exists($event_name."_".$func."_filter_func")) {
|
||||
$filter = $event_name."_".$func."_filter_func";
|
||||
// if it does, we execute the filter (which changes the data
|
||||
// in-place and returns true on success or false on error)
|
||||
$execute = $filter($event_data);
|
||||
} else {
|
||||
// if there's no filter
|
||||
error_log("EventsDispatcher warning : ".$event_name."_".$func."_filter_func does not exist.");
|
||||
}
|
||||
|
||||
if (!$execute) {
|
||||
// if the filter says we cannot send the mail, we get out of here
|
||||
return false;
|
||||
}
|
||||
// finally, if the filter says yes (or the filter doesn't exist),
|
||||
// we execute the in-between function that will call the needed
|
||||
// function
|
||||
$func($event_name, $event_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
285
main/inc/lib/events_email.class.php
Normal file
285
main/inc/lib/events_email.class.php
Normal file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class EventsMail.
|
||||
*
|
||||
* @deprecated to be removed in 2.x
|
||||
* manages the e-mail sending action when a event requires it
|
||||
*/
|
||||
class EventsMail
|
||||
{
|
||||
/**
|
||||
* Sends email according to an event.
|
||||
*
|
||||
* @param string $event_name the name of the event that was triggered
|
||||
* @param array $event_data what to put in the mail
|
||||
*
|
||||
* Possible key :
|
||||
* - $event_data["about_user"] (= $user_id)
|
||||
* - $event_data["prior_lang"]
|
||||
*
|
||||
* Warning :
|
||||
* - $event_data["send_to"] MUST BE an array
|
||||
*/
|
||||
public static function send_mail($event_name, $event_data)
|
||||
{
|
||||
/**
|
||||
* Global explanation :
|
||||
* 1. we get information about the user that fired the event (in $event_data["about_user"])
|
||||
* 2. we send mail to people that are in the $event_data["send_to"]
|
||||
* 2b. if a language was specified, we use that one to send the mail,
|
||||
* else we get the user's language, if there isn't any, we get the english one
|
||||
* 3. we do the same with the people associated to the event through the admin panel.
|
||||
*/
|
||||
global $event_config;
|
||||
|
||||
// common variable for every mail sent
|
||||
$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');
|
||||
// basic keys
|
||||
$event_data["sitename"] = api_get_setting('siteName');
|
||||
$event_data["administrator_name"] = api_get_setting('administratorName');
|
||||
$event_data["administrator_surname"] = api_get_setting('administratorSurname');
|
||||
$event_data["administrator_phone"] = api_get_setting('administratorTelephone');
|
||||
$event_data["administrator_email"] = api_get_setting('emailAdministrator');
|
||||
$event_data["portal"] = api_get_path(WEB_PATH);
|
||||
|
||||
// Fill the array's cells with info regarding the user that fired the event
|
||||
// (for the keys in the template)
|
||||
if (isset($event_data["about_user"])) {
|
||||
$about_user = api_get_user_info($event_data["about_user"]);
|
||||
$event_data["firstname"] = $about_user["firstname"];
|
||||
$event_data["lastname"] = $about_user["lastname"];
|
||||
$event_data["username"] = $about_user["username"];
|
||||
$event_data["usermail"] = $about_user["mail"];
|
||||
$event_data["language"] = $about_user["language"];
|
||||
$event_data["user_id"] = $about_user["user_id"];
|
||||
}
|
||||
|
||||
// First, we send the mail to people we put in the $event_data["send_to"]
|
||||
if ($event_data["send_to"] != null) {
|
||||
// the users we precised need to receive the mail
|
||||
foreach ($event_data["send_to"] as $id) {
|
||||
// for every member put in the array
|
||||
// get user's info (to know where to send)
|
||||
$user_info = api_get_user_info($id);
|
||||
|
||||
// get the language the email will be in
|
||||
if ($event_data["prior_lang"] != null) {
|
||||
// if $lang is not null, we use that lang
|
||||
$language = $event_data["prior_lang"];
|
||||
} else {
|
||||
// else we use the user's language
|
||||
$sql = 'SELECT language
|
||||
FROM '.Database::get_main_table(TABLE_MAIN_USER).' u
|
||||
WHERE u.user_id = "'.$id.'"
|
||||
';
|
||||
$language = Database::store_result(
|
||||
Database::query($sql),
|
||||
'ASSOC'
|
||||
);
|
||||
$language = $language[0]["language"];
|
||||
}
|
||||
|
||||
// we get the message in the correct language (or in english if doesn't exist)
|
||||
$result = self::getMessage($event_name, $language);
|
||||
$message = "";
|
||||
$subject = "";
|
||||
self::getCorrectMessage($message, $subject, $language, $result);
|
||||
|
||||
// replace the keycodes used in the message
|
||||
self::formatMessage($message, $subject, $event_config, $event_name, $event_data);
|
||||
|
||||
// sending email
|
||||
$recipient_name = api_get_person_name($user_info['firstname'], $user_info['lastname']);
|
||||
|
||||
// checks if there's a file we need to join to the mail
|
||||
if (isset($values["certificate_pdf_file"])) {
|
||||
$message = str_replace("\n", "<br />", $message);
|
||||
api_mail_html(
|
||||
$recipient_name,
|
||||
$user_info["mail"],
|
||||
$subject,
|
||||
$message,
|
||||
$sender_name,
|
||||
$email_admin,
|
||||
null,
|
||||
[$values['certificate_pdf_file']]
|
||||
);
|
||||
} else {
|
||||
api_mail_html(
|
||||
$recipient_name,
|
||||
$user_info["mail"],
|
||||
$subject,
|
||||
$message,
|
||||
$sender_name,
|
||||
$email_admin
|
||||
);
|
||||
}
|
||||
|
||||
// If the mail only need to be send once (we know that thanks to the events.conf), we log it in the table
|
||||
if ($event_config[$event_name]["sending_mail_once"]) {
|
||||
$sql = 'INSERT INTO '.Database::get_main_table(TABLE_EVENT_SENT).' (user_from, user_to, event_type_name)
|
||||
VALUES ('.$event_data["user_id"].', '.$id.' ,"'.Database::escape_string($event_name).'")
|
||||
';
|
||||
Database::query($sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second, we send to people linked to the event
|
||||
// So, we get everyone
|
||||
$sql = 'SELECT u.user_id, u.language, u.email, u.firstname, u.lastname
|
||||
FROM '.Database::get_main_table(TABLE_EVENT_TYPE_REL_USER).' ue
|
||||
INNER JOIN '.Database::get_main_table(TABLE_MAIN_USER).' u ON u.user_id = ue.user_id
|
||||
WHERE event_type_name = "'.$event_name.'"';
|
||||
$result = Database::store_result(Database::query($sql), 'ASSOC');
|
||||
// for each of the linked users
|
||||
foreach ($result as $key => $value) {
|
||||
// we get the language
|
||||
if ($event_data["prior_lang"] != null) {
|
||||
// if $lang is not null, we use that lang
|
||||
$language = $event_data["prior_lang"];
|
||||
} else {
|
||||
// else we get the user's lang
|
||||
$sql = 'SELECT language FROM '.Database::get_main_table(TABLE_MAIN_USER).'
|
||||
where user_id = '.$value["user_id"].' ';
|
||||
$result = Database::store_result(Database::query($sql), 'ASSOC');
|
||||
|
||||
$language = $result[0]["language"];
|
||||
}
|
||||
|
||||
// we get the message in the correct language (or in english if doesn't exist)
|
||||
$result = self::getMessage($event_name, $language);
|
||||
$message = '';
|
||||
$subject = '';
|
||||
self::getCorrectMessage($message, $subject, $language, $result);
|
||||
|
||||
// replace the keycodes used in the message
|
||||
self::formatMessage($message, $subject, $event_config, $event_name, $event_data);
|
||||
|
||||
// we send the mail
|
||||
$recipient_name = api_get_person_name($value['firstname'], $value['lastname']);
|
||||
|
||||
api_mail_html(
|
||||
$recipient_name,
|
||||
$value["email"],
|
||||
$subject,
|
||||
$message,
|
||||
$sender_name,
|
||||
$email_admin
|
||||
);
|
||||
|
||||
// If the mail only need to be send once (we know that thanks to the events.conf, we log it in the table
|
||||
if ($event_config[$event_name]["sending_mail_once"]) {
|
||||
$sql = 'INSERT INTO '.Database::get_main_table(TABLE_EVENT_SENT).'
|
||||
(user_from, user_to, event_type_name)
|
||||
VALUES ('.$event_data["user_id"].', '.$value["user_id"].' , "'.Database::escape_string($event_name).'");
|
||||
';
|
||||
Database::query($sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a message in a language exists, if the event is activated
|
||||
* and if "manage event" is checked in admin panel.
|
||||
* If yes to three, we can use this class, else we still use api_mail.
|
||||
*
|
||||
* @param string $event_name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function check_if_using_class($event_name)
|
||||
{
|
||||
if (api_get_setting('activate_email_template') === 'false') {
|
||||
return false;
|
||||
}
|
||||
$current_language = api_get_interface_language();
|
||||
|
||||
$sql = 'SELECT COUNT(*) as total
|
||||
FROM '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).' em
|
||||
INNER JOIN '.Database::get_main_table(TABLE_MAIN_LANGUAGE).' l
|
||||
ON em.language_id = l.id
|
||||
WHERE
|
||||
em.event_type_name = "'.$event_name.'" and
|
||||
l.dokeos_folder = "'.$current_language.'" and
|
||||
em.activated = 1';
|
||||
|
||||
$exists = Database::store_result(Database::query($sql), 'ASSOC');
|
||||
if ($exists[0]["total"]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the record containing the good message and subject.
|
||||
*
|
||||
* @param string $event_name
|
||||
* @param string $language
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getMessage($event_name, $language)
|
||||
{
|
||||
$sql = 'SELECT message, subject, l.dokeos_folder
|
||||
FROM '.Database::get_main_table(TABLE_EVENT_EMAIL_TEMPLATE).' em
|
||||
INNER JOIN '.Database::get_main_table(TABLE_MAIN_LANGUAGE).' l
|
||||
ON em.language_id = l.id
|
||||
WHERE
|
||||
em.event_type_name = "'.$event_name.'" AND
|
||||
(l.dokeos_folder = "'.$language.'" OR l.dokeos_folder = "english") AND
|
||||
em.message <> ""
|
||||
';
|
||||
|
||||
return Database::store_result(Database::query($sql), 'ASSOC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the correct message, meaning in the specified language or in english if previous one doesn't exist.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $subject
|
||||
* @param string $language
|
||||
* @param array $result
|
||||
*/
|
||||
private static function getCorrectMessage(&$message, &$subject, $language, $result)
|
||||
{
|
||||
foreach ($result as $msg) {
|
||||
if ($msg["dokeos_folder"] == $language) {
|
||||
$message = $msg["message"];
|
||||
$subject = $msg["subject"];
|
||||
break;
|
||||
} else {
|
||||
if ($msg["dokeos_folder"] == "english") {
|
||||
$message = $msg["message"];
|
||||
$subject = $msg["subject"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the ((key)) by the good values.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $subject
|
||||
* @param array $event_config
|
||||
* @param string $event_name
|
||||
*/
|
||||
private static function formatMessage(&$message, &$subject, $event_config, $event_name, &$event_data)
|
||||
{
|
||||
foreach ($event_config[$event_name]["available_keyvars"] as $key => $word) {
|
||||
$message = str_replace('(('.$key.'))', $event_data[$word], $message);
|
||||
$subject = str_replace('(('.$key.'))', $event_data[$word], $subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
7870
main/inc/lib/exercise.lib.php
Normal file
7870
main/inc/lib/exercise.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
1069
main/inc/lib/exercise_show_functions.lib.php
Normal file
1069
main/inc/lib/exercise_show_functions.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
420
main/inc/lib/export.lib.inc.php
Normal file
420
main/inc/lib/export.lib.inc.php
Normal file
@@ -0,0 +1,420 @@
|
||||
<?php
|
||||
|
||||
/* See license terms in /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Component\Editor\Connector;
|
||||
use Chamilo\CoreBundle\Component\Filesystem\Data;
|
||||
use Ddeboer\DataImport\Writer\CsvWriter;
|
||||
use Ddeboer\DataImport\Writer\ExcelWriter;
|
||||
use MediaAlchemyst\Alchemyst;
|
||||
use MediaAlchemyst\DriversContainer;
|
||||
use Neutron\TemporaryFilesystem\Manager;
|
||||
use Neutron\TemporaryFilesystem\TemporaryFilesystem;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* This is the export library for Chamilo.
|
||||
* Include/require it in your code to use its functionality.
|
||||
* Several functions below are adaptations from functions distributed by www.nexen.net.
|
||||
*/
|
||||
class Export
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tabular data to CSV-file.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $filename
|
||||
* @param bool $writeOnly Whether to only write on disk or also send for download
|
||||
* @param string $enclosure
|
||||
*
|
||||
* @return mixed csv raw data | false if no data to export | string file path if success in $writeOnly mode
|
||||
*/
|
||||
public static function arrayToCsv($data, $filename = 'export', $writeOnly = false, $enclosure = '"')
|
||||
{
|
||||
if (empty($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$enclosure = !empty($enclosure) ? $enclosure : '"';
|
||||
|
||||
$filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.csv';
|
||||
$stream = fopen($filePath, 'w');
|
||||
$writer = new CsvWriter(';', $enclosure, $stream, true);
|
||||
$writer->prepare();
|
||||
|
||||
foreach ($data as $item) {
|
||||
if (empty($item)) {
|
||||
$writer->writeItem([]);
|
||||
continue;
|
||||
}
|
||||
$item = array_map('trim', $item);
|
||||
$writer->writeItem($item);
|
||||
}
|
||||
$writer->finish();
|
||||
|
||||
if (!$writeOnly) {
|
||||
DocumentManager::file_send_for_download($filePath, true, $filename.'.csv');
|
||||
exit;
|
||||
}
|
||||
|
||||
return $filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tabular data to XLS-file.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $filename
|
||||
*/
|
||||
public static function arrayToXls($data, $filename = 'export', $encoding = 'utf-8')
|
||||
{
|
||||
$filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xlsx';
|
||||
|
||||
$file = new \SplFileObject($filePath, 'w');
|
||||
$writer = new ExcelWriter($file);
|
||||
@$writer->prepare();
|
||||
foreach ($data as $row) {
|
||||
@$writer->writeItem($row);
|
||||
}
|
||||
|
||||
@$writer->finish();
|
||||
|
||||
DocumentManager::file_send_for_download($filePath, true, $filename.'.xlsx');
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tabular data to XLS-file included comments.
|
||||
*
|
||||
* @param array $data The comment by cell should be added with the prefix [comment] to be added ($txtCellValue.'[comment]'.$txtComment)
|
||||
*/
|
||||
public static function arrayToXlsAndComments(
|
||||
array $data,
|
||||
string $filename = 'export'
|
||||
) {
|
||||
$filePath = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xlsx';
|
||||
$file = new \SplFileObject($filePath, 'w');
|
||||
|
||||
$excel = @new PHPExcel();
|
||||
|
||||
$type = 'Excel2007';
|
||||
$sheet = null;
|
||||
$row = 1;
|
||||
$prependHeaderRow = false;
|
||||
if (null !== $sheet && !$excel->sheetNameExists($sheet)) {
|
||||
$excel->removeSheetByIndex(0);
|
||||
}
|
||||
|
||||
if (null !== $sheet) {
|
||||
if (!$excel->sheetNameExists($sheet)) {
|
||||
$excel->createSheet()->setTitle($sheet);
|
||||
}
|
||||
$excel->setActiveSheetIndexByName($sheet);
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
$count = count($item);
|
||||
if ($prependHeaderRow && 1 == $row) {
|
||||
$headers = array_keys($item);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
@$excel->getActiveSheet()->setCellValueByColumnAndRow($i, $row, $headers[$i]);
|
||||
}
|
||||
$row++;
|
||||
}
|
||||
$values = array_values($item);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$txtComment = '';
|
||||
$txtValue = $values[$i];
|
||||
if (false !== strpos($values[$i], '[comment]')) {
|
||||
list($txtValue, $txtComment) = explode('[comment]', $values[$i]);
|
||||
}
|
||||
@$excel->getActiveSheet()->setCellValueByColumnAndRow($i, $row, $txtValue);
|
||||
if (!empty($txtComment)) {
|
||||
$columnLetter = PHPExcel_Cell::stringFromColumnIndex($i);
|
||||
$coordinate = $columnLetter.$row;
|
||||
@$excel->getActiveSheet()->getComment($coordinate)->getText()->createTextRun($txtComment);
|
||||
}
|
||||
}
|
||||
$row++;
|
||||
}
|
||||
|
||||
$writer = \PHPExcel_IOFactory::createWriter($excel, $type);
|
||||
$writer->save($file->getPathname());
|
||||
DocumentManager::file_send_for_download($filePath, true, $filename.'.xlsx');
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tabular data to XLS-file (as html table).
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $filename
|
||||
*/
|
||||
public static function export_table_xls_html($data, $filename = 'export', $encoding = 'utf-8')
|
||||
{
|
||||
$file = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xls';
|
||||
$handle = fopen($file, 'a+');
|
||||
$systemEncoding = api_get_system_encoding();
|
||||
fwrite($handle, '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html" charset="'.$encoding.'" /><body><table>');
|
||||
foreach ($data as $id => $row) {
|
||||
foreach ($row as $id2 => $row2) {
|
||||
$data[$id][$id2] = api_htmlentities($row2);
|
||||
}
|
||||
}
|
||||
foreach ($data as $row) {
|
||||
$string = implode("</td><td>", $row);
|
||||
$string = '<tr><td>'.$string.'</td></tr>';
|
||||
if ($encoding != 'utf-8') {
|
||||
$string = api_convert_encoding($string, $encoding, $systemEncoding);
|
||||
}
|
||||
fwrite($handle, $string."\n");
|
||||
}
|
||||
fwrite($handle, '</table></body></html>');
|
||||
fclose($handle);
|
||||
DocumentManager::file_send_for_download($file, true, $filename.'.xls');
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tabular data to XML-file.
|
||||
*
|
||||
* @param array Simple array of data to put in XML
|
||||
* @param string Name of file to be given to the user
|
||||
* @param string Name of common tag to place each line in
|
||||
* @param string Name of the root element. A root element should always be given.
|
||||
* @param string Encoding in which the data is provided
|
||||
*/
|
||||
public static function arrayToXml(
|
||||
$data,
|
||||
$filename = 'export',
|
||||
$item_tagname = 'item',
|
||||
$wrapper_tagname = null,
|
||||
$encoding = null
|
||||
) {
|
||||
if (empty($encoding)) {
|
||||
$encoding = api_get_system_encoding();
|
||||
}
|
||||
$file = api_get_path(SYS_ARCHIVE_PATH).'/'.uniqid('').'.xml';
|
||||
$handle = fopen($file, 'a+');
|
||||
fwrite($handle, '<?xml version="1.0" encoding="'.$encoding.'"?>'."\n");
|
||||
if (!is_null($wrapper_tagname)) {
|
||||
fwrite($handle, "\t".'<'.$wrapper_tagname.'>'."\n");
|
||||
}
|
||||
foreach ($data as $row) {
|
||||
fwrite($handle, '<'.$item_tagname.'>'."\n");
|
||||
foreach ($row as $key => $value) {
|
||||
fwrite($handle, "\t\t".'<'.$key.'>'.$value.'</'.$key.'>'."\n");
|
||||
}
|
||||
fwrite($handle, "\t".'</'.$item_tagname.'>'."\n");
|
||||
}
|
||||
if (!is_null($wrapper_tagname)) {
|
||||
fwrite($handle, '</'.$wrapper_tagname.'>'."\n");
|
||||
}
|
||||
fclose($handle);
|
||||
DocumentManager::file_send_for_download($file, true, $filename.'.xml');
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export hierarchical tabular data to XML-file.
|
||||
*
|
||||
* @param array Hierarchical array of data to put in XML, each element presenting a 'name' and a 'value' property
|
||||
* @param string Name of file to be given to the user
|
||||
* @param string Name of common tag to place each line in
|
||||
* @param string Name of the root element. A root element should always be given.
|
||||
* @param string Encoding in which the data is provided
|
||||
*/
|
||||
public static function export_complex_table_xml(
|
||||
$data,
|
||||
$filename = 'export',
|
||||
$wrapper_tagname = null,
|
||||
$encoding = 'ISO-8859-1'
|
||||
) {
|
||||
$file = api_get_path(SYS_ARCHIVE_PATH).'/'.uniqid('').'.xml';
|
||||
$handle = fopen($file, 'a+');
|
||||
fwrite($handle, '<?xml version="1.0" encoding="'.$encoding.'"?>'."\n");
|
||||
|
||||
if (!is_null($wrapper_tagname)) {
|
||||
fwrite($handle, '<'.$wrapper_tagname.'>');
|
||||
}
|
||||
$s = self::_export_complex_table_xml_helper($data);
|
||||
fwrite($handle, $s);
|
||||
if (!is_null($wrapper_tagname)) {
|
||||
fwrite($handle, '</'.$wrapper_tagname.'>'."\n");
|
||||
}
|
||||
fclose($handle);
|
||||
DocumentManager::file_send_for_download($file, true, $filename.'.xml');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for the hierarchical XML exporter.
|
||||
*
|
||||
* @param array Hierarhical array composed of elements of type ('name'=>'xyz','value'=>'...')
|
||||
* @param int Level of recursivity. Allows the XML to be finely presented
|
||||
*
|
||||
* @return string The XML string to be inserted into the root element
|
||||
*/
|
||||
public static function _export_complex_table_xml_helper($data, $level = 1)
|
||||
{
|
||||
if (count($data) < 1) {
|
||||
return '';
|
||||
}
|
||||
$string = '';
|
||||
foreach ($data as $row) {
|
||||
$string .= "\n".str_repeat("\t", $level).'<'.$row['name'].'>';
|
||||
if (is_array($row['value'])) {
|
||||
$string .= self::_export_complex_table_xml_helper($row['value'], $level + 1)."\n";
|
||||
$string .= str_repeat("\t", $level).'</'.$row['name'].'>';
|
||||
} else {
|
||||
$string .= $row['value'];
|
||||
$string .= '</'.$row['name'].'>';
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data table to be read with the HTML_table class
|
||||
*/
|
||||
public static function export_table_pdf($data, $params = [])
|
||||
{
|
||||
$table_html = self::convert_array_to_html($data, $params);
|
||||
$params['format'] = isset($params['format']) ? $params['format'] : 'A4';
|
||||
$params['orientation'] = isset($params['orientation']) ? $params['orientation'] : 'P';
|
||||
|
||||
$pdf = new PDF($params['format'], $params['orientation'], $params);
|
||||
$pdf->html_to_pdf_with_template($table_html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $html
|
||||
* @param array $params
|
||||
*/
|
||||
public static function export_html_to_pdf($html, $params = [])
|
||||
{
|
||||
$params['format'] = isset($params['format']) ? $params['format'] : 'A4';
|
||||
$params['orientation'] = isset($params['orientation']) ? $params['orientation'] : 'P';
|
||||
|
||||
$pdf = new PDF($params['format'], $params['orientation'], $params);
|
||||
$pdf->html_to_pdf_with_template($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function convert_array_to_html($data, $params = [])
|
||||
{
|
||||
$headers = $data[0];
|
||||
unset($data[0]);
|
||||
|
||||
$header_attributes = isset($params['header_attributes']) ? $params['header_attributes'] : [];
|
||||
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table', 'repeat_header' => '1']);
|
||||
$row = 0;
|
||||
$column = 0;
|
||||
foreach ($headers as $header) {
|
||||
$table->setHeaderContents($row, $column, $header);
|
||||
$attributes = [];
|
||||
if (isset($header_attributes) && isset($header_attributes[$column])) {
|
||||
$attributes = $header_attributes[$column];
|
||||
}
|
||||
if (!empty($attributes)) {
|
||||
$table->updateCellAttributes($row, $column, $attributes);
|
||||
}
|
||||
$column++;
|
||||
}
|
||||
$row++;
|
||||
foreach ($data as &$printable_data_row) {
|
||||
$column = 0;
|
||||
foreach ($printable_data_row as &$printable_data_cell) {
|
||||
$table->setCellContents($row, $column, $printable_data_cell);
|
||||
//$table->updateCellAttributes($row, $column, $atributes);
|
||||
$column++;
|
||||
}
|
||||
$table->updateRowAttributes($row, $row % 2 ? 'class="row_even"' : 'class="row_odd"', true);
|
||||
$row++;
|
||||
}
|
||||
$table_tp_html = $table->toHtml();
|
||||
|
||||
return $table_tp_html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export HTML content in a ODF document.
|
||||
*
|
||||
* @param string $html
|
||||
* @param string $name
|
||||
* @param string $format
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function htmlToOdt($html, $name, $format = 'odt')
|
||||
{
|
||||
$unoconv = api_get_configuration_value('unoconv.binaries');
|
||||
|
||||
if (empty($unoconv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($html)) {
|
||||
$fs = new Filesystem();
|
||||
$paths = [
|
||||
'root_sys' => api_get_path(SYS_PATH),
|
||||
'path.temp' => api_get_path(SYS_ARCHIVE_PATH),
|
||||
];
|
||||
$connector = new Connector();
|
||||
|
||||
$drivers = new DriversContainer();
|
||||
$drivers['configuration'] = [
|
||||
'unoconv.binaries' => $unoconv,
|
||||
'unoconv.timeout' => 60,
|
||||
];
|
||||
|
||||
$tempFilesystem = TemporaryFilesystem::create();
|
||||
$manager = new Manager($tempFilesystem, $fs);
|
||||
$alchemyst = new Alchemyst($drivers, $manager);
|
||||
|
||||
$dataFileSystem = new Data($paths, $fs, $connector, $alchemyst);
|
||||
$content = $dataFileSystem->convertRelativeToAbsoluteUrl($html);
|
||||
$filePath = $dataFileSystem->putContentInTempFile(
|
||||
$content,
|
||||
api_replace_dangerous_char($name),
|
||||
'html'
|
||||
);
|
||||
|
||||
$try = true;
|
||||
|
||||
while ($try) {
|
||||
try {
|
||||
$convertedFile = $dataFileSystem->transcode(
|
||||
$filePath,
|
||||
$format
|
||||
);
|
||||
|
||||
$try = false;
|
||||
DocumentManager::file_send_for_download(
|
||||
$convertedFile,
|
||||
false,
|
||||
$name.'.'.$format
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
// error_log($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3707
main/inc/lib/extra_field.lib.php
Normal file
3707
main/inc/lib/extra_field.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
976
main/inc/lib/extra_field_option.lib.php
Normal file
976
main/inc/lib/extra_field_option.lib.php
Normal file
@@ -0,0 +1,976 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Entity\ExtraFieldOptions;
|
||||
|
||||
/**
|
||||
* Class ExtraFieldOption
|
||||
* Handles the extra fields for various objects (users, sessions, courses).
|
||||
*/
|
||||
class ExtraFieldOption extends Model
|
||||
{
|
||||
public $columns = [
|
||||
'id',
|
||||
'field_id',
|
||||
'option_value',
|
||||
'display_text',
|
||||
'option_order',
|
||||
'priority',
|
||||
'priority_message',
|
||||
'tms',
|
||||
];
|
||||
|
||||
public $extraField;
|
||||
public $fieldId;
|
||||
|
||||
/**
|
||||
* Gets the table for the type of object for which we are using an extra field.
|
||||
*
|
||||
* @param string $type Type of object (course, user or session)
|
||||
*/
|
||||
public function __construct($type)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->type = $type;
|
||||
$extraField = new ExtraField($this->type);
|
||||
$this->extraField = $extraField;
|
||||
$this->table = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
|
||||
$this->tableExtraField = Database::get_main_table(TABLE_EXTRA_FIELD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ExtraField
|
||||
*/
|
||||
public function getExtraField()
|
||||
{
|
||||
return $this->extraField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of options available for this field.
|
||||
*
|
||||
* @param int $fieldId
|
||||
*
|
||||
* @return int Number of options
|
||||
* @assert ('') === false
|
||||
* @assert (-1) == 0
|
||||
* @assert (0) == 0
|
||||
*/
|
||||
public function get_count_by_field_id($fieldId)
|
||||
{
|
||||
if (empty($fieldId)) {
|
||||
return false;
|
||||
}
|
||||
$extraFieldType = $this->getExtraField()->getExtraFieldType();
|
||||
$fieldId = (int) $fieldId;
|
||||
|
||||
$sql = "SELECT count(*) as count
|
||||
FROM $this->table o
|
||||
INNER JOIN $this->tableExtraField e
|
||||
ON o.field_id = e.id
|
||||
WHERE
|
||||
o.field_id = $fieldId AND
|
||||
e.extra_field_type = $extraFieldType ";
|
||||
$result = Database::query($sql);
|
||||
$result = Database::fetch_array($result);
|
||||
|
||||
return $result['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of options for a specific field, separated by ";".
|
||||
*
|
||||
* @param int $field_id
|
||||
* @param bool $add_id_in_array Indicates whether we want the results to be given with their id
|
||||
* @param string $ordered_by Order by clause (without the "order by") to be added to the SQL query
|
||||
*
|
||||
* @return string List of options separated by ;
|
||||
* @assert (-1, false, null) == ''
|
||||
*/
|
||||
public function getFieldOptionsToString($field_id, $add_id_in_array = false, $ordered_by = null)
|
||||
{
|
||||
$options = self::get_field_options_by_field($field_id, $add_id_in_array, $ordered_by);
|
||||
$new_options = [];
|
||||
if (!empty($options)) {
|
||||
foreach ($options as $option) {
|
||||
$new_options[] = $option['option_value'].':'.$option['display_text'];
|
||||
}
|
||||
$string = implode(';', $new_options);
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the options of a specific field.
|
||||
*
|
||||
* @param int $field_id
|
||||
*
|
||||
* @assert (-1) === false
|
||||
*/
|
||||
public function delete_all_options_by_field_id($field_id)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
$sql = "DELETE FROM {$this->table} WHERE field_id = $field_id";
|
||||
|
||||
return Database::query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save option.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $fieldOption = new ExtraFieldOption('user');
|
||||
* $fieldOption->saveOptions([
|
||||
* 'field_id'=> 1,
|
||||
* 'option_value'=> 1,
|
||||
* 'display_text'=> 'extra value option 1',
|
||||
* 'option_order'=>0
|
||||
* ]);
|
||||
* echo "<pre>".var_export($fieldOption,true)."</pre>";
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param array $params
|
||||
* @param bool $showQuery
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
public function saveOptions($params, $showQuery = false)
|
||||
{
|
||||
$optionInfo = $this->get_field_option_by_field_and_option(
|
||||
$params['field_id'],
|
||||
$params['option_value']
|
||||
);
|
||||
|
||||
if (false == $optionInfo) {
|
||||
$optionValue = api_replace_dangerous_char($params['option_value']);
|
||||
$order = $this->get_max_order($params['field_id']);
|
||||
$newParams = [
|
||||
'field_id' => $params['field_id'],
|
||||
'value' => trim($optionValue),
|
||||
'display_text' => trim($params['display_text']),
|
||||
'option_order' => $order,
|
||||
];
|
||||
|
||||
return parent::save($newParams, $showQuery);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an option into the corresponding *_field_options table.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $fieldOption = new ExtraFieldOption('user');
|
||||
* $fieldOption->save([
|
||||
* 'field_id'=> 1,
|
||||
* 'option_value'=> 1,
|
||||
* 'display_text'=> 'extra value option 1',
|
||||
* 'option_order=>0'
|
||||
* ]);
|
||||
* echo "<pre>".var_export($fieldOption,true)."</pre>";
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param array $params Parameters to be considered for the insertion
|
||||
* @param bool $showQuery Whether to show the query (sent to the parent save() method)
|
||||
*
|
||||
* @return bool True on success, false on error
|
||||
* @assert (array('field_id'=>0), false) === false
|
||||
* @assert (array('field_id'=>1), false) === true
|
||||
*/
|
||||
public function save($params, $showQuery = false)
|
||||
{
|
||||
$field_id = (int) $params['field_id'];
|
||||
|
||||
if (empty($field_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parseOptions = in_array(
|
||||
$params['field_type'],
|
||||
[
|
||||
ExtraField::FIELD_TYPE_RADIO,
|
||||
ExtraField::FIELD_TYPE_SELECT,
|
||||
ExtraField::FIELD_TYPE_SELECT_MULTIPLE,
|
||||
ExtraField::FIELD_TYPE_DOUBLE_SELECT,
|
||||
ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD,
|
||||
ExtraField::FIELD_TYPE_TRIPLE_SELECT,
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($params['field_options']) || !$parseOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ($params['field_type']) {
|
||||
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
|
||||
//$params['field_options'] = France:Paris;Bretagne;Marseilles;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
|
||||
case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
|
||||
//$params['field_options'] = Option 1|Option 2|Option 3
|
||||
$options_parsed = ExtraField::extra_field_double_select_convert_string_to_array(
|
||||
$params['field_options']
|
||||
);
|
||||
|
||||
if (empty($options_parsed)) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($options_parsed as $key => $option) {
|
||||
$new_params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => 0,
|
||||
'display_text' => $option['label'],
|
||||
'option_order' => 0,
|
||||
];
|
||||
// Looking if option already exists:
|
||||
$option_info = self::get_field_option_by_field_id_and_option_display_text(
|
||||
$field_id,
|
||||
$option['label']
|
||||
);
|
||||
|
||||
if (empty($option_info)) {
|
||||
$sub_id = parent::save($new_params, $showQuery);
|
||||
} else {
|
||||
$sub_id = $option_info['id'];
|
||||
$new_params['id'] = $sub_id;
|
||||
parent::update($new_params, $showQuery);
|
||||
}
|
||||
|
||||
if (ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD == $params['field_type']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($option['options'] as $sub_option) {
|
||||
if (empty($sub_option)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$new_params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => $sub_id,
|
||||
'display_text' => $sub_option,
|
||||
'option_order' => 0,
|
||||
];
|
||||
$option_info = self::getFieldOptionByFieldIdAndOptionDisplayTextAndOptionValue(
|
||||
$field_id,
|
||||
$sub_option,
|
||||
$sub_id
|
||||
);
|
||||
|
||||
if (empty($option_info)) {
|
||||
parent::save($new_params, $showQuery);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$new_params['id'] = $option_info['id'];
|
||||
parent::update($new_params, $showQuery);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExtraField::FIELD_TYPE_TRIPLE_SELECT:
|
||||
//Format: Option1\Option11:Option111;Option112\Option12:Option121|Option2\Option21:Option211
|
||||
$options = ExtraField::tripleSelectConvertStringToArray($params['field_options']);
|
||||
|
||||
if (!$options) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($options as $level1) {
|
||||
$level1Params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => 0,
|
||||
'display_text' => $level1['label'],
|
||||
'option_order' => 0,
|
||||
];
|
||||
$optionInfo = self::get_field_option_by_field_id_and_option_display_text(
|
||||
$field_id,
|
||||
$level1['label']
|
||||
);
|
||||
|
||||
if (empty($optionInfo)) {
|
||||
$level1Id = parent::save($level1Params);
|
||||
} else {
|
||||
$level1Id = $optionInfo['id'];
|
||||
$level1Params['id'] = $level1Id;
|
||||
parent::update($level1Params);
|
||||
}
|
||||
|
||||
foreach ($level1['options'] as $level2) {
|
||||
$level2Params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => $level1Id,
|
||||
'display_text' => $level2['label'],
|
||||
'display_order' => 0,
|
||||
];
|
||||
$optionInfo = self::getFieldOptionByFieldIdAndOptionDisplayTextAndOptionValue(
|
||||
$field_id,
|
||||
$level2['label'],
|
||||
$level1Id
|
||||
);
|
||||
|
||||
if (empty($optionInfo)) {
|
||||
$level2Id = parent::save($level2Params);
|
||||
} else {
|
||||
$level2Id = $optionInfo['id'];
|
||||
$level2Params['id'] = $level2Id;
|
||||
parent::update($level2Params);
|
||||
}
|
||||
|
||||
foreach ($level2['options'] as $level3) {
|
||||
foreach ($level3 as $item) {
|
||||
$level3Params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => $level2Id,
|
||||
'display_text' => $item,
|
||||
'display_order' => 0,
|
||||
];
|
||||
$optionInfo = self::getFieldOptionByFieldIdAndOptionDisplayTextAndOptionValue(
|
||||
$field_id,
|
||||
$item,
|
||||
$level2Id
|
||||
);
|
||||
|
||||
if (empty($optionInfo)) {
|
||||
parent::save($level3Params);
|
||||
} else {
|
||||
$level3Params['id'] = $optionInfo['id'];
|
||||
parent::update($level3Params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$list = explode(';', $params['field_options']);
|
||||
|
||||
foreach ($list as $option) {
|
||||
$option_info = $this->get_field_option_by_field_and_option($field_id, $option);
|
||||
|
||||
// Use URLify only for new items
|
||||
$optionValue = api_replace_dangerous_char($option);
|
||||
$option = trim($option);
|
||||
|
||||
if (false != $option_info) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$order = $this->get_max_order($field_id);
|
||||
|
||||
$new_params = [
|
||||
'field_id' => $field_id,
|
||||
'option_value' => trim($optionValue),
|
||||
'display_text' => trim($option),
|
||||
'option_order' => $order,
|
||||
];
|
||||
parent::save($new_params, $showQuery);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save one option item at a time.
|
||||
*
|
||||
* @param array $params Parameters specific to the option
|
||||
* @param bool $show_query Whether to show the query (sent to parent save() method)
|
||||
* @param bool $insert_repeated Whether to insert even if the option already exists
|
||||
*
|
||||
* @return bool True on success, false on failure
|
||||
* @assert (array('field_id'=>0),false) === false
|
||||
* @assert (array('field_id'=>0),false) === true
|
||||
*/
|
||||
public function save_one_item($params, $show_query = false, $insert_repeated = true)
|
||||
{
|
||||
$field_id = intval($params['field_id']);
|
||||
if (empty($field_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($params['option_value'])) {
|
||||
$params['option_value'] = trim($params['option_value']);
|
||||
}
|
||||
|
||||
if (isset($params['display_text'])) {
|
||||
$params['display_text'] = trim($params['display_text']);
|
||||
}
|
||||
|
||||
if (empty($params['option_order'])) {
|
||||
$order = $this->get_max_order($field_id);
|
||||
$params['option_order'] = $order;
|
||||
}
|
||||
if ($insert_repeated) {
|
||||
parent::save($params, $show_query);
|
||||
} else {
|
||||
$check = $this->get_field_option_by_field_and_option(
|
||||
$field_id,
|
||||
$params['option_value']
|
||||
);
|
||||
if (false == $check) {
|
||||
parent::save($params, $show_query);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete row of a specific option of a specific field.
|
||||
*
|
||||
* @param int $field_id
|
||||
* @param string $option_value Value of the option
|
||||
*
|
||||
* @return mixed The row on success or false on failure
|
||||
* @assert (0,'') === false
|
||||
*/
|
||||
public function get_field_option_by_field_and_option($field_id, $option_value)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
$option_value = Database::escape_string($option_value);
|
||||
$extraFieldType = $this->getExtraField()->getExtraFieldType();
|
||||
|
||||
$sql = "SELECT s.* FROM {$this->table} s
|
||||
INNER JOIN {$this->tableExtraField} sf
|
||||
ON (s.field_id = sf.id)
|
||||
WHERE
|
||||
field_id = $field_id AND
|
||||
option_value = '".$option_value."' AND
|
||||
sf.extra_field_type = $extraFieldType
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result) > 0) {
|
||||
return Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete row of a specific option's display text of a specific field.
|
||||
*
|
||||
* @param int $field_id
|
||||
* @param string $option_display_text Display value of the option
|
||||
*
|
||||
* @return mixed The row on success or false on failure
|
||||
* @assert (0, '') === false
|
||||
*/
|
||||
public function get_field_option_by_field_id_and_option_display_text($field_id, $option_display_text)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
$option_display_text = Database::escape_string($option_display_text);
|
||||
$extraFieldType = $this->getExtraField()->getExtraFieldType();
|
||||
|
||||
$sql = "SELECT s.* FROM {$this->table} s
|
||||
INNER JOIN {$this->tableExtraField} sf
|
||||
ON (s.field_id = sf.id)
|
||||
WHERE
|
||||
field_id = $field_id AND
|
||||
s.display_text = '".$option_display_text."' AND
|
||||
sf.extra_field_type = $extraFieldType
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result) > 0) {
|
||||
return Database::fetch_array($result, 'ASSOC');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete row of a specific option's display text of a specific field.
|
||||
*
|
||||
* @param int $field_id
|
||||
* @param string $option_display_text Display value of the option
|
||||
* @param string $option_value Value of the option
|
||||
*
|
||||
* @return mixed The row on success or false on failure
|
||||
* @assert (0, '', '') === false
|
||||
*/
|
||||
public function getFieldOptionByFieldIdAndOptionDisplayTextAndOptionValue(
|
||||
$field_id,
|
||||
$option_display_text,
|
||||
$option_value
|
||||
) {
|
||||
$field_id = (int) $field_id;
|
||||
$option_display_text = Database::escape_string($option_display_text);
|
||||
$option_value = Database::escape_string($option_value);
|
||||
$extraFieldType = $this->getExtraField()->getExtraFieldType();
|
||||
|
||||
$sql = "SELECT s.* FROM {$this->table} s
|
||||
INNER JOIN {$this->tableExtraField} sf
|
||||
ON (s.field_id = sf.id)
|
||||
WHERE
|
||||
field_id = $field_id AND
|
||||
sf.display_text = '".$option_display_text."' AND
|
||||
option_value = '$option_value' AND
|
||||
sf.extra_field_type = ".$extraFieldType."
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
if (Database::num_rows($result) > 0) {
|
||||
return Database::fetch_array($result, 'ASSOC');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of options for a specific field.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $fieldOption = new ExtraFieldOption('user');
|
||||
* $fieldOption->get_field_options_by_field(1);
|
||||
* echo "<pre>".var_export($fieldOption,true)."</pre>";
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param int $field_id The field ID
|
||||
* @param bool $add_id_in_array Whether to add the row ID in the result
|
||||
* @param null $ordered_by Extra ordering query bit
|
||||
*
|
||||
* @return array The options if they exists. Otherwise return false
|
||||
*/
|
||||
public function get_field_options_by_field($field_id, $add_id_in_array = false, $ordered_by = null)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
|
||||
$orderBy = null;
|
||||
switch ($ordered_by) {
|
||||
case 'id':
|
||||
$orderBy = ['id' => 'ASC'];
|
||||
break;
|
||||
case 'field_id':
|
||||
$orderBy = ['fieldId' => 'ASC'];
|
||||
break;
|
||||
case 'option_value':
|
||||
$orderBy = ['optionValue' => 'ASC'];
|
||||
break;
|
||||
case 'display_text':
|
||||
$orderBy = ['displayText' => 'ASC'];
|
||||
break;
|
||||
case 'priority':
|
||||
$orderBy = ['priority' => 'ASC'];
|
||||
break;
|
||||
case 'priority_message':
|
||||
$orderBy = ['priorityMessage' => 'ASC'];
|
||||
break;
|
||||
case 'option_order':
|
||||
$orderBy = ['optionOrder' => 'ASC'];
|
||||
break;
|
||||
}
|
||||
|
||||
$result = Database::getManager()
|
||||
->getRepository('ChamiloCoreBundle:ExtraFieldOptions')
|
||||
->findBy(['field' => $field_id], $orderBy);
|
||||
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$options = [];
|
||||
/** @var ExtraFieldOptions $row */
|
||||
foreach ($result as $row) {
|
||||
$option = [
|
||||
'id' => $row->getId(),
|
||||
'field_id' => $row->getField()->getId(),
|
||||
'option_value' => $row->getValue(),
|
||||
'display_text' => self::translateDisplayName($row->getDisplayText()),
|
||||
'priority' => $row->getPriority(),
|
||||
'priority_message' => $row->getPriorityMessage(),
|
||||
'option_order' => $row->getOptionOrder(),
|
||||
];
|
||||
|
||||
if ($add_id_in_array) {
|
||||
$options[$row->getId()] = $option;
|
||||
continue;
|
||||
}
|
||||
$options[] = $option;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get options for a specific field as array or in JSON format suited for the double-select format.
|
||||
*
|
||||
* @param int $option_value_id Option value ID
|
||||
* @param bool $to_json Return format (whether it should be formatted to JSON or not)
|
||||
*
|
||||
* @return mixed Row/JSON on success
|
||||
*/
|
||||
public function get_second_select_field_options_by_field($option_value_id, $to_json = false)
|
||||
{
|
||||
$em = Database::getManager();
|
||||
$option = $em->find('ChamiloCoreBundle:ExtraFieldOptions', $option_value_id);
|
||||
|
||||
if (!$option) {
|
||||
return !$to_json ? [] : '{}';
|
||||
}
|
||||
|
||||
$subOptions = $em
|
||||
->getRepository('ChamiloCoreBundle:ExtraFieldOptions')
|
||||
->findSecondaryOptions($option);
|
||||
|
||||
$optionsInfo = [];
|
||||
/** @var ExtraFieldOptions $subOption */
|
||||
foreach ($subOptions as $subOption) {
|
||||
$optionsInfo[] = [
|
||||
'id' => $subOption->getId(),
|
||||
'field_id' => $subOption->getField()->getId(),
|
||||
'option_value' => $subOption->getValue(),
|
||||
'display_text' => $subOption->getDisplayText(),
|
||||
'priority' => $subOption->getPriority(),
|
||||
'priority_message' => $subOption->getPriorityMessage(),
|
||||
'option_order' => $subOption->getOptionOrder(),
|
||||
];
|
||||
}
|
||||
|
||||
if (!$to_json) {
|
||||
return $optionsInfo;
|
||||
}
|
||||
|
||||
$json = [];
|
||||
|
||||
foreach ($optionsInfo as $optionInfo) {
|
||||
$json[$optionInfo['id']] = $optionInfo['display_text'];
|
||||
}
|
||||
|
||||
return json_encode($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get options for a specific field as string split by ;.
|
||||
*
|
||||
* @param int $field_id
|
||||
* @param string $ordered_by Extra query bit for reordering
|
||||
*
|
||||
* @return string HTML string of options
|
||||
* @assert (0, '') === null
|
||||
*/
|
||||
public function get_field_options_by_field_to_string($field_id, $ordered_by = null)
|
||||
{
|
||||
$field = new ExtraField($this->type);
|
||||
$field_info = $field->get($field_id);
|
||||
$options = self::get_field_options_by_field($field_id, false, $ordered_by);
|
||||
$elements = [];
|
||||
if (!empty($options)) {
|
||||
switch ($field_info['field_type']) {
|
||||
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
|
||||
$html = ExtraField::extra_field_double_select_convert_array_to_string($options);
|
||||
break;
|
||||
case ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
|
||||
$html = ExtraField::extraFieldSelectWithTextConvertArrayToString($options);
|
||||
break;
|
||||
case ExtraField::FIELD_TYPE_TRIPLE_SELECT:
|
||||
$html = ExtraField::tripleSelectConvertArrayToString($options);
|
||||
break;
|
||||
default:
|
||||
foreach ($options as $option) {
|
||||
$elements[] = $option['option_value'];
|
||||
}
|
||||
$html = implode(';', $elements);
|
||||
break;
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum order value for a specific field.
|
||||
*
|
||||
* @param int $field_id
|
||||
*
|
||||
* @return int Current max ID + 1 (we start from 0)
|
||||
* @assert (0, '') === 1
|
||||
*/
|
||||
public function get_max_order($field_id)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
$sql = "SELECT MAX(option_order)
|
||||
FROM {$this->table}
|
||||
WHERE field_id = $field_id";
|
||||
$res = Database::query($sql);
|
||||
$max = 1;
|
||||
if (Database::num_rows($res) > 0) {
|
||||
$row = Database::fetch_array($res);
|
||||
$max = $row[0] + 1;
|
||||
}
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a form with the options for the field_id given in REQUEST.
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
// action links
|
||||
echo '<div class="actions">';
|
||||
$field_id = isset($_REQUEST['field_id']) ? intval($_REQUEST['field_id']) : null;
|
||||
echo '<a href="'.api_get_self().'?action=add&type='.$this->type.'&field_id='.$field_id.'">'.
|
||||
Display::return_icon('add_user_fields.png', get_lang('Add'), '', ICON_SIZE_MEDIUM).'</a>';
|
||||
echo '</div>';
|
||||
echo Display::grid_html('extra_field_options');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPriorityOptions()
|
||||
{
|
||||
return [
|
||||
'' => get_lang('SelectAnOption'),
|
||||
1 => get_lang('Success'),
|
||||
2 => get_lang('Info'),
|
||||
3 => get_lang('Warning'),
|
||||
4 => get_lang('Error'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $priority
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPriorityMessageType($priority)
|
||||
{
|
||||
switch ($priority) {
|
||||
case 1:
|
||||
return 'success';
|
||||
case 2:
|
||||
return 'info';
|
||||
case 3:
|
||||
return 'warning';
|
||||
case 4:
|
||||
return 'error';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTML form for the current field.
|
||||
*
|
||||
* @param string URL to send the form to (action=...)
|
||||
* @param string Type of action to offer through the form (edit, usually)
|
||||
*
|
||||
* @return FormValidator
|
||||
*/
|
||||
public function return_form($url, $action)
|
||||
{
|
||||
$form_name = $this->type.'_field';
|
||||
$form = new FormValidator($form_name, 'post', $url);
|
||||
// Setting the form elements
|
||||
$header = get_lang('Add');
|
||||
if ($action === 'edit') {
|
||||
$header = get_lang('Modify');
|
||||
}
|
||||
|
||||
$form->addElement('header', $header);
|
||||
$id = isset($_GET['id']) ? (int) $_GET['id'] : '';
|
||||
|
||||
$form->addElement('hidden', 'id', $id);
|
||||
$form->addElement('hidden', 'type', $this->type);
|
||||
$form->addElement('hidden', 'field_id', $this->fieldId);
|
||||
|
||||
if ('edit' == $action) {
|
||||
$translateUrl = api_get_path(WEB_CODE_PATH).'extrafield/translate.php?'.http_build_query([
|
||||
'extra_field_option' => $id,
|
||||
]);
|
||||
$translateButton = Display::toolbarButton(
|
||||
get_lang('TranslateThisTerm'),
|
||||
$translateUrl,
|
||||
'language',
|
||||
'link'
|
||||
);
|
||||
|
||||
$form->addText(
|
||||
'display_text',
|
||||
[get_lang('Name'), $translateButton]
|
||||
);
|
||||
} else {
|
||||
$form->addElement('text', 'display_text', get_lang('Name'));
|
||||
}
|
||||
|
||||
$form->addElement('text', 'option_value', get_lang('Value'));
|
||||
$form->addElement('text', 'option_order', get_lang('Order'));
|
||||
$form->addElement('select', 'priority', get_lang('Priority'), $this->getPriorityOptions());
|
||||
$form->addElement('textarea', 'priority_message', get_lang('PriorityOfMessage'));
|
||||
|
||||
$defaults = [];
|
||||
|
||||
if ('edit' == $action) {
|
||||
// Setting the defaults
|
||||
$defaults = $this->get($id, false);
|
||||
$form->freeze('option_value');
|
||||
$form->addButtonUpdate(get_lang('Modify'));
|
||||
} else {
|
||||
$form->addButtonCreate(get_lang('Add'));
|
||||
}
|
||||
|
||||
$form->setDefaults($defaults);
|
||||
|
||||
// Setting the rules
|
||||
$form->addRule('display_text', get_lang('ThisFieldIsRequired'), 'required');
|
||||
$form->addRule('option_value', get_lang('ThisFieldIsRequired'), 'required');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
* @param int $field_id
|
||||
* @param int $limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function searchByField($tag, $field_id, $limit = 10)
|
||||
{
|
||||
$field_id = (int) $field_id;
|
||||
$limit = (int) $limit;
|
||||
$tag = Database::escape_string($tag);
|
||||
|
||||
$sql = "SELECT DISTINCT id, option_display_text
|
||||
FROM {$this->table}
|
||||
WHERE
|
||||
field_id = '".$field_id."' AND
|
||||
option_value LIKE '%$tag%'
|
||||
ORDER BY option_value
|
||||
LIMIT 0, $limit
|
||||
";
|
||||
$result = Database::query($sql);
|
||||
$values = [];
|
||||
if (Database::num_rows($result)) {
|
||||
$values = Database::store_result($result, 'ASSOC');
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
* @param int $field_id
|
||||
* @param int $limit
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSearchOptionsByField($tag, $field_id, $limit = 10)
|
||||
{
|
||||
$result = $this->searchByField($tag, $field_id, $limit = 10);
|
||||
$values = [];
|
||||
$json = null;
|
||||
if (!empty($result)) {
|
||||
foreach ($result as $item) {
|
||||
$values[] = [
|
||||
'value' => $item['id'],
|
||||
'caption' => $item['option_display_text'],
|
||||
];
|
||||
}
|
||||
$json = json_encode($values);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an element.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $translateDisplayText Optional
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get($id, $translateDisplayText = true)
|
||||
{
|
||||
$info = parent::get($id);
|
||||
|
||||
if ($translateDisplayText) {
|
||||
$info['display_text'] = self::translateDisplayName($info['display_text']);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the display text for a extra field option.
|
||||
*
|
||||
* @param string $defaultDisplayText
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function translateDisplayName($defaultDisplayText)
|
||||
{
|
||||
$variableLanguage = self::getLanguageVariable($defaultDisplayText);
|
||||
|
||||
return isset($GLOBALS[$variableLanguage]) ? $GLOBALS[$variableLanguage] : $defaultDisplayText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $defaultDisplayText
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
public static function getLanguageVariable($defaultDisplayText)
|
||||
{
|
||||
$variableLanguage = api_replace_dangerous_char($defaultDisplayText);
|
||||
$variableLanguage = str_replace('-', '_', $variableLanguage);
|
||||
$variableLanguage = api_underscore_to_camel_case($variableLanguage);
|
||||
|
||||
return $variableLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all($options = null)
|
||||
{
|
||||
$result = parent::get_all($options);
|
||||
|
||||
foreach ($result as &$row) {
|
||||
$row['display_text'] = self::translateDisplayName($row['display_text']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $variable
|
||||
*
|
||||
* @return array|ExtraFieldOptions[]
|
||||
*/
|
||||
public function getOptionsByFieldVariable($variable)
|
||||
{
|
||||
$extraFieldType = $this->getExtraField()->getExtraFieldType();
|
||||
|
||||
$dql = "SELECT o FROM ChamiloCoreBundle:ExtraFieldOptions o
|
||||
INNER JOIN ChamiloCoreBundle:ExtraField f WITH o.field = f.id
|
||||
WHERE f.variable = :variable AND f.extraFieldType = :extra_field_type
|
||||
ORDER BY o.value ASC";
|
||||
|
||||
$result = Database::getManager()
|
||||
->createQuery($dql)
|
||||
->setParameters(['variable' => $variable, 'extra_field_type' => $extraFieldType])
|
||||
->getResult();
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
1224
main/inc/lib/extra_field_value.lib.php
Normal file
1224
main/inc/lib/extra_field_value.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
208
main/inc/lib/fileDisplay.lib.php
Normal file
208
main/inc/lib/fileDisplay.lib.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
/* See license terms in /license.txt */
|
||||
/**
|
||||
* This is the file display library for Dokeos.
|
||||
* Include/require it in your code to use its functionality.
|
||||
*
|
||||
* @todo move this file to DocumentManager
|
||||
*
|
||||
* Define the image to display for each file extension.
|
||||
* This needs an existing image repository to work.
|
||||
*
|
||||
* @author - Hugues Peeters <peeters@ipm.ucl.ac.be>
|
||||
*
|
||||
* @param string $file_name (string) - Name of a file
|
||||
*
|
||||
* @return string The gif image to chose
|
||||
*/
|
||||
function choose_image($file_name)
|
||||
{
|
||||
static $type, $image;
|
||||
|
||||
/* TABLES INITIALISATION */
|
||||
if (!$type || !$image) {
|
||||
$type['word'] = [
|
||||
'doc',
|
||||
'dot',
|
||||
'rtf',
|
||||
'mcw',
|
||||
'wps',
|
||||
'psw',
|
||||
'docm',
|
||||
'docx',
|
||||
'dotm',
|
||||
'dotx',
|
||||
];
|
||||
$type['web'] = [
|
||||
'htm',
|
||||
'html',
|
||||
'htx',
|
||||
'xml',
|
||||
'xsl',
|
||||
'php',
|
||||
'xhtml',
|
||||
];
|
||||
$type['image'] = [
|
||||
'gif',
|
||||
'jpg',
|
||||
'png',
|
||||
'bmp',
|
||||
'jpeg',
|
||||
'tif',
|
||||
'tiff',
|
||||
];
|
||||
$type['image_vect'] = ['svg', 'svgz'];
|
||||
$type['audio'] = [
|
||||
'wav',
|
||||
'mid',
|
||||
'mp2',
|
||||
'mp3',
|
||||
'midi',
|
||||
'sib',
|
||||
'amr',
|
||||
'kar',
|
||||
'oga',
|
||||
'au',
|
||||
'wma',
|
||||
];
|
||||
$type['video'] = [
|
||||
'mp4',
|
||||
'mov',
|
||||
'rm',
|
||||
'pls',
|
||||
'mpg',
|
||||
'mpeg',
|
||||
'm2v',
|
||||
'm4v',
|
||||
'flv',
|
||||
'f4v',
|
||||
'avi',
|
||||
'wmv',
|
||||
'asf',
|
||||
'3gp',
|
||||
'ogv',
|
||||
'ogg',
|
||||
'ogx',
|
||||
'webm',
|
||||
];
|
||||
$type['excel'] = [
|
||||
'xls',
|
||||
'xlt',
|
||||
'xls',
|
||||
'xlt',
|
||||
'pxl',
|
||||
'xlsx',
|
||||
'xlsm',
|
||||
'xlam',
|
||||
'xlsb',
|
||||
'xltm',
|
||||
'xltx',
|
||||
];
|
||||
$type['compressed'] = ['zip', 'tar', 'rar', 'gz'];
|
||||
$type['code'] = [
|
||||
'js',
|
||||
'cpp',
|
||||
'c',
|
||||
'java',
|
||||
'phps',
|
||||
'jsp',
|
||||
'asp',
|
||||
'aspx',
|
||||
'cfm',
|
||||
];
|
||||
$type['acrobat'] = ['pdf'];
|
||||
$type['powerpoint'] = [
|
||||
'ppt',
|
||||
'pps',
|
||||
'pptm',
|
||||
'pptx',
|
||||
'potm',
|
||||
'potx',
|
||||
'ppam',
|
||||
'ppsm',
|
||||
'ppsx',
|
||||
];
|
||||
$type['flash'] = ['fla', 'swf'];
|
||||
$type['text'] = ['txt', 'log'];
|
||||
$type['oo_writer'] = ['odt', 'ott', 'sxw', 'stw'];
|
||||
$type['oo_calc'] = ['ods', 'ots', 'sxc', 'stc'];
|
||||
$type['oo_impress'] = ['odp', 'otp', 'sxi', 'sti'];
|
||||
$type['oo_draw'] = ['odg', 'otg', 'sxd', 'std'];
|
||||
$type['epub'] = ['epub'];
|
||||
$type['java'] = ['class', 'jar'];
|
||||
$type['freemind'] = ['mm'];
|
||||
|
||||
$image['word'] = 'word.png';
|
||||
$image['web'] = 'file_html.png';
|
||||
$image['image'] = 'file_image.png';
|
||||
$image['image_vect'] = 'file_svg.png';
|
||||
$image['audio'] = 'file_sound.png';
|
||||
$image['video'] = 'film.png';
|
||||
$image['excel'] = 'excel.png';
|
||||
$image['compressed'] = 'file_zip.png';
|
||||
$image['code'] = 'icons/22/mime_code.png';
|
||||
$image['acrobat'] = 'file_pdf.png';
|
||||
$image['powerpoint'] = 'powerpoint.png';
|
||||
$image['flash'] = 'file_flash.png';
|
||||
$image['text'] = 'icons/22/mime_text.png';
|
||||
$image['oo_writer'] = 'file_oo_writer.png';
|
||||
$image['oo_calc'] = 'file_oo_calc.png';
|
||||
$image['oo_impress'] = 'file_oo_impress.png';
|
||||
$image['oo_draw'] = 'file_oo_draw.png';
|
||||
$image['epub'] = 'file_epub.png';
|
||||
$image['java'] = 'file_java.png';
|
||||
$image['freemind'] = 'file_freemind.png';
|
||||
}
|
||||
|
||||
$extension = [];
|
||||
if (!is_array($file_name)) {
|
||||
if (preg_match('/\.([[:alnum:]]+)(\?|$)/', $file_name, $extension)) {
|
||||
$extension[1] = strtolower($extension[1]);
|
||||
|
||||
foreach ($type as $generic_type => $extension_list) {
|
||||
if (in_array($extension[1], $extension_list)) {
|
||||
return $image[$generic_type];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 'defaut.gif';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon to display for a folder by its path.
|
||||
*
|
||||
* @param string $folderPath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function chooseFolderIcon($folderPath)
|
||||
{
|
||||
if ($folderPath == '/shared_folder') {
|
||||
return 'folder_users.png';
|
||||
}
|
||||
|
||||
if (strstr($folderPath, 'shared_folder_session_')) {
|
||||
return 'folder_users.png';
|
||||
}
|
||||
|
||||
switch ($folderPath) {
|
||||
case '/audio':
|
||||
return 'folder_audio.png';
|
||||
case '/flash':
|
||||
return 'folder_flash.png';
|
||||
case '/images':
|
||||
return 'folder_images.png';
|
||||
case '/video':
|
||||
return 'folder_video.png';
|
||||
case '/images/gallery':
|
||||
return 'folder_gallery.png';
|
||||
case '/chat_files':
|
||||
return 'folder_chat.png';
|
||||
case '/learning_path':
|
||||
return 'folder_learningpath.png';
|
||||
}
|
||||
|
||||
return 'folder_document.png';
|
||||
}
|
||||
388
main/inc/lib/fileManage.lib.php
Normal file
388
main/inc/lib/fileManage.lib.php
Normal file
@@ -0,0 +1,388 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
/**
|
||||
* This is the file manage library for Chamilo.
|
||||
* Include/require it in your code to use its functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cheks a file or a directory actually exist at this location.
|
||||
*
|
||||
* @author Hugues Peeters <peeters@ipm.ucl.ac.be>
|
||||
*
|
||||
* @param string $file_path Path of the presume existing file or dir
|
||||
*
|
||||
* @return bool TRUE if the file or the directory exists or FALSE otherwise
|
||||
*/
|
||||
function check_name_exist($file_path)
|
||||
{
|
||||
clearstatcache();
|
||||
$save_dir = getcwd();
|
||||
if (!is_dir(dirname($file_path))) {
|
||||
return false;
|
||||
}
|
||||
chdir(dirname($file_path));
|
||||
$file_name = basename($file_path);
|
||||
|
||||
if (file_exists($file_name)) {
|
||||
chdir($save_dir);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
chdir($save_dir);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a file or a directory.
|
||||
*
|
||||
* @author - Hugues Peeters
|
||||
*
|
||||
* @param $file (String) - the path of file or directory to delete
|
||||
*
|
||||
* @return bool - true if the delete succeed, false otherwise
|
||||
*
|
||||
* @see - delete() uses check_name_exist() and removeDir() functions
|
||||
*/
|
||||
function my_delete($file)
|
||||
{
|
||||
if (check_name_exist($file)) {
|
||||
if (is_file($file)) { // FILE CASE
|
||||
unlink($file);
|
||||
|
||||
return true;
|
||||
} elseif (is_dir($file)) { // DIRECTORY CASE
|
||||
removeDir($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // no file or directory to delete
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a directory recursively.
|
||||
*
|
||||
* @returns true if OK, otherwise false
|
||||
*
|
||||
* @author Amary <MasterNES@aol.com> (from Nexen.net)
|
||||
* @author Olivier Brouckaert <oli.brouckaert@skynet.be>
|
||||
*
|
||||
* @param string $dir directory to remove
|
||||
*/
|
||||
function removeDir($dir)
|
||||
{
|
||||
if (!@$opendir = opendir($dir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while ($readdir = readdir($opendir)) {
|
||||
if ($readdir != '..' && $readdir != '.') {
|
||||
if (is_file($dir.'/'.$readdir)) {
|
||||
if (!@unlink($dir.'/'.$readdir)) {
|
||||
return false;
|
||||
}
|
||||
} elseif (is_dir($dir.'/'.$readdir)) {
|
||||
if (!removeDir($dir.'/'.$readdir)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir($opendir);
|
||||
|
||||
if (!@rmdir($dir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if folder is empty.
|
||||
*
|
||||
* @author hubert.borderiou@grenet.fr
|
||||
*
|
||||
* @param string $in_folder folder path on disk
|
||||
*
|
||||
* @return int 1 if folder is empty, 0 otherwise
|
||||
*/
|
||||
function folder_is_empty($in_folder)
|
||||
{
|
||||
$folder_is_empty = 0;
|
||||
if (is_dir($in_folder)) {
|
||||
$tab_folder_content = scandir($in_folder);
|
||||
if ((
|
||||
count($tab_folder_content) == 2 &&
|
||||
in_array(".", $tab_folder_content) &&
|
||||
in_array("..", $tab_folder_content)
|
||||
) ||
|
||||
(count($tab_folder_content) < 2)
|
||||
) {
|
||||
$folder_is_empty = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $folder_is_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a file or a directory.
|
||||
*
|
||||
* @author Hugues Peeters <peeters@ipm.ucl.ac.be>
|
||||
*
|
||||
* @param string $file_path complete path of the file or the directory
|
||||
* @param string $new_file_name new name for the file or the directory
|
||||
*
|
||||
* @return bool true if succeed, false otherwise
|
||||
*
|
||||
* @see rename() uses the check_name_exist() and php2phps() functions
|
||||
*/
|
||||
function my_rename($file_path, $new_file_name)
|
||||
{
|
||||
$save_dir = getcwd();
|
||||
$path = dirname($file_path);
|
||||
$old_file_name = basename($file_path);
|
||||
$new_file_name = api_replace_dangerous_char($new_file_name);
|
||||
|
||||
// If no extension, take the old one
|
||||
if ((strpos($new_file_name, '.') === false) && ($dotpos = strrpos($old_file_name, '.'))) {
|
||||
$new_file_name .= substr($old_file_name, $dotpos);
|
||||
}
|
||||
|
||||
// Note: still possible: 'xx.yy' -rename-> '.yy' -rename-> 'zz'
|
||||
// This is useful for folder names, where otherwise '.' would be sticky
|
||||
|
||||
// Extension PHP is not allowed, change to PHPS
|
||||
$new_file_name = php2phps($new_file_name);
|
||||
|
||||
if ($new_file_name == $old_file_name) {
|
||||
return $old_file_name;
|
||||
}
|
||||
|
||||
if (strtolower($new_file_name) != strtolower($old_file_name) && check_name_exist($path.'/'.$new_file_name)) {
|
||||
return false;
|
||||
}
|
||||
// On a Windows server, it would be better not to do the above check
|
||||
// because it succeeds for some new names resembling the old name.
|
||||
// But on Unix/Linux the check must be done because rename overwrites.
|
||||
|
||||
chdir($path);
|
||||
$res = rename($old_file_name, $new_file_name) ? $new_file_name : false;
|
||||
chdir($save_dir);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a file or a directory to an other area.
|
||||
*
|
||||
* @author Hugues Peeters <peeters@ipm.ucl.ac.be>
|
||||
*
|
||||
* @param string $source the path of file or directory to move
|
||||
* @param string $target the path of the new area
|
||||
* @param bool $forceMove Whether to force a move or to make a copy (safer but slower) and then delete the original
|
||||
* @param bool $moveContent In some cases (including migrations), we need to move the *content* and not the folder itself
|
||||
*
|
||||
* @return bool true if the move succeed, false otherwise
|
||||
*
|
||||
* @see move() uses check_name_exist() and copyDirTo() functions
|
||||
*/
|
||||
function move($source, $target, $forceMove = true, $moveContent = false)
|
||||
{
|
||||
$target = realpath($target); // remove trailing slash
|
||||
$source = realpath($source);
|
||||
if (check_name_exist($source)) {
|
||||
$file_name = basename($source);
|
||||
// move onto self illegal: mv a/b/c a/b/c or mv a/b/c a/b
|
||||
if (strcasecmp($target, dirname($source)) === 0) {
|
||||
return false;
|
||||
}
|
||||
$isWindowsOS = api_is_windows_os();
|
||||
$canExec = function_exists('exec');
|
||||
|
||||
/* File case */
|
||||
if (is_file($source)) {
|
||||
if ($forceMove) {
|
||||
if (!$isWindowsOS && $canExec) {
|
||||
exec('mv '.$source.' '.$target.'/'.$file_name);
|
||||
} else {
|
||||
// Try copying
|
||||
copy($source, $target.'/'.$file_name);
|
||||
unlink($source);
|
||||
}
|
||||
} else {
|
||||
copy($source, $target.'/'.$file_name);
|
||||
unlink($source);
|
||||
}
|
||||
|
||||
return true;
|
||||
} elseif (is_dir($source)) {
|
||||
// move dir down will cause loop: mv a/b/ a/b/c/ not legal
|
||||
if (strncasecmp($target, $source, strlen($source)) == 0) {
|
||||
return false;
|
||||
}
|
||||
/* Directory */
|
||||
if ($forceMove && !$isWindowsOS && $canExec) {
|
||||
if ($moveContent) {
|
||||
$base = basename($source);
|
||||
$out = [];
|
||||
$retVal = -1;
|
||||
exec('mv '.$source.'/* '.$target.'/'.$base, $out, $retVal);
|
||||
if ($retVal !== 0) {
|
||||
return false; // mv should return 0 on success
|
||||
}
|
||||
exec('rm -rf '.$source);
|
||||
} else {
|
||||
$out = [];
|
||||
$retVal = -1;
|
||||
exec("mv $source $target", $out, $retVal);
|
||||
if ($retVal !== 0) {
|
||||
error_log("Chamilo error fileManage.lib.php: mv $source $target\n");
|
||||
|
||||
return false; // mv should return 0 on success
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$base = basename($source);
|
||||
|
||||
return copyDirTo($source, $target.'/'.$base);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a directory and its content to an other area.
|
||||
*
|
||||
* @author Hugues Peeters <peeters@ipm.ucl.ac.be>
|
||||
*
|
||||
* @param string $source the path of the directory to move
|
||||
* @param string $destination the path of the new area
|
||||
* @param bool $move Whether we want to remove the source at the end
|
||||
*
|
||||
* @return bool false on error
|
||||
*/
|
||||
function copyDirTo($source, $destination, $move = true)
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
if (is_dir($source)) {
|
||||
$fs->mkdir($destination);
|
||||
if (!is_dir($destination)) {
|
||||
error_log("Chamilo copyDirTo cannot mkdir $destination\n");
|
||||
|
||||
return false; // could not create destination dir
|
||||
}
|
||||
$fs->mirror($source, $destination);
|
||||
if ($move) {
|
||||
$fs->remove($source);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a directory and its directories (not files) to an other area.
|
||||
*
|
||||
* @param string $source the path of the directory to move
|
||||
* @param string $destination the path of the new area
|
||||
*
|
||||
* @return bool false on error
|
||||
*/
|
||||
function copyDirWithoutFilesTo($source, $destination)
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
|
||||
if (!is_dir($source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$fs->exists($destination)) {
|
||||
$fs->mkdir($destination);
|
||||
}
|
||||
|
||||
$dirIterator = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator, RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
/** @var \SplFileInfo $item */
|
||||
foreach ($iterator as $item) {
|
||||
if ($item->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newDir = $destination.'/'.$item->getFilename();
|
||||
|
||||
if (!$fs->exists($newDir)) {
|
||||
$fs->mkdir($destination.'/'.$item->getFilename());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracting extension of a filename.
|
||||
*
|
||||
* @returns array
|
||||
*
|
||||
* @param string $filename filename
|
||||
*/
|
||||
function getextension($filename)
|
||||
{
|
||||
$bouts = explode('.', $filename);
|
||||
|
||||
return [array_pop($bouts), implode('.', $bouts)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all PHP (.php) files in a given directory. Includes .tpl files.
|
||||
*
|
||||
* @param string $base_path The base path in which to find the corresponding files
|
||||
* @param bool $includeStatic Include static .html, .htm and .css files
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getAllPhpFiles($base_path, $includeStatic = false)
|
||||
{
|
||||
$list = scandir($base_path);
|
||||
$files = [];
|
||||
$extensionsArray = ['.php', '.tpl'];
|
||||
if ($includeStatic) {
|
||||
$extensionsArray[] = 'html';
|
||||
$extensionsArray[] = '.htm';
|
||||
$extensionsArray[] = '.css';
|
||||
}
|
||||
foreach ($list as $item) {
|
||||
if (substr($item, 0, 1) == '.') {
|
||||
continue;
|
||||
}
|
||||
$special_dirs = [api_get_path(SYS_TEST_PATH), api_get_path(SYS_COURSE_PATH), api_get_path(SYS_LANG_PATH), api_get_path(SYS_ARCHIVE_PATH)];
|
||||
if (in_array($base_path.$item.'/', $special_dirs)) {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($base_path.$item)) {
|
||||
$files = array_merge($files, getAllPhpFiles($base_path.$item.'/', $includeStatic));
|
||||
} else {
|
||||
//only analyse php files
|
||||
$sub = substr($item, -4);
|
||||
if (in_array($sub, $extensionsArray)) {
|
||||
$files[] = $base_path.$item;
|
||||
}
|
||||
}
|
||||
}
|
||||
$list = null;
|
||||
|
||||
return $files;
|
||||
}
|
||||
2274
main/inc/lib/fileUpload.lib.php
Normal file
2274
main/inc/lib/fileUpload.lib.php
Normal file
File diff suppressed because it is too large
Load Diff
118
main/inc/lib/fixlinks.js
Normal file
118
main/inc/lib/fixlinks.js
Normal file
@@ -0,0 +1,118 @@
|
||||
$(function() {
|
||||
var objects = $(document).find('object');
|
||||
var pathname = location.pathname;
|
||||
var coursePath = pathname.substr(0, pathname.indexOf('/courses/'));
|
||||
var iconPath = location.protocol + '//' + location.host+ coursePath + '/main/img/';
|
||||
var url = "http://"+location.host + coursePath+"/courses/proxy.php?";
|
||||
|
||||
objects.each(function (value, obj) {
|
||||
var openerId = this.id +'_opener';
|
||||
var link = '<a id="'+openerId+'" href="#">If video does not work, try clicking here.</a>';
|
||||
var embed = $("#"+this.id).find('embed').first();
|
||||
|
||||
var hasHttp = embed.attr('src').indexOf("http");
|
||||
|
||||
if (hasHttp < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var height = embed.attr('height');
|
||||
var width = embed.attr('width');
|
||||
var src = embed.attr('src').replace('https', 'http');
|
||||
|
||||
var completeUrl = url + 'width='+embed.attr('width')+
|
||||
'&height='+height+
|
||||
'&id='+this.id+
|
||||
'&flashvars='+encodeURIComponent(embed.attr('flashvars'))+
|
||||
'&src='+src+
|
||||
'&width='+width;
|
||||
|
||||
var result = $("#"+this.id).find('#'+openerId);
|
||||
if (result.length == 0) {
|
||||
$("#" + this.id).append('<br />' + link);
|
||||
$('#' + openerId).click(function () {
|
||||
var window = window.open(completeUrl, "Video", "width=" + width + ", " + "height=" + height + "");
|
||||
window.document.title = 'Video';
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var iframes = $(document).find('iframe');
|
||||
iframes.each(function (value, obj) {
|
||||
var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
|
||||
var uniqid = randLetter + Date.now();
|
||||
var openerId = uniqid +'_opener';
|
||||
var link = '<a id="'+openerId+'" class="generated" href="#">Open website.<img width="16px" src="'+iconPath+'link-external.png "/></a>';
|
||||
var embed = $(this);
|
||||
var height = embed.attr('height');
|
||||
var width = embed.attr('width');
|
||||
var src = embed.attr('src');
|
||||
|
||||
var n = src.indexOf("youtube.com");
|
||||
if (n > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var completeUrl = url + 'width='+embed.attr('width')+
|
||||
'&height='+height+
|
||||
'&type=iframe'+
|
||||
'&id='+uniqid+
|
||||
'&src='+src+
|
||||
'&width='+width;
|
||||
var result = $(this).find('#'+openerId);
|
||||
|
||||
if (result.length == 0) {
|
||||
if (embed.next().attr('class') != 'generated') {
|
||||
$(this).prepend(link + '<br />');
|
||||
$('#' + openerId).click(function () {
|
||||
width = 1280;
|
||||
height = 640;
|
||||
var win = window.open(completeUrl, "Video", "width=" + width + ", " + "height=" + height + "");
|
||||
win.document.title = 'Video';
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var anchors = $(document).find('a').not('.generated');
|
||||
anchors.each(function (value, obj) {
|
||||
if ($(this).next().attr('class') != 'generated' ) {
|
||||
var content = $(this).html();
|
||||
content = content.replace('<br />', '');
|
||||
content = content.replace('<br>', '');
|
||||
content = $.trim(content);
|
||||
if (content == '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($(this).attr('href')) {
|
||||
var hasLocalhost = $(this).attr('href').indexOf(location.host);
|
||||
|
||||
if (hasLocalhost > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var hasJs = $(this).attr('href').indexOf('javascript');
|
||||
if (hasJs >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($(this).attr('class')) {
|
||||
var hasAccordion = $(this).attr('class').indexOf('accordion-toggle');
|
||||
if (hasAccordion >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var src = $(this).attr('href');
|
||||
src = url+'&type=link&src='+src;
|
||||
src = src.replace('https', 'http');
|
||||
$(this).attr('href', src);
|
||||
$(this).attr('target', '_blank');
|
||||
var myAnchor = $('<a><img width="16px" src="'+iconPath+'link-external.png "/></a>').attr("href", src).attr('target', '_blank').attr('class', 'generated');
|
||||
$(this).after(myAnchor);
|
||||
$(this).after('-');
|
||||
}
|
||||
});
|
||||
});
|
||||
6
main/inc/lib/flv_player/index.html
Normal file
6
main/inc/lib/flv_player/index.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
BIN
main/inc/lib/flv_player/player_flv_mini.swf
Normal file
BIN
main/inc/lib/flv_player/player_flv_mini.swf
Normal file
Binary file not shown.
86
main/inc/lib/formvalidator/Element/BigUpload.php
Normal file
86
main/inc/lib/formvalidator/Element/BigUpload.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Input file with progress element.
|
||||
*
|
||||
* Class BigUpload
|
||||
*/
|
||||
class BigUpload extends HTML_QuickForm_file
|
||||
{
|
||||
/**
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
$origin = $this->getAttribute('data-origin');
|
||||
$id = $this->getAttribute('id');
|
||||
$maxSize = getIniMaxFileSizeInBytes();
|
||||
$errorUploadMessage = get_lang('FileSizeIsTooBig').' '.get_lang('MaxFileSize').' : '.getIniMaxFileSizeInBytes(true);
|
||||
$html = parent::toHtml();
|
||||
$html .= '<div id="'.$id.'-bigUploadProgressBarContainer">
|
||||
<div id="'.$id.'-bigUploadProgressBarFilled"></div>
|
||||
</div>
|
||||
<div id="'.$id.'-bigUploadTimeRemaining"></div>
|
||||
<div id="'.$id.'-bigUploadResponse"></div>';
|
||||
$js = '<script src="'.api_get_path(WEB_LIBRARY_JS_PATH).'bigupload/js/bigUpload.js"></script>';
|
||||
$js .= '<script>
|
||||
var bigUpload = new bigUpload();
|
||||
var uploadForm, formId, submitButtonId;
|
||||
$(function() {
|
||||
uploadForm = $("#'.$id.'").closest("form");
|
||||
formId = uploadForm.attr("id");
|
||||
submitButtonId = uploadForm.find("[type=\'submit\']").attr("id");
|
||||
$("#"+submitButtonId).click(function(e) {
|
||||
if ($("#'.$id.'").val()) {
|
||||
e.preventDefault();
|
||||
setBigUploadSettings();
|
||||
bigUpload.fire();
|
||||
}
|
||||
});
|
||||
});
|
||||
function setBigUploadSettings() {
|
||||
//The id of the file input
|
||||
bigUpload.settings.inputField = "'.$id.'";
|
||||
//The id of the form with the file upload.
|
||||
bigUpload.settings.formId = formId;
|
||||
//The id of the progress bar
|
||||
bigUpload.settings.progressBarField = "'.$id.'-bigUploadProgressBarFilled";
|
||||
//The id of the time remaining field
|
||||
bigUpload.settings.timeRemainingField = "'.$id.'-bigUploadTimeRemaining";
|
||||
//The id of the text response field
|
||||
bigUpload.settings.responseField = "'.$id.'-bigUploadResponse";
|
||||
//The id of the submit button
|
||||
bigUpload.settings.submitButton = submitButtonId;
|
||||
//Color of the background of the progress bar
|
||||
bigUpload.settings.progressBarColor = "#5bb75b";
|
||||
//Color of the background of the progress bar when an error is triggered
|
||||
bigUpload.settings.progressBarColorError = "#da4f49";
|
||||
//Path to the php script for handling the uploads
|
||||
bigUpload.settings.scriptPath = "'.api_get_path(WEB_LIBRARY_JS_PATH).'bigupload/inc/bigUpload.php";
|
||||
//cid Req
|
||||
bigUpload.settings.cidReq = "'.api_get_cidreq().'";
|
||||
//Set the origin upload
|
||||
bigUpload.settings.origin = "'.$origin.'";
|
||||
//The parameters from the upload form
|
||||
bigUpload.settings.formParams = uploadForm.serialize();
|
||||
//Max file size allowed
|
||||
bigUpload.settings.maxFileSize = "'.$maxSize.'";
|
||||
// Message error upload filesize
|
||||
bigUpload.settings.errMessageFileSize = "'.$errorUploadMessage.'";
|
||||
}
|
||||
</script>';
|
||||
|
||||
return $js.$html;
|
||||
}
|
||||
}
|
||||
52
main/inc/lib/formvalidator/Element/Color.php
Normal file
52
main/inc/lib/formvalidator/Element/Color.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Input Color element.
|
||||
*
|
||||
* Class Color
|
||||
*/
|
||||
class Color extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
|
||||
$attributes['type'] = 'color';
|
||||
$attributes['class'] = 'form-control';
|
||||
$attributes['cols-size'] = isset($attributes['cols-size']) ? $attributes['cols-size'] : [2, 1, 9];
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
|
||||
$this->_appendName = true;
|
||||
$this->setType('color');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
return parent::toHtml().<<<JS
|
||||
<script>
|
||||
$(function() {
|
||||
var txtColor = $('#{$this->getAttribute('id')}'),
|
||||
lblColor = txtColor.parent().next();
|
||||
|
||||
lblColor.text(txtColor.val());
|
||||
|
||||
txtColor.on('change', function () {
|
||||
lblColor.text(txtColor.val());
|
||||
})
|
||||
});
|
||||
</script>
|
||||
JS;
|
||||
}
|
||||
}
|
||||
186
main/inc/lib/formvalidator/Element/DatePicker.php
Normal file
186
main/inc/lib/formvalidator/Element/DatePicker.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Form element to select a date.
|
||||
*
|
||||
* Class DatePicker
|
||||
*/
|
||||
class DatePicker extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* @param string $elementName
|
||||
* @param string|array $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
$attributes['class'] = 'form-control';
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_appendName = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML code to display this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
if ($this->_flagFrozen) {
|
||||
return $this->getFrozenHtml();
|
||||
}
|
||||
|
||||
$id = $this->getAttribute('id');
|
||||
$value = $this->getValue();
|
||||
|
||||
if (!empty($value)) {
|
||||
$value = api_format_date($value, DATE_FORMAT_LONG_NO_DAY);
|
||||
}
|
||||
|
||||
return '
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon cursor-pointer">
|
||||
<input '.$this->_getAttrString($this->_attributes).'>
|
||||
</span>
|
||||
<p class="form-control disabled" id="'.$id.'_alt_text">'.$value.'</p>
|
||||
<input class="form-control" type="hidden" id="'.$id.'_alt" value="'.$value.'">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button"
|
||||
title="'.sprintf(get_lang('ResetFieldX'), $this->_label).'">
|
||||
<span class="fa fa-trash text-danger" aria-hidden="true"></span>
|
||||
<span class="sr-only">'.sprintf(get_lang('ResetFieldX'), $this->_label).'</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
'.$this->getElementJS();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$value = substr($value, 0, 16);
|
||||
$this->updateAttributes(
|
||||
[
|
||||
'value' => $value,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $layout
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate($layout)
|
||||
{
|
||||
$size = $this->calculateSize();
|
||||
|
||||
switch ($layout) {
|
||||
case FormValidator::LAYOUT_INLINE:
|
||||
return '
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
|
||||
{element}
|
||||
</div>';
|
||||
case FormValidator::LAYOUT_HORIZONTAL:
|
||||
return '
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} class="col-sm-'.$size[0].' control-label {extra_label_class}" >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
<div class="col-sm-'.$size[1].'">
|
||||
{icon}
|
||||
|
||||
{element}
|
||||
|
||||
<!-- BEGIN label_2 -->
|
||||
<p class="help-block">{label_2}</p>
|
||||
<!-- END label_2 -->
|
||||
|
||||
<!-- BEGIN error -->
|
||||
<span class="help-inline help-block">{error}</span>
|
||||
<!-- END error -->
|
||||
</div>
|
||||
<div class="col-sm-'.$size[2].'">
|
||||
<!-- BEGIN label_3 -->
|
||||
{label_3}
|
||||
<!-- END label_3 -->
|
||||
</div>
|
||||
</div>';
|
||||
case FormValidator::LAYOUT_BOX_NO_LABEL:
|
||||
return '{element}';
|
||||
}
|
||||
|
||||
return '<div class="form-group">
|
||||
<label {label-for}>{label}</label>
|
||||
{element}
|
||||
</div>'
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the necessary javascript for this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getElementJS()
|
||||
{
|
||||
$js = null;
|
||||
$id = $this->getAttribute('id');
|
||||
|
||||
$js .= "<script>
|
||||
$(function() {
|
||||
var txtDate = $('#$id'),
|
||||
inputGroup = txtDate.parents('.input-group'),
|
||||
txtDateAlt = $('#{$id}_alt'),
|
||||
txtDateAltText = $('#{$id}_alt_text');
|
||||
|
||||
txtDate
|
||||
.hide()
|
||||
.datepicker({
|
||||
defaultDate: '".$this->getValue()."',
|
||||
dateFormat: 'yy-mm-dd',
|
||||
altField: '#{$id}_alt',
|
||||
altFormat: \"".get_lang('DateFormatLongNoDayJS')."\",
|
||||
showOn: 'both',
|
||||
buttonImage: '".Display::return_icon('attendance.png', null, [], ICON_SIZE_TINY, true, true)."',
|
||||
buttonImageOnly: true,
|
||||
buttonText: '".get_lang('SelectDate')."',
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
yearRange: 'c-60y:c+5y'
|
||||
})
|
||||
.on('change', function (e) {
|
||||
txtDateAltText.text(txtDateAlt.val());
|
||||
});
|
||||
|
||||
txtDateAltText.on('click', function () {
|
||||
txtDate.datepicker('show');
|
||||
});
|
||||
|
||||
inputGroup
|
||||
.find('button')
|
||||
.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('#$id, #{$id}_alt').val('');
|
||||
$('#{$id}_alt_text').html('');
|
||||
});
|
||||
});
|
||||
</script>";
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
231
main/inc/lib/formvalidator/Element/DateRangePicker.php
Normal file
231
main/inc/lib/formvalidator/Element/DateRangePicker.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Form element to select a range of dates (with popup datepicker).
|
||||
*/
|
||||
class DateRangePicker extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* DateRangePicker constructor.
|
||||
*
|
||||
* @param string $elementName
|
||||
* @param string|array $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
$attributes['class'] = 'form-control';
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_appendName = true;
|
||||
$this->_type = 'date_range_picker';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
$js = $this->getElementJS();
|
||||
|
||||
$this->removeAttribute('format');
|
||||
$this->removeAttribute('timepicker');
|
||||
$this->removeAttribute('validate_format');
|
||||
|
||||
return $js.parent::toHtml();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->updateAttributes(
|
||||
[
|
||||
'value' => $value,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $dateRange
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parseDateRange($dateRange)
|
||||
{
|
||||
$dateRange = Security::remove_XSS($dateRange);
|
||||
$dates = explode('/', $dateRange);
|
||||
$dates = array_map('trim', $dates);
|
||||
$start = isset($dates[0]) ? $dates[0] : '';
|
||||
$end = isset($dates[1]) ? $dates[1] : '';
|
||||
|
||||
$pattern = 'yyyy-MM-dd HH:mm';
|
||||
if ('false' === $this->getAttribute('timePicker') &&
|
||||
false === strpos($this->getAttribute('format'), 'HH:mm')) {
|
||||
$pattern = 'yyyy-MM-dd';
|
||||
}
|
||||
|
||||
$formatter = new IntlDateFormatter(
|
||||
'en',
|
||||
IntlDateFormatter::NONE,
|
||||
IntlDateFormatter::NONE,
|
||||
'UTC',
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
$pattern
|
||||
);
|
||||
$resultStart = $formatter->format($formatter->parse($start));
|
||||
$resultEnd = $formatter->format($formatter->parse($end));
|
||||
|
||||
return [
|
||||
'start' => $resultStart,
|
||||
'end' => $resultEnd,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $dates result of parseDateRange()
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validateDates($dates, $format = null)
|
||||
{
|
||||
if (empty($dates['start']) || empty($dates['end'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$format = $format ? $format : 'Y-m-d H:i';
|
||||
$d = DateTime::createFromFormat($format, $dates['start']);
|
||||
$resultStart = $d && $d->format($format) == $dates['start'];
|
||||
|
||||
$d = DateTime::createFromFormat($format, $dates['end']);
|
||||
$resultEnd = $d && $d->format($format) == $dates['end'];
|
||||
|
||||
if (!$resultStart || !$resultEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $submitValues
|
||||
* @param array $errors
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubmitValue($value, &$submitValues, &$errors)
|
||||
{
|
||||
/** @var DateRangePicker $element */
|
||||
$elementName = $this->getName();
|
||||
$parsedDates = $this->parseDateRange($value);
|
||||
$validateFormat = $this->getAttribute('validate_format');
|
||||
|
||||
if (!$this->validateDates($parsedDates, $validateFormat)) {
|
||||
$errors[$elementName] = get_lang('CheckDates');
|
||||
}
|
||||
$submitValues[$elementName.'_start'] = $parsedDates['start'];
|
||||
$submitValues[$elementName.'_end'] = $parsedDates['end'];
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the necessary javascript for this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getElementJS()
|
||||
{
|
||||
$js = null;
|
||||
$id = $this->getAttribute('id');
|
||||
$dateRange = $this->getAttribute('value');
|
||||
|
||||
$defaultDates = null;
|
||||
if (!empty($dateRange)) {
|
||||
$dates = $this->parseDateRange($dateRange);
|
||||
$defaultDates = "
|
||||
startDate: '".$dates['start']."',
|
||||
endDate: '".$dates['end']."', ";
|
||||
}
|
||||
|
||||
$minDate = null;
|
||||
$minDateValue = Security::remove_XSS($this->getAttribute('minDate'));
|
||||
if (!empty($minDateValue)) {
|
||||
$minDate = "
|
||||
minDate: '{$minDateValue}',
|
||||
";
|
||||
}
|
||||
|
||||
$maxDate = null;
|
||||
$maxDateValue = Security::remove_XSS($this->getAttribute('maxDate'));
|
||||
if (!empty($maxDateValue)) {
|
||||
$maxDate = "
|
||||
maxDate: '{$maxDateValue}',
|
||||
";
|
||||
}
|
||||
|
||||
$format = 'YYYY-MM-DD HH:mm';
|
||||
$formatValue = Security::remove_XSS($this->getAttribute('format'));
|
||||
if (!empty($formatValue)) {
|
||||
$format = $formatValue;
|
||||
}
|
||||
|
||||
$timePicker = 'true';
|
||||
$timePickerValue = Security::remove_XSS($this->getAttribute('timePicker'));
|
||||
if (!empty($timePickerValue)) {
|
||||
$timePicker = 'false';
|
||||
}
|
||||
|
||||
$timeIncrement = FormValidator::getTimepickerIncrement();
|
||||
|
||||
// timeFormat: 'hh:mm'
|
||||
$js .= "<script>
|
||||
$(function() {
|
||||
$('#$id').daterangepicker({
|
||||
timePicker: $timePicker,
|
||||
timePickerIncrement: $timeIncrement,
|
||||
timePicker24Hour: true,
|
||||
$defaultDates
|
||||
$maxDate
|
||||
$minDate
|
||||
ranges: {
|
||||
'".addslashes(get_lang('Today'))."': [moment(), moment()],
|
||||
'".addslashes(get_lang('Yesterday'))."': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
|
||||
'".addslashes(get_lang('ThisMonth'))."': [moment().startOf('month'), moment().endOf('month')],
|
||||
'".addslashes(get_lang('LastMonth'))."': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
|
||||
'".addslashes(get_lang('ThisWeek'))."': [moment().weekday(1), moment().weekday(5)],
|
||||
'".addslashes(get_lang('NextWeek'))."': [moment().weekday(8), moment().weekday(12)]
|
||||
},
|
||||
//showDropdowns : true,
|
||||
|
||||
locale: {
|
||||
separator: ' / ',
|
||||
format: '$format',
|
||||
applyLabel: '".addslashes(get_lang('Ok'))."',
|
||||
cancelLabel: '".addslashes(get_lang('Cancel'))."',
|
||||
fromLabel: '".addslashes(get_lang('From'))."',
|
||||
toLabel: '".addslashes(get_lang('Until'))."',
|
||||
customRangeLabel: '".addslashes(get_lang('CustomRange'))."',
|
||||
}
|
||||
});
|
||||
|
||||
$('#$id').on('change', function() {
|
||||
var myPickedDates = $('#$id').val().split('/');
|
||||
var {$id}_start = myPickedDates[0].trim();
|
||||
var {$id}_end = myPickedDates[1].trim();
|
||||
|
||||
$('input[name={$id}_start]').val({$id}_start);
|
||||
$('input[name={$id}_end]').val({$id}_end);
|
||||
});
|
||||
});
|
||||
</script>";
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
191
main/inc/lib/formvalidator/Element/DateTimePicker.php
Normal file
191
main/inc/lib/formvalidator/Element/DateTimePicker.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Form element to select a date and hour.
|
||||
*/
|
||||
class DateTimePicker extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* DateTimePicker constructor.
|
||||
*
|
||||
* @param string $elementName
|
||||
* @param string|array $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
$attributes['class'] = 'form-control';
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_appendName = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML code to display this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
if ($this->_flagFrozen) {
|
||||
return $this->getFrozenHtml();
|
||||
}
|
||||
|
||||
$id = $this->getAttribute('id');
|
||||
$value = $this->getValue();
|
||||
|
||||
$formattedValue = '';
|
||||
if (!empty($value)) {
|
||||
$formattedValue = api_format_date($value, DATE_TIME_FORMAT_LONG_24H);
|
||||
}
|
||||
|
||||
$label = $this->getLabel();
|
||||
if (is_array($label) && isset($label[0])) {
|
||||
$label = $label[0];
|
||||
}
|
||||
|
||||
$resetFieldX = sprintf(get_lang('ResetFieldX'), $label);
|
||||
|
||||
return '
|
||||
<div class="input-group" id="date_time_wrapper_'.$id.'">
|
||||
<span class="input-group-addon cursor-pointer">
|
||||
<input '.$this->_getAttrString($this->_attributes).'>
|
||||
</span>
|
||||
<p class="form-control disabled" id="'.$id.'_alt_text">'.$formattedValue.'</p>
|
||||
<input class="form-control" type="hidden" id="'.$id.'_alt" value="'.$value.'">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button"
|
||||
title="'.$resetFieldX.'">
|
||||
<span class="fa fa-trash text-danger" aria-hidden="true"></span>
|
||||
<span class="sr-only">'.$resetFieldX.'</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
'.$this->getElementJS();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$value = substr($value, 0, 16);
|
||||
$this->updateAttributes(['value' => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $layout
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate($layout)
|
||||
{
|
||||
$size = $this->calculateSize();
|
||||
|
||||
switch ($layout) {
|
||||
case FormValidator::LAYOUT_INLINE:
|
||||
return '
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
|
||||
{element}
|
||||
</div>';
|
||||
case FormValidator::LAYOUT_HORIZONTAL:
|
||||
return '
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} class="col-sm-'.$size[0].' control-label {extra_label_class}" >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
<div class="col-sm-'.$size[1].'">
|
||||
{icon}
|
||||
|
||||
{element}
|
||||
|
||||
<!-- BEGIN label_2 -->
|
||||
<p class="help-block">{label_2}</p>
|
||||
<!-- END label_2 -->
|
||||
|
||||
<!-- BEGIN error -->
|
||||
<span class="help-inline help-block">{error}</span>
|
||||
<!-- END error -->
|
||||
</div>
|
||||
<div class="col-sm-'.$size[2].'">
|
||||
<!-- BEGIN label_3 -->
|
||||
{label_3}
|
||||
<!-- END label_3 -->
|
||||
</div>
|
||||
</div>';
|
||||
case FormValidator::LAYOUT_BOX_NO_LABEL:
|
||||
return '{element}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the necessary javascript for this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getElementJS()
|
||||
{
|
||||
$timeIncrement = FormValidator::getTimepickerIncrement();
|
||||
|
||||
$js = null;
|
||||
$id = $this->getAttribute('id');
|
||||
//timeFormat: 'hh:mm'
|
||||
$js .= "<script>
|
||||
$(function() {
|
||||
var txtDateTime = $('#$id'),
|
||||
inputGroup = txtDateTime.parents('.input-group'),
|
||||
txtDateTimeAlt = $('#{$id}_alt'),
|
||||
txtDateTimeAltText = $('#{$id}_alt_text');
|
||||
|
||||
txtDateTime
|
||||
.hide()
|
||||
.datetimepicker({
|
||||
defaultDate: '".$this->getValue()."',
|
||||
dateFormat: 'yy-mm-dd',
|
||||
controlType: 'select',
|
||||
oneLine: true,
|
||||
stepMinute: $timeIncrement,
|
||||
timeFormat: 'HH:mm',
|
||||
altField: '#{$id}_alt',
|
||||
altFormat: \"".get_lang('DateFormatLongNoDayJS')."\",
|
||||
altTimeFormat: \"".get_lang('TimeFormatNoSecJS')."\",
|
||||
altSeparator: \" ".get_lang('AtTime')." \",
|
||||
altFieldTimeOnly: false,
|
||||
showOn: 'both',
|
||||
buttonImage: '".Display::return_icon('attendance.png', null, [], ICON_SIZE_TINY, true, true)."',
|
||||
buttonImageOnly: true,
|
||||
buttonText: '".get_lang('SelectDate')."',
|
||||
changeMonth: true,
|
||||
changeYear: true
|
||||
})
|
||||
.on('change', function (e) {
|
||||
txtDateTimeAltText.text(txtDateTimeAlt.val());
|
||||
});
|
||||
|
||||
txtDateTimeAltText.on('click', function () {
|
||||
txtDateTime.datepicker('show');
|
||||
});
|
||||
|
||||
inputGroup
|
||||
.find('button')
|
||||
.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('#$id, #{$id}_alt').val('');
|
||||
$('#{$id}_alt_text').html('');
|
||||
});
|
||||
});
|
||||
</script>";
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
239
main/inc/lib/formvalidator/Element/DateTimeRangePicker.php
Normal file
239
main/inc/lib/formvalidator/Element/DateTimeRangePicker.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Form element to select a date.
|
||||
*
|
||||
* Class DatePicker
|
||||
*/
|
||||
class DateTimeRangePicker extends DateRangePicker
|
||||
{
|
||||
/**
|
||||
* HTML code to display this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
if ($this->_flagFrozen) {
|
||||
return $this->getFrozenHtml();
|
||||
}
|
||||
|
||||
$id = $this->getAttribute('id');
|
||||
$dateRange = $this->getValue();
|
||||
|
||||
$value = '';
|
||||
if (!empty($dateRange)) {
|
||||
$dates = $this->parseDateRange($dateRange);
|
||||
$value = api_format_date($dates['date'], DATE_FORMAT_LONG_NO_DAY);
|
||||
}
|
||||
|
||||
return '
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon cursor-pointer">
|
||||
<input '.$this->_getAttrString($this->_attributes).'>
|
||||
</span>
|
||||
<p class="form-control disabled" id="'.$id.'_alt_text">'.$value.'</p>
|
||||
<input class="form-control" type="hidden" id="'.$id.'_alt" value="'.$value.'">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button"
|
||||
title="'.sprintf(get_lang('ResetFieldX'), $this->_label).'">
|
||||
<span class="fa fa-trash text-danger" aria-hidden="true"></span>
|
||||
<span class="sr-only">'.sprintf(get_lang('ResetFieldX'), $this->_label).'</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
'.$this->getElementJS();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $layout
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate($layout)
|
||||
{
|
||||
$size = $this->calculateSize();
|
||||
$id = $this->getAttribute('id');
|
||||
|
||||
switch ($layout) {
|
||||
case FormValidator::LAYOUT_INLINE:
|
||||
return '
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
{element}
|
||||
</div>';
|
||||
break;
|
||||
case FormValidator::LAYOUT_HORIZONTAL:
|
||||
return '
|
||||
<span id="'.$id.'_date_time_wrapper">
|
||||
<div class="form-group {error_class}">
|
||||
<label {label-for} class="col-sm-'.$size[0].' control-label" >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
{label}
|
||||
</label>
|
||||
<div class="col-sm-'.$size[1].'">
|
||||
{icon}
|
||||
{element}
|
||||
|
||||
<!-- BEGIN label_2 -->
|
||||
<p class="help-block">{label_2}</p>
|
||||
<!-- END label_2 -->
|
||||
|
||||
<!-- BEGIN error -->
|
||||
<span class="help-inline help-block">{error}</span>
|
||||
<!-- END error -->
|
||||
</div>
|
||||
<div class="col-sm-'.$size[2].'">
|
||||
<!-- BEGIN label_3 -->
|
||||
{label_3}
|
||||
<!-- END label_3 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group {error_class}">
|
||||
<label class="col-sm-'.$size[0].' control-label" >
|
||||
<!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
|
||||
'.get_lang('Hour').'
|
||||
</label>
|
||||
<div class="col-sm-'.$size[1].'">
|
||||
<div class="input-group">
|
||||
<p id="'.$id.'_time_range">
|
||||
<input type="text" id="'.$id.'_time_range_start" name="'.$id.'_time_range_start" class="time start" autocomplete="off">
|
||||
'.get_lang('To').'
|
||||
<input type="text" id="'.$id.'_time_range_end" name="'.$id.'_time_range_end" class="time end " autocomplete="off">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
';
|
||||
break;
|
||||
case FormValidator::LAYOUT_BOX_NO_LABEL:
|
||||
return '
|
||||
<label {label-for}>{label}</label>
|
||||
<div class="input-group">
|
||||
|
||||
{icon}
|
||||
{element}
|
||||
</div>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $dateRange
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parseDateRange($dateRange)
|
||||
{
|
||||
$dateRange = Security::remove_XSS($dateRange);
|
||||
$dates = explode('@@', $dateRange);
|
||||
$dates = array_map('trim', $dates);
|
||||
$start = isset($dates[0]) ? $dates[0] : '';
|
||||
$end = isset($dates[1]) ? $dates[1] : '';
|
||||
|
||||
$date = substr($start, 0, 10);
|
||||
$start = isset($dates[0]) ? $dates[0] : '';
|
||||
//$start = substr($start, 11, strlen($start));
|
||||
//$end = substr($end, 11, strlen($end));
|
||||
|
||||
return [
|
||||
'date' => $date,
|
||||
'start_time' => $start,
|
||||
'end_time' => $end,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->updateAttributes(
|
||||
[
|
||||
'value' => $value,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the necessary javascript for this datepicker.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getElementJS()
|
||||
{
|
||||
$js = null;
|
||||
$id = $this->getAttribute('id');
|
||||
|
||||
$dateRange = $this->getValue();
|
||||
|
||||
$defaultDate = '';
|
||||
$startTime = '';
|
||||
$endTime = '';
|
||||
if (!empty($dateRange)) {
|
||||
$dates = $this->parseDateRange($dateRange);
|
||||
$defaultDate = $dates['date'];
|
||||
$startTime = $dates['start_time'];
|
||||
$endTime = $dates['end_time'];
|
||||
}
|
||||
|
||||
$js .= "<script>
|
||||
$(function() {
|
||||
var txtDate = $('#$id'),
|
||||
inputGroup = txtDate.parents('.input-group'),
|
||||
txtDateAlt = $('#{$id}_alt'),
|
||||
txtDateAltText = $('#{$id}_alt_text');
|
||||
|
||||
txtDate
|
||||
.hide()
|
||||
.datepicker({
|
||||
defaultDate: '".$defaultDate."',
|
||||
dateFormat: 'yy-mm-dd',
|
||||
altField: '#{$id}_alt',
|
||||
altFormat: \"".get_lang('DateFormatLongNoDayJS')."\",
|
||||
showOn: 'both',
|
||||
buttonImage: '".Display::return_icon('attendance.png', null, [], ICON_SIZE_TINY, true, true)."',
|
||||
buttonImageOnly: true,
|
||||
buttonText: '".get_lang('SelectDate')."',
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
yearRange: 'c-60y:c+5y'
|
||||
})
|
||||
.on('change', function (e) {
|
||||
txtDateAltText.text(txtDateAlt.val());
|
||||
});
|
||||
|
||||
txtDateAltText.on('click', function () {
|
||||
txtDate.datepicker('show');
|
||||
});
|
||||
|
||||
inputGroup
|
||||
.find('button')
|
||||
.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#$id, #{$id}_alt').val('');
|
||||
$('#{$id}_alt_text').html('');
|
||||
});
|
||||
|
||||
$('#".$id."_time_range .time').timepicker({
|
||||
'showDuration': true,
|
||||
'timeFormat': 'H:i:s',
|
||||
'scrollDefault': 'now',
|
||||
});
|
||||
|
||||
$('#".$id."_time_range_start').timepicker('setTime', new Date('".$startTime."'));
|
||||
$('#".$id."_time_range_end').timepicker('setTime', new Date('".$endTime."'));
|
||||
|
||||
var timeOnlyExampleEl = document.getElementById('".$id."_time_range');
|
||||
var timeOnlyDatepair = new Datepair(timeOnlyExampleEl);
|
||||
});
|
||||
</script>";
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
84
main/inc/lib/formvalidator/Element/FloatNumber.php
Normal file
84
main/inc/lib/formvalidator/Element/FloatNumber.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Float element.
|
||||
*
|
||||
* Accepts values like 3.1415 and 3,1415 (its processed and converted to 3.1415)
|
||||
*
|
||||
* Class Float
|
||||
*/
|
||||
class FloatNumber extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
|
||||
$attributes['type'] = 'float';
|
||||
$attributes['class'] = 'form-control';
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_appendName = true;
|
||||
$this->setType('float');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$value = api_float_val($value);
|
||||
$this->updateAttributes(
|
||||
[
|
||||
'value' => $value,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
$value = $this->getAttribute('value');
|
||||
$value = api_float_val($value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param array $submitValues
|
||||
* @param array $errors
|
||||
*/
|
||||
public function getSubmitValue($value, &$submitValues, &$errors)
|
||||
{
|
||||
$value = api_float_val($value);
|
||||
$elementName = $this->getName();
|
||||
$submitValues[$elementName] = $value;
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* We check the options and return only the values that _could_ have been
|
||||
* selected. We also return a scalar value if select is not "multiple".
|
||||
*/
|
||||
public function exportValue(&$submitValues, $assoc = false)
|
||||
{
|
||||
$value = $this->_findValue($submitValues);
|
||||
$value = api_float_val($value);
|
||||
if (!$value) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return $this->_prepareValue($value, $assoc);
|
||||
}
|
||||
}
|
||||
119
main/inc/lib/formvalidator/Element/HtmlEditor.php
Normal file
119
main/inc/lib/formvalidator/Element/HtmlEditor.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\CoreBundle\Component\Editor\CkEditor\CkEditor;
|
||||
use Chamilo\CoreBundle\Component\HTMLPurifier\Filter\RemoveOnAttributes;
|
||||
|
||||
/**
|
||||
* A html editor field to use with QuickForm.
|
||||
*/
|
||||
class HtmlEditor extends HTML_QuickForm_textarea
|
||||
{
|
||||
/** @var \Chamilo\CoreBundle\Component\Editor\Editor */
|
||||
public $editor;
|
||||
|
||||
/**
|
||||
* Full page.
|
||||
*/
|
||||
public $fullPage;
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|array $label HTML editor label
|
||||
* @param array $attributes Attributes for the textarea
|
||||
* @param array $config optional configuration settings for the online editor
|
||||
*/
|
||||
public function __construct(
|
||||
$name,
|
||||
$label = null,
|
||||
$attributes = [],
|
||||
$config = []
|
||||
) {
|
||||
if (empty($name)) {
|
||||
throw new \Exception('Name is required');
|
||||
}
|
||||
|
||||
parent::__construct($name, $label, $attributes);
|
||||
$id = $this->getAttribute('id');
|
||||
$this->_persistantFreeze = true;
|
||||
$this->_type = 'html_editor';
|
||||
$editor = new CkEditor();
|
||||
if ($editor) {
|
||||
$this->editor = $editor;
|
||||
$this->editor->setTextareaId($id);
|
||||
$this->editor->setName($name);
|
||||
$this->editor->processConfig($config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the HTML editor in HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
if ($this->editor) {
|
||||
if ($this->editor->getConfigAttribute('fullPage')) {
|
||||
$value = $this->getValue();
|
||||
if (strlen(trim($value)) == 0) {
|
||||
// TODO: To be considered whether here to add
|
||||
// language and character set declarations.
|
||||
$value = '<!DOCTYPE html><html><head><title></title></head><body></body></html>';
|
||||
$this->setValue($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isFrozen()) {
|
||||
return $this->getFrozenHtml();
|
||||
} else {
|
||||
$styleCss = $this->editor->getConfigAttribute('style');
|
||||
$style = false;
|
||||
if ($styleCss) {
|
||||
$style = true;
|
||||
}
|
||||
|
||||
return $this->buildEditor($style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the html area content in HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFrozenHtml()
|
||||
{
|
||||
return Security::remove_XSS($this->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function buildEditor($style = false)
|
||||
{
|
||||
$result = '';
|
||||
if ($this->editor) {
|
||||
$value = $this->getCleanValue();
|
||||
|
||||
$this->editor->setName($this->getName());
|
||||
if ($style === true) {
|
||||
$result = $this->editor->createHtmlStyle($value);
|
||||
} else {
|
||||
$result = $this->editor->createHtml($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getValue(): ?string
|
||||
{
|
||||
return RemoveOnAttributes::filter($this->_value);
|
||||
}
|
||||
}
|
||||
31
main/inc/lib/formvalidator/Element/InternalUrl.php
Normal file
31
main/inc/lib/formvalidator/Element/InternalUrl.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* InternalUrl element (URL without the domain as prefix).
|
||||
*
|
||||
* Class InternalUrl
|
||||
*/
|
||||
class InternalUrl extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* InternalUrl constructor.
|
||||
*
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
|
||||
$attributes['type'] = 'text';
|
||||
$attributes['class'] = 'form-control';
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
|
||||
$this->setType('text');
|
||||
}
|
||||
}
|
||||
28
main/inc/lib/formvalidator/Element/Number.php
Normal file
28
main/inc/lib/formvalidator/Element/Number.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Number element.
|
||||
*
|
||||
* Class Number
|
||||
*/
|
||||
class Number extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
|
||||
$attributes['type'] = 'number';
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
$this->_appendName = true;
|
||||
$this->setType('number');
|
||||
}
|
||||
}
|
||||
212
main/inc/lib/formvalidator/Element/SelectAjax.php
Normal file
212
main/inc/lib/formvalidator/Element/SelectAjax.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* A drop down list with all languages to use with QuickForm.
|
||||
*/
|
||||
class SelectAjax extends HTML_QuickForm_select
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct($elementName, $elementLabel = '', $options = null, $attributes = null)
|
||||
{
|
||||
parent::__construct($elementName, $elementLabel, $options, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ajax call must contain an array of id and text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
$iso = api_get_language_isocode(api_get_interface_language());
|
||||
$dropdownParent = $this->getAttribute('dropdownParent');
|
||||
$dropdownParentCondition = $dropdownParent ? "dropdownParent: '$dropdownParent'," : '';
|
||||
$formatResult = $this->getAttribute('formatResult');
|
||||
$formatSelection = $this->getAttribute('formatSelection');
|
||||
$formatCondition = '';
|
||||
|
||||
if (!empty($formatResult)) {
|
||||
$formatCondition .= ',
|
||||
templateResult : '.$formatResult;
|
||||
}
|
||||
|
||||
if (!empty($formatSelection)) {
|
||||
$formatCondition .= ',
|
||||
templateSelection : '.$formatSelection;
|
||||
}
|
||||
|
||||
$width = 'element';
|
||||
$givenWidth = '100%';
|
||||
if (!empty($givenWidth)) {
|
||||
$width = $givenWidth;
|
||||
}
|
||||
|
||||
//Get the minimumInputLength for select2
|
||||
$minimumInputLength = $this->getAttribute('minimumInputLength') > 3 ?
|
||||
$this->getAttribute('minimumInputLength') : 3
|
||||
;
|
||||
|
||||
$plHolder = $this->getAttribute('placeholder');
|
||||
if (empty($plHolder)) {
|
||||
$plHolder = preg_replace("/'/", "\\'", get_lang('SelectAnOption'));
|
||||
}
|
||||
|
||||
$id = $this->getAttribute('id');
|
||||
|
||||
if (empty($id)) {
|
||||
$id = $this->getAttribute('name');
|
||||
$this->setAttribute('id', $id);
|
||||
}
|
||||
// URL must return ajax json_encode arrady [items => [['id'=>1, 'text'='content']]
|
||||
$url = $this->getAttribute('url');
|
||||
|
||||
if (!$url) {
|
||||
$url = $this->getAttribute('url_function');
|
||||
} else {
|
||||
$url = "'$url'";
|
||||
}
|
||||
|
||||
$tagsAttr = $this->getAttribute('tags');
|
||||
$multipleAttr = $this->getAttribute('multiple');
|
||||
|
||||
$tags = !empty($tagsAttr) ? (bool) $tagsAttr : false;
|
||||
$tags = $tags ? 'true' : 'false';
|
||||
|
||||
$multiple = !empty($multipleAttr) ? (bool) $multipleAttr : false;
|
||||
$multiple = $multiple ? 'true' : 'false';
|
||||
|
||||
$max = $this->getAttribute('maximumSelectionLength');
|
||||
$max = !empty($max) ? "maximumSelectionLength: $max, " : '';
|
||||
|
||||
// wait XX milliseconds before triggering the request
|
||||
$delay = ((int) $this->getAttribute('delay')) ?: 1000;
|
||||
|
||||
$html = <<<JS
|
||||
<script>
|
||||
$(function(){
|
||||
$('#{$this->getAttribute('id')}').select2({
|
||||
language: '$iso',
|
||||
placeholder: '$plHolder',
|
||||
allowClear: true,
|
||||
width: '$width',
|
||||
minimumInputLength: '$minimumInputLength',
|
||||
tags: $tags,
|
||||
$dropdownParentCondition
|
||||
ajax: {
|
||||
url: $url,
|
||||
delay: $delay,
|
||||
dataType: 'json',
|
||||
data: function(params) {
|
||||
return {
|
||||
q: params.term, // search term
|
||||
page_limit: 10,
|
||||
};
|
||||
},
|
||||
processResults: function (data, page) {
|
||||
// Parse the results into the format expected by Select2
|
||||
if (data.items) {
|
||||
return {
|
||||
results: data.items
|
||||
};
|
||||
}
|
||||
return {
|
||||
results: ''
|
||||
};
|
||||
}
|
||||
}
|
||||
$formatCondition
|
||||
});
|
||||
});
|
||||
</script>
|
||||
JS;
|
||||
|
||||
$this->removeAttribute('formatResult');
|
||||
$this->removeAttribute('formatSelection');
|
||||
$this->removeAttribute('minimumInputLength');
|
||||
$this->removeAttribute('maximumSelectionLength');
|
||||
$this->removeAttribute('tags');
|
||||
$this->removeAttribute('placeholder');
|
||||
$this->removeAttribute('class');
|
||||
$this->removeAttribute('url');
|
||||
$this->removeAttribute('url_function');
|
||||
$this->removeAttribute('dropdownParent');
|
||||
$this->setAttribute('style', 'width: 100%;');
|
||||
|
||||
return parent::toHtml().$html;
|
||||
}
|
||||
|
||||
/**
|
||||
* We check the options and return only the values that _could_ have been
|
||||
* selected. We also return a scalar value if select is not "multiple".
|
||||
*/
|
||||
public function exportValue(&$submitValues, $assoc = false)
|
||||
{
|
||||
$value = $this->_findValue($submitValues);
|
||||
|
||||
if (!$value) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return $this->_prepareValue($value, $assoc);
|
||||
}
|
||||
|
||||
public static function templateResultForUsersInCourse(): string
|
||||
{
|
||||
return "function (state) {
|
||||
if (state.loading) {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
var \$container = \$(
|
||||
'<div class=\"select2-result-user clearfix\">' +
|
||||
'<div class=\"select2-result-user__avatar pull-left\">' +
|
||||
'<img>' +
|
||||
'</div>' +
|
||||
'<div class=\"select2-result-user__info pull-left\">' +
|
||||
'<div class=\"select2-result-user__name\"></div>' +
|
||||
'<div class=\"select2-result-user__username small\"></div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
\$container.find('.select2-result-user__avatar img')
|
||||
.prop({ 'src': state.avatarUrl, 'alt': state.username })
|
||||
.css({ 'width': '40px', 'height': '40px' });
|
||||
\$container.find('.select2-result-user__info').css({ 'paddingLeft': '6px' });
|
||||
\$container.find('.select2-result-user__name').text(state.completeName);
|
||||
\$container.find('.select2-result-user__username').text(state.username);
|
||||
|
||||
return \$container;
|
||||
}";
|
||||
}
|
||||
|
||||
public static function templateSelectionForUsersInCourse(): string
|
||||
{
|
||||
return "function (state) {
|
||||
if (!state.id) {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
if (!state.avatarUrl) {
|
||||
var avatarUrl = $(state.element).data('avatarurl');
|
||||
var username = $(state.element).data('username');
|
||||
|
||||
state.avatarUrl = avatarUrl;
|
||||
state.username = username;
|
||||
state.completeName = state.text;
|
||||
}
|
||||
|
||||
var \$container = \$('<span><img> ' + state.completeName + '</span>');
|
||||
|
||||
\$container.find('img')
|
||||
.prop({ 'src': state.avatarUrl, 'alt': state.username })
|
||||
.css({ 'width': '20px', 'height': '20px' });
|
||||
|
||||
return \$container;
|
||||
}";
|
||||
}
|
||||
}
|
||||
38
main/inc/lib/formvalidator/Element/SelectLanguage.php
Normal file
38
main/inc/lib/formvalidator/Element/SelectLanguage.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class SelectLanguage
|
||||
* A dropdownlist with all languages to use with QuickForm.
|
||||
*/
|
||||
class SelectLanguage extends HTML_QuickForm_select
|
||||
{
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
$elementName = null,
|
||||
$elementLabel = null,
|
||||
$options = [],
|
||||
$attributes = []
|
||||
) {
|
||||
parent::__construct($elementName, $elementLabel, $options, $attributes);
|
||||
|
||||
$default = isset($attributes['set_custom_default']) ? $attributes['set_custom_default'] : false;
|
||||
|
||||
// Get all languages
|
||||
$languages = api_get_languages();
|
||||
foreach ($languages['name'] as $index => $name) {
|
||||
if (!empty($default)) {
|
||||
$defaultValue = $default;
|
||||
} else {
|
||||
$defaultValue = api_get_setting('platformLanguage');
|
||||
}
|
||||
if ($languages['folder'][$index] == $defaultValue) {
|
||||
$this->addOption($name, $languages['folder'][$index], ['selected' => 'selected']);
|
||||
} else {
|
||||
$this->addOption($name, $languages['folder'][$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
main/inc/lib/formvalidator/Element/SelectTheme.php
Normal file
28
main/inc/lib/formvalidator/Element/SelectTheme.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* A dropdownlist with all themes to use with QuickForm.
|
||||
*/
|
||||
class SelectTheme extends HTML_QuickForm_select
|
||||
{
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct(
|
||||
$elementName = null,
|
||||
$elementLabel = null,
|
||||
$options = null,
|
||||
$attributes = null
|
||||
) {
|
||||
parent::__construct($elementName, $elementLabel, $options, $attributes);
|
||||
// Get all languages
|
||||
$themes = api_get_themes();
|
||||
$this->_options = [];
|
||||
$this->_values = [];
|
||||
$this->addOption('--', ''); // no theme select
|
||||
foreach ($themes as $themeValue => $themeName) {
|
||||
$this->addOption($themeName, $themeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
main/inc/lib/formvalidator/Element/Url.php
Normal file
31
main/inc/lib/formvalidator/Element/Url.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Url element.
|
||||
*
|
||||
* Class Url
|
||||
*/
|
||||
class Url extends HTML_QuickForm_text
|
||||
{
|
||||
/**
|
||||
* Url constructor.
|
||||
*
|
||||
* @param string $elementName
|
||||
* @param string $elementLabel
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($elementName = null, $elementLabel = null, $attributes = null)
|
||||
{
|
||||
if (!isset($attributes['id'])) {
|
||||
$attributes['id'] = $elementName;
|
||||
}
|
||||
|
||||
$attributes['type'] = 'url';
|
||||
$attributes['class'] = 'form-control';
|
||||
|
||||
parent::__construct($elementName, $elementLabel, $attributes);
|
||||
|
||||
$this->setType('url');
|
||||
}
|
||||
}
|
||||
87
main/inc/lib/formvalidator/Element/UserAvatar.php
Normal file
87
main/inc/lib/formvalidator/Element/UserAvatar.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
use Chamilo\UserBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* Class UserAvatar
|
||||
* FormValidator element to add an user avatar wrapping a hidden input with its user ID
|
||||
* Is necessary set an instance of Chamilo\UserBundle\Entity\User as value. The exported value is the user ID.
|
||||
*/
|
||||
class UserAvatar extends HTML_QuickForm_input
|
||||
{
|
||||
/** @var User */
|
||||
private $user = null;
|
||||
private $imageSize = 'small';
|
||||
private $subTitle = '';
|
||||
|
||||
/**
|
||||
* UserAvatar constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $label
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($name, $label, $attributes = [])
|
||||
{
|
||||
if (isset($attributes['image_size'])) {
|
||||
$this->imageSize = $attributes['image_size'];
|
||||
unset($attributes['image_size']);
|
||||
}
|
||||
|
||||
if (isset($attributes['sub_title'])) {
|
||||
$this->subTitle = $attributes['sub_title'];
|
||||
unset($attributes['sub_title']);
|
||||
}
|
||||
|
||||
parent::__construct($name, $label, $attributes);
|
||||
|
||||
$this->setType('hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->user = !is_a($value, 'Chamilo\UserBundle\Entity\User')
|
||||
? UserManager::getManager()->find($value)
|
||||
: $value;
|
||||
|
||||
parent::setValue($this->user->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toHtml()
|
||||
{
|
||||
if (!$this->user) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$userInfo = api_get_user_info($this->user->getId());
|
||||
$userPicture = isset($userInfo["avatar_{$this->imageSize}"])
|
||||
? $userInfo["avatar_{$this->imageSize}"]
|
||||
: $userInfo["avatar"];
|
||||
|
||||
if (!$this->subTitle) {
|
||||
$this->subTitle = $this->user->getUsername();
|
||||
}
|
||||
|
||||
$html = parent::toHtml();
|
||||
$html .= '
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<img src="'.$userPicture.'" alt="'.UserManager::formatUserFullName($this->user).'">
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">'.UserManager::formatUserFullName($this->user).'</h4>
|
||||
'.$this->subTitle.'
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
6
main/inc/lib/formvalidator/Element/index.html
Normal file
6
main/inc/lib/formvalidator/Element/index.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
2112
main/inc/lib/formvalidator/FormValidator.class.php
Normal file
2112
main/inc/lib/formvalidator/FormValidator.class.php
Normal file
File diff suppressed because it is too large
Load Diff
31
main/inc/lib/formvalidator/Rule/CompareDateTimeText.php
Normal file
31
main/inc/lib/formvalidator/Rule/CompareDateTimeText.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* QuickForm rule to compare 2 dates.
|
||||
*/
|
||||
class HTML_QuickForm_Rule_CompareDateTimeText extends HTML_QuickForm_Rule_Compare
|
||||
{
|
||||
/**
|
||||
* Validate 2 dates.
|
||||
*
|
||||
* @param string $operator The operator to use (default '==')
|
||||
*
|
||||
* @return bool True if the 2 given dates match the operator
|
||||
*/
|
||||
public function validate($values, $operator = null)
|
||||
{
|
||||
$datetime1 = api_strtotime($values[0]);
|
||||
$datetime2 = api_strtotime($values[1]);
|
||||
|
||||
if (strpos($operator, 'allow_empty') !== false) {
|
||||
$operator = str_replace('allow_empty', '', $operator);
|
||||
if (!$datetime2 || empty($datetime2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$result = parent::validate([$datetime1, $datetime2], $operator);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
35
main/inc/lib/formvalidator/Rule/CompareFields.php
Normal file
35
main/inc/lib/formvalidator/Rule/CompareFields.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* QuickForm rule to check a date.
|
||||
*/
|
||||
class HTML_QuickForm_Compare_Fields extends HTML_QuickForm_Rule_Compare
|
||||
{
|
||||
/**
|
||||
* Function to check an array of fields.
|
||||
*
|
||||
* @param array of field names
|
||||
* @param string operator ==, >=, etc
|
||||
* @param string the value to compare
|
||||
*
|
||||
* @return bool True if date is valid
|
||||
*/
|
||||
public function validate($values = [], $operator_and_max_value = null)
|
||||
{
|
||||
if (is_array($values) && !empty($values) && !empty($operator_and_max_value)) {
|
||||
$final_value = 0;
|
||||
foreach ($values as $value) {
|
||||
$value = (float) $value;
|
||||
$final_value += $value;
|
||||
}
|
||||
$params = explode('@', $operator_and_max_value);
|
||||
$operator = $params[0];
|
||||
$max_value = $params[1];
|
||||
|
||||
return parent::validate([$final_value, $max_value], $operator);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
24
main/inc/lib/formvalidator/Rule/Date.php
Normal file
24
main/inc/lib/formvalidator/Rule/Date.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
/** @author Bart Mollet, Julio Montoya */
|
||||
|
||||
/**
|
||||
* Class HTML_QuickForm_Rule_Date.
|
||||
*/
|
||||
class HTML_QuickForm_Rule_Date extends HTML_QuickForm_Rule
|
||||
{
|
||||
/**
|
||||
* Check a date.
|
||||
*
|
||||
* @see HTML_QuickForm_Rule
|
||||
*
|
||||
* @param string $date example 2014-04-30
|
||||
* @param array $options
|
||||
*
|
||||
* @return bool True if date is valid
|
||||
*/
|
||||
public function validate($date, $options)
|
||||
{
|
||||
return api_is_valid_date($date, 'Y-m-d');
|
||||
}
|
||||
}
|
||||
23
main/inc/lib/formvalidator/Rule/DateCompare.php
Normal file
23
main/inc/lib/formvalidator/Rule/DateCompare.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class HTML_QuickForm_Rule_DateCompare.
|
||||
*
|
||||
* @author Julio Montoya
|
||||
*/
|
||||
class HTML_QuickForm_Rule_DateCompare extends HTML_QuickForm_Rule_Compare
|
||||
{
|
||||
/**
|
||||
* Validate 2 dates.
|
||||
*
|
||||
* @param array $values array with the 2 dates
|
||||
* @param $operator
|
||||
*
|
||||
* @return bool true if the 2 given dates match the operator
|
||||
*/
|
||||
public function validate($values, $operator = null)
|
||||
{
|
||||
return api_strtotime($values[0]) < api_strtotime($values[1]);
|
||||
}
|
||||
}
|
||||
25
main/inc/lib/formvalidator/Rule/DateTimeRule.php
Normal file
25
main/inc/lib/formvalidator/Rule/DateTimeRule.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/**
|
||||
* Class DateTimeRule.
|
||||
*
|
||||
* @author Julio Montoya
|
||||
*/
|
||||
class DateTimeRule extends HTML_QuickForm_Rule
|
||||
{
|
||||
/**
|
||||
* Check a date.
|
||||
*
|
||||
* @param string $date example 2014-04-30 18:00
|
||||
* @param array $options
|
||||
*
|
||||
* @return bool True if date is valid
|
||||
*
|
||||
* @see HTML_QuickForm_Rule
|
||||
*/
|
||||
public function validate($date, $options)
|
||||
{
|
||||
return api_is_valid_date($date, 'Y-m-d H:i');
|
||||
}
|
||||
}
|
||||
26
main/inc/lib/formvalidator/Rule/FileName.php
Normal file
26
main/inc/lib/formvalidator/Rule/FileName.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/* For licensing terms, see /license.txt */
|
||||
|
||||
/** @author Julio Montoya */
|
||||
|
||||
/**
|
||||
* Class HTML_QuickForm_Rule_FileName.
|
||||
*/
|
||||
class HTML_QuickForm_Rule_FileName extends HTML_QuickForm_Rule
|
||||
{
|
||||
/**
|
||||
* @param $value array Uploaded file info (from $_FILES)
|
||||
* @param null $options
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($value, $options = null)
|
||||
{
|
||||
if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
|
||||
(!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
|
||||
return is_uploaded_file($elementValue['tmp_name']);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user