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

pull/2487/head
Yannick Warnier 8 years ago
commit 77e13fb5c3
  1. 21
      main/announcements/announcements.php
  2. 3
      main/calendar/agenda.php
  3. 1
      main/course_info/download.php
  4. 2
      main/cron/user_import/client.php
  5. 15
      main/document/create_document.php
  6. 5
      main/document/downloadfolder.inc.php
  7. 6
      main/inc/email_editor.php
  8. 5
      main/inc/global_error_message.inc.php
  9. 15
      main/inc/introductionSection.inc.php
  10. 10
      main/inc/lib/AnnouncementEmail.php
  11. 54
      main/inc/lib/AnnouncementManager.php
  12. 35
      main/inc/lib/MoodleImport.php
  13. 3
      main/inc/lib/api.lib.php
  14. 32
      main/inc/lib/tracking.lib.php
  15. 3
      main/inc/local.inc.php
  16. 3
      main/install/index.php
  17. 7
      main/install/install.lib.php
  18. 14
      plugin/vchamilo/README.md
  19. 3
      plugin/vchamilo/install.php
  20. 2
      plugin/vchamilo/lib/VChamiloPlugin.php
  21. 44
      plugin/vchamilo/lib/Virtual.php
  22. 1
      plugin/vchamilo/vcron.php
  23. 10
      plugin/vchamilo/views/editinstance_form.php
  24. 28
      plugin/vchamilo/views/import.php
  25. 19
      src/Chamilo/CourseBundle/Component/CourseCopy/CourseArchiver.php

@ -86,7 +86,6 @@ $searchFormToString = '';
switch ($action) {
case 'move':
/* Move announcement up/down */
if (!empty($_GET['down'])) {
$thisAnnouncementId = intval($_GET['down']);
$sortDirection = "DESC";
@ -105,15 +104,15 @@ switch ($action) {
$announcementInfo = AnnouncementManager::get_by_id($course_id, $thisAnnouncementId);
$sql = "SELECT DISTINCT announcement.id, announcement.display_order
FROM $tbl_announcement announcement,
$tbl_item_property itemproperty
WHERE
announcement.c_id = $course_id AND
itemproperty.c_id = $course_id AND
itemproperty.ref = announcement.id AND
itemproperty.tool = '".TOOL_ANNOUNCEMENT."' AND
itemproperty.visibility <> 2
ORDER BY display_order $sortDirection";
FROM $tbl_announcement announcement,
$tbl_item_property itemproperty
WHERE
announcement.c_id = $course_id AND
itemproperty.c_id = $course_id AND
itemproperty.ref = announcement.id AND
itemproperty.tool = '".TOOL_ANNOUNCEMENT."' AND
itemproperty.visibility <> 2
ORDER BY display_order $sortDirection";
$result = Database::query($sql);
$thisAnnouncementOrderFound = false;
$thisAnnouncementOrder = null;
@ -549,6 +548,7 @@ switch ($action) {
$sendToUsersInSession
);
}
Display::addFlash(
Display::return_message(
get_lang('AnnouncementAdded'),
@ -565,7 +565,6 @@ switch ($action) {
}
header('Location: '.$homeUrl);
exit;
} // end condition token
}
}

@ -219,6 +219,7 @@ if (api_is_allowed_to_edit(false, true) ||
exit;
}
$usersToSend = isset($values['users_to_send']) ? $values['users_to_send'] : '';
// Editing normal event.
$agenda->editEvent(
$eventId,
@ -227,7 +228,7 @@ if (api_is_allowed_to_edit(false, true) ||
$allDay,
$values['title'],
$values['content'],
$values['users_to_send'],
$usersToSend,
$attachmentList,
$attachmentCommentList,
$comment,

@ -1,5 +1,6 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CourseBundle\Component\CourseCopy\CourseArchiver;
/**

@ -27,7 +27,7 @@ $response = $client->call(
'import_users',
array(
'filepath' => api_get_path(SYS_UPLOAD_PATH)."users_import.csv",
'security_key' => $_configuration['security_key'],
'security_key' => api_get_configuration_value('security_key'),
)
);
echo $response;

@ -502,21 +502,6 @@ if ($form->validate()) {
fclose($fp);
chmod($filepath.$filename.'.'.$extension, api_get_permissions_for_new_files());
/*
if (!is_dir($filepath.'css')) {
mkdir($filepath.'css', api_get_permissions_for_new_directories());
$doc_id = add_document($_course, $dir.'css', 'folder', 0, 'css');
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'FolderCreated', $userId, null, null, null, null, $current_session_id);
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, null, null, null, null, $current_session_id);
}
if (!is_file($filepath.'css/frames.css')) {
// Make a copy of the current css for the new document
copy(api_get_path(SYS_CODE_PATH).'css/'.api_get_setting('stylesheets').'/frames.css', $filepath.'css/frames.css');
$doc_id = add_document($_course, $dir.'css/frames.css', 'file', filesize($filepath.'css/frames.css'), 'frames.css');
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $userId, null, null, null, null, $current_session_id);
api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'invisible', $userId, null, null, null, null, $current_session_id);
}*/
$file_size = filesize($filepath.$filename.'.'.$extension);
$save_file_path = $dir.$filename.'.'.$extension;

@ -1,13 +1,14 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
/**
* Functions and main code for the download folder feature
*
* @package chamilo.document
*/
use ChamiloSession as Session;
set_time_limit(0);
require_once '../inc/global.inc.php';

@ -1,6 +1,8 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
/**
* This script contains the code to edit and send an e-mail to one of
* the platform's users.
@ -10,8 +12,6 @@
* @author Julio Montoya <gugli100@gmail.com> Updating form with formvalidator
*/
use ChamiloSession as Session;
require_once '../inc/global.inc.php';
if (empty($_user['user_id'])) {
@ -31,12 +31,10 @@ $form->addElement('text', 'email_address', get_lang('EmailDestination'));
$form->addElement('text', 'email_title', get_lang('EmailTitle'));
$form->freeze('email_address');
$form->addElement('textarea', 'email_text', get_lang('EmailText'), array('rows' => '6'));
$form->addRule('email_address', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('email_title', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('email_text', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('email_address', get_lang('EmailWrong'), 'email');
$form->addButtonSend(get_lang('SendMail'));
switch ($action) {

@ -49,7 +49,6 @@ $TechnicalIssuesTitle = 'Technical issues';
$TechnicalIssuesDescription = 'This portal is currently experiencing technical issues. Please report this to the portal administrator. Thank you for your help.';
if (is_int($global_error_code) && $global_error_code > 0) {
if (class_exists('Template') && function_exists('api_get_configuration_value')) {
$theme = Template::getThemeFallback().'/';
} else {
@ -58,7 +57,7 @@ if (is_int($global_error_code) && $global_error_code > 0) {
$root_rel = '';
$installation_guide_url = $root_rel.'documentation/installation_guide.html';
$css_path = 'app/Resources/public/css/';
$css_web_assets = 'web/assets/';
$css_web_path = 'web/css/';
@ -251,7 +250,7 @@ if (is_int($global_error_code) && $global_error_code > 0) {
</html>
EOM;
} else {
$global_error_message_page =
$global_error_message_page =
<<<EOM
<!DOCTYPE html>
<html>

@ -96,7 +96,6 @@ if ($intro_editAllowed) {
}
Database::getManager()->persist($toolIntro);
Database::getManager()->flush();
Display::addFlash(
Display::return_message(
get_lang('IntroductionTextUpdated'),
@ -164,10 +163,9 @@ if (!empty($session_id)) {
}
}
$intro_content = Security::remove_XSS($intro_content);
$intro_content = Security::remove_XSS($intro_content, COURSEMANAGER);
/* Determines the correct display */
if ($intro_cmdEdit || $intro_cmdAdd) {
$intro_dispDefault = false;
$intro_dispForm = true;
@ -190,7 +188,7 @@ if ($intro_dispForm) {
$default['intro_content'] = $intro_content;
$form->setDefaults($default);
$introduction_section .= '<div id="courseintro" style="width: 98%">';
$introduction_section .= $form->return_form();
$introduction_section .= $form->returnForm();
$introduction_section .= '</div>';
}
@ -209,7 +207,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
$thematic_advance_info = $thematic->get_thematic_advance_list($last_done_advance);
$subTitle1 = get_lang('CurrentTopic');
$class1 = ' current';
} else if($displayMode == '2') {
} else if ($displayMode == '2') {
// Show only the two next course progress steps
// $information_title = get_lang('InfoAboutNextAdvanceNotDone');
$last_done_advance = $thematic->get_next_thematic_advance_not_done();
@ -217,7 +215,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
$thematic_advance_info = $thematic->get_thematic_advance_list($last_done_advance);
$thematic_advance_info2 = $thematic->get_thematic_advance_list($next_advance_not_done);
$subTitle1 = $subTitle2 = get_lang('NextTopic');
} else if($displayMode == '3') {
} else if ($displayMode == '3') {
// Show the current and next course progress steps
// $information_title = get_lang('InfoAboutLastDoneAdvanceAndNextAdvanceNotDone');
$last_done_advance = $thematic->get_last_done_thematic_advance();
@ -232,8 +230,7 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
if (!empty($thematic_advance_info)) {
$thematic_advance = get_lang('CourseThematicAdvance');
$thematicScore = $thematic->get_total_average_of_thematic_advances() . '%';
$thematicUrl = api_get_path(WEB_CODE_PATH) .
'course_progress/index.php?action=thematic_details&'.api_get_cidreq();
$thematicUrl = api_get_path(WEB_CODE_PATH).'course_progress/index.php?action=thematic_details&'.api_get_cidreq();
$thematic_info = $thematic->get_thematic_list(
$thematic_advance_info['thematic_id']
);
@ -283,8 +280,6 @@ if ($tool == TOOL_COURSE_HOMEPAGE && !isset($_GET['intro_cmdEdit'])) {
</div>
</div>';
}
$thematicPanel = '<div class="row">';
$thematicPanel .= '<div class="col-md-2">' . $infoUser . '</div>';
$thematicPanel .= '<div class="col-md-10"><div class="row">' . $thematicItemOne . $thematicItemTwo . '</div></div>';

@ -307,6 +307,10 @@ class AnnouncementEmail
// Send email one by one to avoid antispam
$users = $this->sent_to();
$batchSize = 20;
$counter = 1;
$em = Database::getManager();
foreach ($users as $user) {
$message = $this->message($user['user_id']);
MessageManager::send_message_simple(
@ -317,6 +321,12 @@ class AnnouncementEmail
$sendToDrhUsers,
true
);
if (($counter % $batchSize) === 0) {
$em->flush();
$em->clear();
}
$counter++;
}
if ($sendToUsersInSession) {

@ -153,11 +153,17 @@ class AnnouncementManager
/**
* Deletes an announcement
* @param array $_course the course array
* @param int $id the announcement id
* @param int $id the announcement id
*/
public static function delete_announcement($_course, $id)
{
api_item_property_update($_course, TOOL_ANNOUNCEMENT, $id, 'delete', api_get_user_id());
api_item_property_update(
$_course,
TOOL_ANNOUNCEMENT,
$id,
'delete',
api_get_user_id()
);
}
/**
@ -387,13 +393,13 @@ class AnnouncementManager
/**
* Store an announcement in the database (including its attached file if any)
* @param string Announcement title (pure text)
* @param string Content of the announcement (can be HTML)
* @param int Display order in the list of announcements
* @param array Array of users and groups to send the announcement to
* @param array uploaded file $_FILES
* @param string Comment describing the attachment
* @param bool $sendToUsersInSession
* @param string $emailTitle Announcement title (pure text)
* @param string $newContent Content of the announcement (can be HTML)
* @param array $sentTo Array of users and groups to send the announcement to
* @param array $file uploaded file $_FILES
* @param string $file_comment Comment describing the attachment
* @param string $end_date
* @param bool $sendToUsersInSession
* @return int false on failure, ID of the announcement on success
*/
public static function add_announcement(
@ -458,8 +464,11 @@ class AnnouncementManager
} else {
$send_to = CourseManager::separateUsersGroups($sentTo);
$batchSize = 20;
$em = Database::getManager();
// Storing the selected groups
if (is_array($send_to['groups']) && !empty($send_to['groups'])) {
$counter = 1;
foreach ($send_to['groups'] as $group) {
api_item_property_update(
$_course,
@ -469,11 +478,18 @@ class AnnouncementManager
api_get_user_id(),
$group
);
if (($counter % $batchSize) === 0) {
$em->flush();
$em->clear();
}
$counter++;
}
}
// Storing the selected users
if (is_array($send_to['users'])) {
$counter = 1;
foreach ($send_to['users'] as $user) {
api_item_property_update(
$_course,
@ -484,6 +500,12 @@ class AnnouncementManager
'',
$user
);
if (($counter % $batchSize) === 0) {
$em->flush();
$em->clear();
}
$counter++;
}
}
}
@ -1206,8 +1228,11 @@ class AnnouncementManager
* @param bool $sendToUsersInSession
* @param bool $sendToDrhUsers
*/
public static function send_email($id, $sendToUsersInSession = false, $sendToDrhUsers = false)
{
public static function send_email(
$id,
$sendToUsersInSession = false,
$sendToDrhUsers = false
) {
$email = AnnouncementEmail::create(null, $id);
$email->send($sendToUsersInSession, $sendToDrhUsers);
}
@ -1278,7 +1303,7 @@ class AnnouncementManager
//if (!empty($user_id)) {
if (0) {
if (is_array($group_memberships) && count($group_memberships) > 0 ) {
if (is_array($group_memberships) && count($group_memberships) > 0) {
$sql = "SELECT $select
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
@ -1325,7 +1350,6 @@ class AnnouncementManager
ORDER BY display_order DESC";
//GROUP BY ip.ref
} else {
// A.3 you are a course admin without any group or user filter
// A.3.a you are a course admin without user or group filter but WITH studentview
// => see all the messages of all the users and groups without editing possibilities
@ -1402,7 +1426,6 @@ class AnnouncementManager
AND ip.visibility='1'
ORDER BY display_order DESC";
} else {
if ($user_id) {
if ($allowUserEditSetting && !api_is_anonymous()) {
$cond_user_id = " AND (
@ -1426,7 +1449,6 @@ class AnnouncementManager
AND ip.visibility='1'
AND announcement.session_id IN(0, ".$session_id.")
ORDER BY display_order DESC";
} else {
if (($allowUserEditSetting && !api_is_anonymous())) {
$cond_user_id = " AND (
@ -1691,7 +1713,7 @@ class AnnouncementManager
}
// the user is not identiefied => show only the general announcements
$sql="SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
$sql = "SELECT announcement.*, ip.visibility, ip.to_group_id, ip.insert_user_id
FROM $tbl_announcement announcement, $tbl_item_property ip
WHERE
announcement.c_id = $course_id AND

@ -32,7 +32,12 @@ class MoodleImport
}
if (!$mainFileKey) {
Display::addFlash(Display::return_message(get_lang('FailedToImportThisIsNotAMoodleFile'), 'error'));
Display::addFlash(
Display::return_message(
get_lang('FailedToImportThisIsNotAMoodleFile'),
'error'
)
);
}
$folder = api_get_unique_id();
@ -45,7 +50,7 @@ class MoodleImport
mkdir($destinationDir, api_get_permissions_for_new_directories(), true);
$newFolderData = create_unexisting_directory(
create_unexisting_directory(
$courseInfo,
api_get_user_id(),
$sessionId,
@ -90,7 +95,7 @@ class MoodleImport
// Create a Forum category based on Moodle forum type.
$catForumValues['forum_category_title'] = $moduleValues['type'];
$catForumValues['forum_category_comment'] = '';
$catId = store_forumcategory($catForumValues, [], false);
$catId = store_forumcategory($catForumValues, $courseInfo, false);
$forumValues = [];
$forumValues['forum_title'] = $moduleValues['name'];
$forumValues['forum_image'] = '';
@ -98,10 +103,9 @@ class MoodleImport
$forumValues['forum_category'] = $catId;
$forumValues['moderated'] = 0;
store_forum($forumValues);
store_forum($forumValues, $courseInfo);
break;
case 'quiz':
// Read the current quiz module xml.
// The quiz case is the very complicate process of all the import.
// Please if you want to review the script, try to see the readingXML functions.
@ -117,7 +121,7 @@ class MoodleImport
// var_dump($moduleValues); // <-- uncomment this to see the final array
// Lets do this ...
$exercise = new Exercise();
$exercise = new Exercise($courseInfo['real_id']);
$exercise->updateTitle(Exercise::format_title_variable($moduleValues['name']));
$exercise->updateDescription($moduleValues['intro']);
$exercise->updateAttempts($moduleValues['attempts_number']);
@ -177,7 +181,7 @@ class MoodleImport
$questionList = $moduleValues['question_instances'][$index]['plugin_qtype_'.$qType.'_question'];
$currentQuestion = $moduleValues['question_instances'][$index];
$result = $this->processAnswers($questionList, $qType, $questionInstance, $currentQuestion);
$this->processAnswers($questionList, $qType, $questionInstance, $currentQuestion);
}
}
@ -337,6 +341,7 @@ class MoodleImport
}
$currentItem['contextid'] = $contextId;
return $currentItem;
}
@ -464,7 +469,7 @@ class MoodleImport
}
/**
* Search the current quiestion resource in main Questions XML
* Search the current question resource in main Questions XML
*
* @param resource $questionsXml XML file
* @param int $questionId
@ -617,13 +622,9 @@ class MoodleImport
break;
case 'multianswer':
$objAnswer = new Answer($questionInstance->id);
$coursePath = api_get_course_path();
$placeholder = str_replace('@@PLUGINFILE@@', '/courses/' . $coursePath . '/document/moodle', $currentQuestion['questiontext']);
$optionsValues = [];
foreach ($questionList as $slot => $subQuestion) {
$qtype = $subQuestion['qtype'];
$optionsValues[] = $this->processFillBlanks($objAnswer, $qtype, $subQuestion['plugin_qtype_'.$qtype.'_question'], $placeholder, $slot + 1);
@ -794,13 +795,11 @@ class MoodleImport
*/
public function processFillBlanks($objAnswer, $questionType, $answerValues, &$placeholder, $position)
{
$coursePath = api_get_course_path();
switch ($questionType) {
case 'multichoice':
$optionsValues = [];
$correctAnswer = '';
$othersAnswer = '';
foreach ($answerValues as $answer) {
@ -818,13 +817,10 @@ class MoodleImport
$placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
return $optionsValues;
break;
case 'shortanswer':
$optionsValues = [];
$correctAnswer = '';
foreach ($answerValues as $answer) {
$correct = intval($answer['fraction']);
if ($correct) {
@ -838,7 +834,6 @@ class MoodleImport
$placeholder = str_replace("{#$position}", $currentAnswers, $placeholder);
return $optionsValues;
break;
case 'match':
$answers = [];
@ -893,7 +888,6 @@ class MoodleImport
if ($moduleRes) {
$activities = $moduleDoc->getElementsByTagName('file');
foreach ($activities as $activity) {
$currentItem = [];
$thisIsAnInvalidItem = false;
@ -953,5 +947,4 @@ class MoodleImport
}
}
}
}
}

@ -2,6 +2,7 @@
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
use Chamilo\CourseBundle\Entity\CItemProperty;
/**
* This is a code library for Chamilo.
@ -3717,7 +3718,7 @@ function api_item_property_update(
$startVisibleDate = !empty($start_visible) ? new DateTime($start_visible, new DateTimeZone('UTC')) : null;
$endVisibleDate = !empty($endVisibleDate) ? new DateTime($endVisibleDate, new DateTimeZone('UTC')) : null;
$cItemProperty = new \Chamilo\CourseBundle\Entity\CItemProperty($objCourse);
$cItemProperty = new CItemProperty($objCourse);
$cItemProperty
->setTool($tool)
->setRef($item_id)

@ -3381,13 +3381,15 @@ class Tracking
}
$sql = "SELECT count(ip.tool) AS count
FROM $tbl_item_property ip INNER JOIN $tbl_document pub
ON ip.ref = pub.id
WHERE ip.c_id = $course_id AND
pub.c_id = $course_id AND
pub.filetype ='file' AND
ip.tool = 'document'
$condition_user $condition_session ";
FROM $tbl_item_property ip
INNER JOIN $tbl_document pub
ON (ip.ref = pub.id AND ip.c_id = pub.c_id)
WHERE
ip.c_id = $course_id AND
pub.c_id = $course_id AND
pub.filetype ='file' AND
ip.tool = 'document'
$condition_user $condition_session ";
$rs = Database::query($sql);
$row = Database::fetch_array($rs, 'ASSOC');
return $row['count'];
@ -3438,7 +3440,8 @@ class Tracking
$sql = "SELECT count(ip.tool) as count
FROM $tbl_item_property ip
INNER JOIN $tbl_student_publication pub ON ip.ref = pub.id
INNER JOIN $tbl_student_publication pub
ON (ip.ref = pub.id AND ip.c_id = pub.c_id)
WHERE
ip.tool='work' AND
$conditionToString";
@ -3465,7 +3468,7 @@ class Tracking
$courseCondition = null;
$conditions = array();
if (!empty($courseInfo)) {
$course_id = $courseInfo['real_id'];
$course_id = $courseInfo['real_id'];
$conditions[]= " post.c_id = $course_id AND forum.c_id = $course_id ";
}
@ -3489,7 +3492,7 @@ class Tracking
$conditionsToString = implode('AND ', $conditions);
$sql = "SELECT count(poster_id) as count
FROM $tbl_forum_post post INNER JOIN $tbl_forum forum
ON forum.forum_id = post.forum_id
ON (forum.forum_id = post.forum_id AND forum.c_id = post.c_id)
WHERE $conditionsToString";
$rs = Database::query($sql);
@ -3651,7 +3654,7 @@ class Tracking
$sql = "SELECT count(*)
FROM $tbl_forums f
INNER JOIN $item i
ON f.c_id = i.c_id AND f.iid = i.ref AND tool = '".TOOL_FORUM."'
ON f.c_id = i.c_id AND f.iid = i.ref AND tool = '".TOOL_FORUM."'
WHERE
f.c_id = $course_id AND
$groupCondition
@ -3741,9 +3744,9 @@ class Tracking
/**
* Get count student's visited links
* @param int Student id
* @param int $courseId
* @param int Session id (optional)
* @param int $student_id Student id
* @param int $courseId
* @param int $session_id Session id (optional)
* @return int count of visited links
*/
public static function count_student_visited_links($student_id, $courseId, $session_id = 0)
@ -3887,7 +3890,6 @@ class Tracking
session_course_user.c_id = ' . $courseId . ' AND
stats_login.login_course_date IS NULL
GROUP BY session_course_user.user_id';
}
}

@ -487,8 +487,7 @@ if (!empty($_SESSION['_user']['user_id']) && !($login || $logout)) {
}
header(
'Location: '.api_get_path(WEB_PATH)
.'index.php?loginFailed=1&error=user_password_incorrect'
'Location: '.api_get_path(WEB_PATH).'index.php?loginFailed=1&error=user_password_incorrect'
);
exit;
}

@ -881,8 +881,9 @@ if (@$_POST['step2']) {
$connection->executeQuery("ALTER TABLE faq_category_translation ADD CONSTRAINT FK_5493B0FC2C2AC5D3 FOREIGN KEY (translatable_id) REFERENCES faq_category (id) ON DELETE CASCADE;");
$connection->executeQuery("ALTER TABLE faq_question ADD CONSTRAINT FK_4A55B05912469DE2 FOREIGN KEY (category_id) REFERENCES faq_category (id);");
*/
// Add version table
$connection->executeQuery('CREATE TABLE version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version))');
$connection->executeQuery('CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version))');
// Tickets
$ticketProject = new TicketProject();

@ -2776,9 +2776,14 @@ function finishInstallation(
updateDirAndFilesPermissions();
// Set the latest version
$path = api_get_path(SYS_PATH).'app/Migrations/Schema/V111/';
$path = $sysPath.'app/Migrations/Schema/V111/';
$finder = new \Symfony\Component\Finder\Finder();
$files = $finder->files()->in($path);
// Needed for chash
$sql = 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(255), PRIMARY KEY(id), UNIQUE(version));';
Database::query($sql);
foreach ($files as $version) {
$version = str_replace(['Version', '.php' ], '', $version->getFilename());
$sql = "INSERT INTO version (version) VALUES ('$version')";

@ -6,6 +6,20 @@ Authors : Valery Fremaux (valery.fremaux@gmail.com), Julio Montoya
Virtual chamilo is a feature that allows running several chamilo instances sharing the same
code base.
Changelog
=========
Version 1.4
Database upgrade needed:
ALTER TABLE vchamilo ADD COLUMN password_encryption VARCHAR(255);
Version 1.3
Add vchamilo import
Version features
===================
This is a yet prototypal version that is not full featured in back-office tools.

@ -36,8 +36,9 @@ $sql = "CREATE TABLE IF NOT EXISTS $tablename (
`lastcron` int(11),
`croncount` int(11),
`template` varchar(255),
`password_encryption` varchar(255),
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
";
Database::query($sql);

@ -16,7 +16,7 @@ class VChamiloPlugin extends Plugin
*/
public function __construct()
{
parent::__construct('1.3', 'Valery Fremaux, Julio Montoya');
parent::__construct('1.4', 'Valery Fremaux, Julio Montoya');
}
/**

@ -16,7 +16,7 @@ class Virtual
/**
* @param array $_configuration
*/
public static function hookConfiguration(&$_configuration)
public static function hookConfiguration(& $_configuration)
{
global $virtualChamilo;
@ -55,6 +55,7 @@ class Virtual
$coursePath = '';
$archivePath = '';
$uploadPath = '';
$passwordEncryption = '';
foreach ($virtualSettings as $setting) {
switch ($setting['variable']) {
@ -70,6 +71,9 @@ class Virtual
case 'vchamilo_archive_real_root':
$archivePath = $setting['selected_value'];
break;
case 'vchamilo_password_encryption':
$passwordEncryption = $setting['selected_value'];
break;
}
}
@ -92,6 +96,10 @@ class Virtual
$data['SYS_COURSE_PATH'] = $coursePath.'/'.$data['slug'];
$data['SYS_UPLOAD_PATH'] = $uploadPath.'/'.$data['slug'];
if (!empty($passwordEncryption)) {
$_configuration['password_encryption'] = $passwordEncryption;
}
$virtualChamilo = $data;
} else {
exit("This portal is disabled. Please contact your administrator");
@ -967,8 +975,9 @@ class Virtual
/**
* @param stdClass $data
* @param string $fromVersion
*/
public static function importInstance($data)
public static function importInstance($data, $fromVersion)
{
if (isset($data->what)) {
unset($data->what);
@ -1061,6 +1070,7 @@ class Virtual
}
if (!$id) {
var_dump($data);
throw new Exception('Was not registered');
}
@ -1069,7 +1079,6 @@ class Virtual
}
self::createDirsFromSlug($slug);
self::ctrace("Create database");
$databaseCreated = Virtual::createDatabase($newDatabase);
if (!$databaseCreated) {
Display::addFlash(
@ -1078,6 +1087,10 @@ class Virtual
return false;
}
$coursePath = self::getConfig('vchamilo', 'course_real_root').'/'.$slug;
$homePath = self::getConfig('vchamilo', 'home_real_root').'/'.$slug;
$uploadPath = self::getConfig('vchamilo', 'upload_real_root').'/'.$slug;
$dumpFile = api_get_path(SYS_ARCHIVE_PATH).uniqid($data->main_database.'_dump_', true).'.sql';
self::ctrace('Create backup from "'.$data->main_database.'" here: '.$dumpFile.' ');
Virtual::backupDatabase($data, $dumpFile);
@ -1117,7 +1130,7 @@ class Virtual
$outputStream = new \Symfony\Component\Console\Output\BufferedOutput($tmpFile);
$arguments = array(
'from-version' => '1.10.0', // @todo change value
'from-version' => $fromVersion, // @todo change value
'to-version' => '1.11.x',
'host' => $newDatabase->db_host,
'username' => $newDatabase->db_user,
@ -1129,16 +1142,12 @@ class Virtual
$input = new ArrayInput($arguments);
$command->run($input, $outputStream);
Display::addFlash(Display::return_message($outputStream->fetch()));
error_log($outputStream->fetch());
if (file_exists($dumpFile)) {
unlink($dumpFile);
}
$coursePath = self::getConfig('vchamilo', 'course_real_root').'/'.$slug;
$homePath = self::getConfig('vchamilo', 'home_real_root').'/'.$slug;
$uploadPath = self::getConfig('vchamilo', 'upload_real_root').'/'.$slug;
// Course
self::ctrace("Copy from '$fromCoursePath' to backup '$coursePath' ");
copyDirTo(
@ -1276,5 +1285,22 @@ class Virtual
return false;
}
/**
* @return array
*/
public static function getEncryptList()
{
$encryptList = [
'bcrypt',
'sha1',
'md5',
'none'
];
return array_combine($encryptList, $encryptList);
}
}

@ -1,4 +1,5 @@
<?php
exit;
/**
* This file is a cron microclock script.
* It will be used as replacement of setting individual

@ -352,9 +352,7 @@ class InstanceForm extends ChamiloForm
$form->addHeader($plugin->get_lang('hostdefinition'));
$form->addText('sitename', [$plugin->get_lang('sitename'), $plugin->get_lang('SiteNameExample')]);
$form->applyFilter('sitename', 'trim');
$form->addText('institution', [$plugin->get_lang('institution'), $plugin->get_lang('InstitutionExample')]);
$form->applyFilter('institution', 'trim');
// Host's name.
@ -366,6 +364,14 @@ class InstanceForm extends ChamiloForm
$form->applyFilter('root_web', 'trim');
if ($this->_mode == 'update') {
$encryptList = Virtual::getEncryptList();
$encryptMethod = $form->addElement(
'select',
'password_encryption',
get_lang('EncryptMethodUserPass'),
$encryptList
);
$encryptMethod->freeze();
$elementWeb->freeze();
}

@ -45,6 +45,29 @@ $form->addText(
true
);
$encryptList = Virtual::getEncryptList();
$form->addSelect(
'password_encryption',
get_lang('EncryptMethodUserPass'),
$encryptList
);
$encryptList = Virtual::getEncryptList();
$versionList = [
'1.11.x',
'1.10.x',
'1.9.x'
];
$form->addSelect(
'version',
get_lang('FromVersion'),
array_combine($versionList, $versionList)
);
$form->addText(
'course_path',
[
@ -143,8 +166,11 @@ if ($form->validate()) {
$vchamilo->course_path = $values['course_path'];
$vchamilo->home_path = $values['home_path'];
$vchamilo->upload_path = $values['upload_path'];
$vchamilo->password_encryption = $values['password_encryption'];
Virtual::importInstance($vchamilo, $values['version']);
Virtual::importInstance($vchamilo);
Virtual::redirect(api_get_path(WEB_PLUGIN_PATH).'vchamilo/views/manage.php');
}
}

@ -42,17 +42,18 @@ class CourseArchiver
public static function cleanBackupDir()
{
$dir = self::getBackupDir();
if ($handle = @ opendir($dir)) {
while (($file = readdir($handle)) !== false) {
if ($file != "." && $file != ".." &&
strpos($file, 'CourseArchiver_') === 0 &&
is_dir($dir . '/' . $file)
) {
rmdirr($dir . '/' . $file);
if (is_dir($dir)) {
if ($handle = @ opendir($dir)) {
while (($file = readdir($handle)) !== false) {
if ($file != "." && $file != ".." &&
strpos($file, 'CourseArchiver_') === 0 &&
is_dir($dir.'/'.$file)
) {
rmdirr($dir.'/'.$file);
}
}
closedir($handle);
}
closedir($handle);
}
}

Loading…
Cancel
Save