Merge with 1.10.x

pull/2487/head
jmontoyaa 10 years ago
commit c81ef9b2ea
  1. 5
      app/Resources/public/css/base.css
  2. 32
      documentation/optimization.html
  3. 3
      main/course_info/infocours.php
  4. 6
      main/exercice/admin.php
  5. 2
      main/exercice/exercise_admin.php
  6. 2
      main/exercice/question_pool.php
  7. 4
      main/exercice/upload_exercise.php
  8. 6
      main/gradebook/gradebook_display_certificate.php
  9. 2
      main/gradebook/gradebook_display_summary.php
  10. 4
      main/group/group_category.php
  11. 4
      main/group/group_edit.php
  12. 2
      main/group/group_overview.php
  13. 14
      main/group/group_space.php
  14. 2
      main/group/member_settings.php
  15. 4
      main/group/settings.php
  16. 4
      main/group/tutor_settings.php
  17. BIN
      main/img/icons/32/bbb.png
  18. BIN
      main/img/icons/32/bbb_na.png
  19. 15
      main/inc/lib/api.lib.php
  20. 2
      main/inc/lib/course.lib.php
  21. 9
      main/inc/lib/database.lib.php
  22. 23
      main/inc/lib/internationalization.lib.php
  23. 6
      main/inc/lib/pear/PEAR.php
  24. 9
      main/inc/lib/plugin.class.php
  25. 6
      main/inc/lib/plugin.lib.php
  26. 2
      main/newscorm/index.php
  27. 2
      main/survey/index.php
  28. 2
      main/survey/survey_invite.php
  29. 22
      plugin/bbb/changelog.md
  30. 4
      plugin/bbb/lang/english.php
  31. 12
      plugin/bbb/lang/french.php
  32. 3
      plugin/bbb/lang/spanish.php
  33. 135
      plugin/bbb/lib/bbb.lib.php
  34. 71
      plugin/bbb/lib/bbb_plugin.class.php
  35. 1
      plugin/bbb/listing.php
  36. 7
      tests/main/inc/lib/main_api.lib.test.php

@ -2954,6 +2954,9 @@ a:active{
tr.forum_category_header a {
color: #fff;
}
.forum-description {
display: inline-block;
}
/* **** FORUM **** */
.forum_header {
background-color: #EEF;
@ -6032,4 +6035,4 @@ a.sessionView {
border: 2px dashed #bbbbbb;
font-size: 120%;
margin-bottom: 0;
}
}

@ -56,6 +56,7 @@
<li><a href="#10.igbinary">IGBinary for faster courses backups and better sessions</a></li>
<li><a href="#11.permissions-check">Removing files download permissions check</a></li>
<li><a href="#12.MySQL-compression">MySQL/MariaDB compression</a></li>
<li><a href="#13.increasing-php-limits">Increasing PHP limits</a></li>
</ol>
<h2><a name="1.Using-XCache"></a>1. Using opcaches</h2>
@ -598,13 +599,42 @@ In 1.10.0, we have added the possibility to enable this compression very
This should have an immediate effect on the load average on your server.
</p>
<hr />
<h2><a name="13.increasing-php-limits"></a>Increasing PHP limits</h2>
<p>
As your use of Chamilo increases and you get above the thousands of users,
you're likely to hit a few milestones set by PHP to avoid hacks.
One of them is PHP5.4's Suhosin extension limit post_max_vars, which was
extended into PHP5.5 and above through the max_input_vars limit. This limit
is usually set to 1000. What does it mean?<br />
It means that, when you manipulate any list greater than 1000 items, PHP will
automatically remove anything sent above the first 1000 registers (usually
a little bit less because it needs to add the other input fields of the page).
For example, if subscribing 5 new users to a course where you already have
1000 users subscribed, you will remain at 1000, although the 1000 will not
necessarily be the 1000 that were there in the first place (they are sent
in order of the elements inside the form, so probably alphabetically,
depending on the page).<br /><br />
Increasing this limit to a higher level (say 10,000 instead of 1000) should
be relatively safe, considering your application is normally not open to
the public (and so also open to the evil kind of users). So, in your
php.ini, this limit should now look like this:<br />
<pre>
max_input_vars = 10000
</pre><br /><br />
A number of other limits might also become an issue in the long run, like
memory_limit, post_max_size, etc. We have given reasonnable recommendations
in the installation process for these values, but remember that if you
have a larger portal than anyone else, you probably need to give it more
care than anyone else.
</p>
<hr />
<h2>Authors</h2>
<ul>
<li>Yannick Warnier, Zend Certified PHP Engineer, BeezNest Belgium SPRL, <a href="mailto:ywarnier@beeznest.net">ywarnier@beeznest.net</a></li>
</ul>
<hr />
Don't have time or resources to optimize your Chamilo installation
yourself? Hire an <a href="//www.chamilo.org/en/providers">official Chamilo provider</a> and get it sorted out professionally by specialists.
yourself? Hire an <a href="//www.chamilo.org/en/providers">official Chamilo provider</a> and get it sorted out professionally by specialists.<br />
<a href="http://validator.w3.org/check?uri=referer"><img src="//www.w3.org/Icons/valid-xhtml10-blue" alt="Valid XHTML 1.0 Transitional" style="margin: 1em; float: right;" height="31" width="88" /></a>
<a href="http://jigsaw.w3.org/css-validator/">
<img src="//jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />

@ -536,7 +536,7 @@ $form->setDefaults($values);
// Validate form
if ($form->validate() && is_settings_editable()) {
$updateValues = $form->exportValues();
$updateValues = $form->getSubmitValues();
// update course picture
$picture = $_FILES['picture'];
@ -624,7 +624,6 @@ if ($form->validate() && is_settings_editable()) {
];
Database::update($table_course, $params, ['id = ?' => $courseId]);
// Insert/Updates course_settings table
foreach ($courseSettings as $setting) {
$value = isset($updateValues[$setting]) ? $updateValues[$setting] : null;

@ -363,11 +363,11 @@ $inATest = isset($exerciseId) && $exerciseId > 0;
if ($inATest) {
echo '<div class="actions">';
if (isset($_GET['hotspotadmin']) || isset($_GET['newQuestion']) || isset($_GET['myid']))
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?exerciseId='.$exerciseId.'&'.api_get_cidReq().'">'.
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?exerciseId='.$exerciseId.'&'.api_get_cidreq().'">'.
Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
if (!isset($_GET['hotspotadmin']) && !isset($_GET['newQuestion']) && !isset($_GET['myid']) && !isset($_GET['editQuestion'])) {
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/exercise.php?'.api_get_cidReq().'">'.
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/exercise.php?'.api_get_cidreq().'">'.
Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).'</a>';
}
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/overview.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id.'&preview=1">'.
@ -375,7 +375,7 @@ if ($inATest) {
echo Display::url(
Display::return_icon('test_results.png', get_lang('Results'),'',ICON_SIZE_MEDIUM),
api_get_path(WEB_CODE_PATH).'exercice/exercise_report.php?'.api_get_cidReq().'&exerciseId='.$objExercise->id
api_get_path(WEB_CODE_PATH).'exercice/exercise_report.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id
);
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/exercise_admin.php?'.api_get_cidreq().'&modifyExercise=yes&exerciseId='.$objExercise->id.'">'.

@ -187,7 +187,7 @@ if ($form->validate()) {
echo '<div class="actions">';
if ($objExercise->id != 0) {
echo '<a href="admin.php?'.api_get_cidReq().'&exerciseId='.$objExercise->id.'">' .
echo '<a href="admin.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id.'">' .
Display :: return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM).'</a>';
} else {
if (!empty($_GET['lp_id']) || !empty($_POST['lp_id'])){

@ -219,7 +219,7 @@ if (isset($fromExercise) && $fromExercise > 0) {
Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
$titleAdd = get_lang('AddQuestionToTest');
} else {
echo '<a href="exercise.php?'.api_get_cidReq().'">'.
echo '<a href="exercise.php?'.api_get_cidreq().'">'.
Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).'</a>';
echo "<a href='admin.php?exerciseId=0'>".Display::return_icon('add_question.gif', get_lang('NewQu'), '', ICON_SIZE_MEDIUM)."</a>";
$titleAdd = get_lang('ManageAllQuestions');

@ -58,7 +58,7 @@ lp_upload_quiz_main();
function lp_upload_quiz_actions()
{
$return = '<a href="exercise.php?'.api_get_cidReq().'">'.
$return = '<a href="exercise.php?'.api_get_cidreq().'">'.
Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).'</a>';
return $return;
}
@ -622,7 +622,7 @@ function lp_upload_quiz_action_handling() {
exit;
} else {
// header('location: exercice.php?' . api_get_cidreq());
echo '<script>window.location.href = "'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?'.api_get_cidReq().'&exerciseId='.$quiz_id.'&session_id='.api_get_session_id().'"</script>';
echo '<script>window.location.href = "'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?'.api_get_cidreq().'&exerciseId='.$quiz_id.'&session_id='.api_get_session_id().'"</script>';
}
}
}

@ -181,15 +181,15 @@ if ($filter === 'true') {
}
echo '<div class="btn-group">';
$url = api_get_self().'?action=generate_all_certificates'.'&'.api_get_cidReq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
$url = api_get_self().'?action=generate_all_certificates'.'&'.api_get_cidreq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
echo Display::url(get_lang('GenerateCertificates'), $url, array('class' => 'btn btn-default'));
$url = api_get_self().'?action=delete_all_certificates'.'&'.api_get_cidReq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
$url = api_get_self().'?action=delete_all_certificates'.'&'.api_get_cidreq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
echo Display::url(get_lang('DeleteAllCertificates'), $url, array('class' => 'btn btn-default'));
$hideCertificateExport = api_get_setting('hide_certificate_export_link');
if (count($certificate_list) > 0 && $hideCertificateExport !== 'true') {
$url = api_get_self().'?action=export_all_certificates'.'&'.api_get_cidReq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
$url = api_get_self().'?action=export_all_certificates'.'&'.api_get_cidreq().'&cat_id='.$cat_id.'&filter='.$filterOfficialCode;
echo Display::url(get_lang('ExportAllCertificatesToPDF'), $url, array('class' => 'btn btn-default'));
}
echo '</div>';

@ -126,7 +126,7 @@ echo Display::page_header(get_lang('GradebookListOfStudentsReports'));
echo '<div class="btn-group">';
if (count($userList) > 0) {
$url = api_get_self().'?action=export_all&'.api_get_cidReq().'&selectcat='.$cat_id;
$url = api_get_self().'?action=export_all&'.api_get_cidreq().'&selectcat='.$cat_id;
echo Display::url(get_lang('ExportAllToPDF'), $url, array('class' => 'btn btn-default'));
}
echo '</div>';

@ -80,7 +80,7 @@ $(document).ready( function() {
});
</script>';
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
$course_id = api_get_course_int_id();
@ -91,7 +91,7 @@ if (isset($_GET['id'])) {
$form = new FormValidator(
'group_category',
'post',
api_get_self().'?id='.$category['id'].'&'.api_get_cidReq()
api_get_self().'?id='.$category['id'].'&'.api_get_cidreq()
);
$form->addElement('hidden', 'id');
} else {

@ -22,8 +22,8 @@ $group_id = api_get_group_id();
$current_group = GroupManager :: get_group_properties($group_id);
$nameTools = get_lang('EditGroup');
$interbreadcrumb[] = array ('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array ('url' => 'group_space.php?'.api_get_cidReq(), 'name' => $current_group['name']);
$interbreadcrumb[] = array ('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array ('url' => 'group_space.php?'.api_get_cidreq(), 'name' => $current_group['name']);
$is_group_member = GroupManager :: is_tutor_of_group(api_get_user_id(), $group_id);

@ -64,7 +64,7 @@ if (isset($_GET['action'])) {
}
/* Header */
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
if (!isset ($_GET['origin']) || $_GET['origin'] != 'learnpath') {
// So we are not in learnpath tool
if (!$is_allowed_in_course) {

@ -20,7 +20,6 @@ require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
require_once api_get_path(SYS_CODE_PATH).'forum/forumconfig.inc.php';
/* MAIN CODE */
$group_id = api_get_group_id();
$user_id = api_get_user_id();
$current_group = GroupManager::get_group_properties($group_id);
@ -30,7 +29,7 @@ if (empty($current_group)) {
$this_section = SECTION_COURSES;
$nameTools = get_lang('GroupSpace');
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
/* Ensure all private groups // Juan Carlos Raña Trabado */
@ -205,6 +204,17 @@ if (api_is_allowed_to_edit(false, true) ||
}
}
$enabled = api_get_plugin_setting('bbb', 'tool_enable');
if ($enabled === 'true') {
$bbb = new bbb();
if ($bbb->hasGroupSupport()) {
$actions_array[] = array(
'url' => api_get_path(WEB_PLUGIN_PATH)."bbb/start.php?".api_get_cidreq(),
'content' => Display::return_icon('bbb.png', get_lang('VideoConference'), array(), 32)
);
}
}
if (!empty($actions_array)) {
echo Display::actions($actions_array);
}

@ -23,7 +23,7 @@ $current_group = GroupManager::get_group_properties($group_id);
$nameTools = get_lang('EditGroup');
$interbreadcrumb[] = array('url' => 'group.php', 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group_space.php?'.api_get_cidReq(), 'name' => $current_group['name']);
$interbreadcrumb[] = array('url' => 'group_space.php?'.api_get_cidreq(), 'name' => $current_group['name']);
$is_group_member = GroupManager::is_tutor_of_group(api_get_user_id(), $group_id);

@ -21,8 +21,8 @@ $group_id = api_get_group_id();
$current_group = GroupManager::get_group_properties($group_id);
$nameTools = get_lang('EditGroup');
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group_space.php?'.api_get_cidReq(), 'name' => $current_group['name']);
$interbreadcrumb[] = array('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array('url' => 'group_space.php?'.api_get_cidreq(), 'name' => $current_group['name']);
$is_group_member = GroupManager::is_tutor_of_group(api_get_user_id(), $group_id);
if (!api_is_allowed_to_edit(false, true) && !$is_group_member) {

@ -22,8 +22,8 @@ $group_id = api_get_group_id();
$current_group = GroupManager :: get_group_properties($group_id);
$nameTools = get_lang('EditGroup');
$interbreadcrumb[] = array ('url' => 'group.php?'.api_get_cidReq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array ('url' => 'group_space.php?'.api_get_cidReq(), 'name' => $current_group['name']);
$interbreadcrumb[] = array ('url' => 'group.php?'.api_get_cidreq(), 'name' => get_lang('Groups'));
$interbreadcrumb[] = array ('url' => 'group_space.php?'.api_get_cidreq(), 'name' => $current_group['name']);
$is_group_member = GroupManager :: is_tutor_of_group(api_get_user_id(), $group_id);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

@ -4413,21 +4413,6 @@ function api_number_of_plugins($location) {
return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
}
/**
* Checks to see wether a certain plugin is installed.
* @return boolean true if the plugin is installed, false otherwise.
*/
function api_is_plugin_installed($plugin_list, $plugin_name) {
if (is_array($plugin_list)) {
foreach ($plugin_list as $plugin_location) {
if (array_search($plugin_name, $plugin_location) !== false) {
return true;
}
}
}
return false;
}
/**
* Transforms a number of seconds in hh:mm:ss format
* @author Julian Prud'homme

@ -5124,11 +5124,11 @@ class CourseManager
$settingList = self::getCourseSettingVariables($appPlugin);
if (!in_array($variable, $settingList)) {
return false;
}
$courseSettingTable = Database::get_course_table(TABLE_COURSE_SETTING);
if (self::hasCourseSetting($variable, $courseId)) {
// Update
Database::update(

@ -686,4 +686,13 @@ class Database
{
return self::getManager()->getConnection()->getSchemaManager()->tablesExist($table);
}
/**
* @param $table
* @return \Doctrine\DBAL\Schema\Column[]
*/
public static function listTableColumns($table)
{
return self::getManager()->getConnection()->getSchemaManager()->listTableColumns($table);
}
}

@ -3,7 +3,7 @@
/**
* File: internationalization.lib.php
* Internationalization library for Chamilo 1.8.7 LMS
* Internationalization library for Chamilo 1.x LMS
* A library implementing internationalization related functions.
* License: GNU General Public License Version 3 (Free Software Foundation)ww
* @author Ivan Tcholakov, <ivantcholakov@gmail.com>, 2009, 2010
@ -275,7 +275,7 @@ function api_get_language_isocode($language = null, $default_code = 'en')
}
/**
* Gets language isocode column from the language table
* Gets language iso code column from the language table
*
* @return array An array with the current isocodes
*
@ -283,7 +283,8 @@ function api_get_language_isocode($language = null, $default_code = 'en')
function api_get_platform_isocodes()
{
$iso_code = array();
$sql_result = Database::query("SELECT isocode FROM ".Database::get_main_table(TABLE_MAIN_LANGUAGE)." ORDER BY isocode ");
$sql = "SELECT isocode FROM ".Database::get_main_table(TABLE_MAIN_LANGUAGE)." ORDER BY isocode ";
$sql_result = Database::query($sql);
if (Database::num_rows($sql_result)) {
while ($row = Database::fetch_array($sql_result)) {;
$iso_code[] = trim($row['isocode']);
@ -348,6 +349,7 @@ function api_get_timezones()
}
$null_option = array('' => '');
$result = array_merge($null_option, $out);
return $result;
}
@ -439,8 +441,12 @@ function api_get_utc_datetime($time = null, $return_null_if_invalid_date = false
*
* @author Guillaume Viguier <guillaume.viguier@beeznest.com>
*/
function api_get_local_time($time = null, $to_timezone = null, $from_timezone = null, $return_null_if_invalid_date = false)
{
function api_get_local_time(
$time = null,
$to_timezone = null,
$from_timezone = null,
$return_null_if_invalid_date = false
) {
// Determining the timezone to be converted from
if (is_null($from_timezone)) {
$from_timezone = 'UTC';
@ -471,8 +477,10 @@ function api_get_local_time($time = null, $to_timezone = null, $from_timezone =
try {
$date = new DateTime($time, new DateTimezone($from_timezone));
$date->setTimezone(new DateTimeZone($to_timezone));
return $date->format('Y-m-d H:i:s');
} catch (Exception $e) {
return null;
}
}
@ -480,8 +488,8 @@ function api_get_local_time($time = null, $to_timezone = null, $from_timezone =
/**
* Converts a string into a timestamp safely (handling timezones), using strtotime
*
* @param string String to be converted
* @param string Timezone (if null, the timezone will be determined based
* @param string $time to be converted
* @param string $timezone (if null, the timezone will be determined based
* on user preference, or timezone chosen by the admin for the platform)
* @return int Timestamp
*
@ -494,6 +502,7 @@ function api_strtotime($time, $timezone = null) {
}
$timestamp = strtotime($time);
date_default_timezone_set($system_timezone);
return $timestamp;
}

@ -558,12 +558,6 @@ class PEAR
$ec = 'PEAR_Error';
}
if (intval(PHP_VERSION) < 5) {
// little non-eval hack to fix bug #12147
include 'PEAR/FixPHP5PEARWarnings.php';
return $a;
}
if ($skipmsg) {
$a = new $ec($code, $mode, $options, $userinfo);
} else {

@ -748,4 +748,13 @@ class Plugin
}
}
}
/**
* @param string $variable
* @return bool
*/
public function validateCourseSetting($variable)
{
return true;
}
}

@ -372,8 +372,7 @@ class AppPlugin
$_template['plugin_info'] = $plugin_info;
}
// Setting the plugin info available in the template if exists
// Setting the plugin info available in the template if exists.
$template->assign($plugin_name, $_template);
// Loading the Twig template plugin files if exists
@ -548,6 +547,9 @@ class AppPlugin
$groups = array();
foreach ($obj->course_settings as $setting) {
if ($obj->validateCourseSetting($setting['name']) === false) {
continue;
}
if ($setting['type'] != 'checkbox') {
$form->addElement($setting['type'], $setting['name'], $obj->get_lang($setting['name']));
} else {

@ -10,4 +10,4 @@
$use_anonymous = true;
require_once '../inc/global.inc.php';
header('location: lp_controller.php?'.api_get_cidReq().'&action=list');
header('location: lp_controller.php?'.api_get_cidreq().'&action=list');

@ -1,4 +1,4 @@
<?php
require_once '../inc/global.inc.php';
header('location: '.api_get_path(WEB_CODE_PATH).'survey/survey_list.php?'.api_get_cidReq());
header('location: '.api_get_path(WEB_CODE_PATH).'survey/survey_list.php?'.api_get_cidreq());
exit;

@ -96,7 +96,7 @@ if ($survey_data['invited'] > 0 && !isset($_POST['submit'])) {
$form = new FormValidator(
'publish_form',
'post',
api_get_self().'?survey_id='.$survey_id.'&'.api_get_cidReq()
api_get_self().'?survey_id='.$survey_id.'&'.api_get_cidreq()
);
$form->addElement('header', '', $tool_name);

@ -1,10 +1,19 @@
version 2.3 - 2015-05-18
Version 2.4 2016-05
------------------------
Changes:
* Global conference support (Requires to update the plugin settings).
* Course group conference support
* Requires a database change: "ALTER TABLE plugin_bbb_meeting ADD COLUMN group_id INT DEFAULT 0"
* Requires to update the plugin settings.
Version 2.3 - 2015-05-18
------------------------
Changes:
* Added support for variable voiceBridge to be sent on meeting creation. See https://code.google.com/p/bigbluebutton/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Component%20Summary&groupby=&sort=&id=1186 and https://support.chamilo.org/issues/7669 for details.
* Requires you to "ALTER TABLE plugin_bbb_meeting ADD COLUMN voice_bridge INT NOT NULL DEFAULT 1;"
* Requires a database change: "ALTER TABLE plugin_bbb_meeting ADD COLUMN voice_bridge INT NOT NULL DEFAULT 1;"
version 2.2 - 2014-10-15
Version 2.2 - 2014-10-15
------------------------
Changes:
* Add a pseudo-random guid to avoid clashing conferences when several Chamilo portals use the same server. If you were using this plugin before, you will have to update the plugin_bbb_meeting table to "alter table plugin_bbb_meeting add column remote_id char(36);".
@ -13,16 +22,15 @@ Changes:
* Hide the ID of the meeting (this was an internal ID, useless to the final user). It is still in the HTML source, however
* Show number of minutes of the recording (in the recordings list)
version 2.1
Version 2.1
-----------
Released with: Chamilo LMS 1.9.8
Changes:
* now supports sessions (requires you to "alter table plugin_bbb_meeting add column session_id int default 0;")
version 2.0
Version 2.0
-----------
(to be described)
version 1.0
Version 1.0
-----------
Released with: Chamilo LMS 1.9.0

@ -45,7 +45,11 @@ $strings['tool_enable_help'] = "Choose whether you want to enable the BigBlueBut
Once enabled, it will show as an additional course tool in all courses' homepage, and teachers will be able to launch a conference at any time. Students will not be able to launch a conference, only join one. If you don't have a BigBlueButton server, please <a target=\"_blank\" href=\"http://bigbluebutton.org/\">set one up</a> or ask the Chamilo official providers for a quote. BigBlueButton is a free (as in freedom *and* beer), but its installation requires a set of technical skills that might not be immediately available to all. You can install it on your own or seek professional help to assist you or do it for you. This help, however, will generate a certain cost. In the pure logic of the free software, we offer you the tools to make your work easier and recommend professionals (the Chamilo Official Providers) that will be able to help you if this were too difficult.<br />";
$strings['big_blue_button_welcome_message'] = 'Welcome message';
$strings['enable_global_conference'] = 'Enable global conference';
$strings['enable_conference_in_course_groups'] = 'Enable conference in course groups';
$strings['big_blue_button_record_and_store'] = 'Record and store sessions';
$strings['bbb_enable_conference_in_groups'] = 'Allow conference in groups';
$strings['plugin_tool_bbb'] = 'Video';

@ -13,38 +13,28 @@ $strings['CloseMeeting'] = "Fermer la session";
$strings['VideoConferenceXCourseX'] = "Vidéoconférence #%s, cours %s";
$strings['VideoConferenceAddedToTheCalendar'] = "Vidéoconférence ajoutée au calendrier";
$strings['VideoConferenceAddedToTheLinkTool'] = "Vidéoconférence ajoutée comme lien. Vous pouvez éditer et publier le lien sur la page principale du cours depuis l'outil liens.";
$strings['GoToTheVideoConference'] = "Entrer dans la salle de conférence";
$strings['Records'] = "Enregistrement";
$strings['Meeting'] = "Salle de conférence";
$strings['ViewRecord'] = "Voir l'enregistrement";
$strings['CopyToLinkTool'] = "Ajouter comme lien du cours";
$strings['EnterConference'] = "Entrer dans la salle de conférence";
$strings['RecordList'] = "Liste des enregistrements";
$strings['ServerIsNotRunning'] = "Le serveur de vidéoconférence ne fonctionne pas";
$strings['ServerIsNotConfigured'] = "Le serveur de vidéoconférence n'est pas configuré correctement";
$strings['XUsersOnLine'] = "%s utilisateurs dans la salle";
$strings['host'] = 'Hôte de BigBlueButton';
$strings['host_help'] = "C'est le nom du serveur où le serveur de vidéoconférence a été habilité. Cela peut être localhost, une adresse IP (du genre 192.168.13.54) ou un nom de domaine (du genre ma.video.com).";
$strings['salt'] = 'Clef BigBlueButton';
$strings['salt_help'] = "C'est la clef de sécurité de votre serveur BigBlueButton (appelée 'salt' en anglais) qui permet à votre serveur de vérifier l'identité de votre installation de Chamilo et ainsi l'autoriser à se connecter. Veuillez vous référer à la documentation de BigBlueButton pour la localiser, ou utilisez la commande 'bbb-conf --salt' si vous disposez d'un accès en ligne de commande au serveur de vidéoconférence.";
$strings['tool_enable'] = 'Outil de vidéoconférence BigBlueButton activé';
$strings['tool_enable_help'] = "Choisissez si vous souhaitez activer l'outil de vidéoconférence BigBlueButton.
Une fois activé, il apparaîtra comme un outil additionnel sur toutes les pages principales de cours, et les enseignants pourront démarrer une conférence à n'importe quel moment. Les étudiants ne pourront pas lancer de nouvelle session de conférence, seulement se joindre à une session existante. Si vous ne disposez pas d'un serveur de vidéoconférence BigBlueButton, veuillez <a target=\"_blank\" href=\"http://bigbluebutton.org/\">en installer un</a> avant de poursuivre, ou demander un devis à l'un des fournisseurs officiels de Chamilo. BigBlueButton est un outil de logiciel libre (et gratuit), mais son installation pourrait présenter une certaine complexité et demander des compétences qui ne sont peut-être pas à la portée de tous. Vous pouvez l'installer vous-même à partir de la documentation (disponible publiquement) de BigBlueButton, ou recherchez un soutien professionnel. Ce soutien pourrait générer certains coûts (au moins le temps de la personne qui vous assiste dans l'opération). Dans le plus pur esprit du logiciel libre, nous vous fournissons les outils pour simplifier votre travail dans la mesure de nos possibilités, et nous vous recommandons des professionnels (les fournisseurs officiels de Chamilo) pour vous venir en aide au cas où ceux-ci seraient insuffisants.<br />";
$strings['big_blue_button_welcome_message'] = 'Message de bienvenue de BigBlueButton';
$strings['big_blue_button_record_and_store'] = 'Enregistrer les sessions de vidéoconférence';
$strings['bbb_enable_conference_in_groups'] = 'Permettre la création de vidéoconférence pour les groupes';
$strings['plugin_tool_bbb'] = 'Vidéo';
$strings['ThereAreNotRecordingsForTheMeetings'] = 'Aucun enregistrement disponible';
$strings['NoRecording'] = "Pas d'enregistrement";
$strings['ClickToContinue'] = 'Cliquez pour continuer';

@ -40,7 +40,8 @@ $strings['tool_enable_help'] = "Escoja si desea activar la herramienta de videoc
Una vez activada, se mostrará como una herramienta adicional en todas las páginas principales de cursos, y los profesores podrán iniciar una conferencia en cualquier momento. Los estudiantes no podrían lanzar una conferencia, solo juntarse a una existente. Si no tiene un servidor de videoconferencia BigBlueButton, por favor <a target=\"_blank\" href=\"http://bigbluebutton.org/\">configure uno</a> antes de seguir, o pida una cotización a uno de los proveedores oficiales de Chamilo. BigBlueButton es una herramienta de software libre (y gratuita), pero su instalación requiere de competencias que quizás no sean inmediatamente disponibles para todos. Puede instalarla usted mismo o buscar ayuda profesional. Esta ayuda podría no obstante generar algunos costos (por lo menos el tiempo de la persona quien lo ayude). En el puro espíritu del software libre, le ofrecemos las herramientas para hacer su trabajo más simple, en la medida de nuestras posibilidades, y le recomendamos profesionales (los proveedores oficiales de Chamilo) para ayudarlo en caso esto fuera demasiado complicado.<br />";
$strings['big_blue_button_welcome_message'] = 'Mensaje de bienvenida de BigBlueButton';
$strings['big_blue_button_record_and_store'] = 'Grabar las sesiones de videoconferencia';
$strings['big_blue_button_record_and_store'] = 'Grabar las sesiones de videoconferencia.';
$strings['bbb_enable_conference_in_groups'] = 'Activar la creación de videoconferencia en los grupos.';
$strings['plugin_tool_bbb'] = 'Video';

@ -20,19 +20,21 @@ class bbb
public $url;
public $salt;
public $api;
public $user_complete_name = '';
public $userCompleteName = '';
public $protocol = 'http://';
public $debug = false;
public $logoutUrl = '';
public $pluginEnabled = false;
public $enableGlobalConference = false;
public $isGlobalConference = false;
public $groupSupport = false;
/**
* Constructor (generates a connection to the API and the Chamilo settings
* required for the connection to the video conference server)
* @param string $host
* @param string $salt
* @param bool $isGlobalConference
*/
public function __construct($host = '', $salt = '', $isGlobalConference = false)
{
@ -49,9 +51,22 @@ class bbb
$this->enableGlobalConference = $plugin->get('enable_global_conference');
$this->isGlobalConference = (bool) $isGlobalConference;
$columns = Database::listTableColumns($this->table);
$this->groupSupport = isset($columns['group_id']) ? true : false;
if ($this->groupSupport) {
$this->groupSupport = (bool) $plugin->get('enable_conference_in_course_groups');
if ($this->groupSupport) {
$courseInfo = api_get_course_info();
if ($courseInfo) {
$this->groupSupport = api_get_course_setting('bbb_enable_conference_in_groups') === '1';
}
}
}
if ($bbbPlugin === true) {
$userInfo = api_get_user_info();
$this->user_complete_name = $userInfo['complete_name'];
$this->userCompleteName = $userInfo['complete_name'];
$this->salt = $bbb_salt;
$info = parse_url($bbb_host);
$this->url = $bbb_host.'/bigbluebutton/';
@ -90,6 +105,14 @@ class bbb
return (bool) $this->isGlobalConference;
}
/**
* @return bool
*/
public function hasGroupSupport()
{
return $this->groupSupport;
}
/**
* Checks whether a user is teacher in the current course
* @return bool True if the user can be considered a teacher in this course, false otherwise
@ -129,7 +152,8 @@ class bbb
# a user joins. If after this period, a user hasn't joined, the meeting is
# removed from memory.
defaultMeetingCreateJoinDuration=5
*
*
* @return mixed
*/
public function createMeeting($params)
{
@ -137,6 +161,10 @@ class bbb
$params['c_id'] = api_get_course_int_id();
$params['session_id'] = api_get_session_id();
if ($this->hasGroupSupport()) {
$params['group_id'] = api_get_group_id();
}
$params['attendee_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $courseCode;
$attendeePassword = $params['attendee_pw'];
$params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->getModMeetingPassword();
@ -166,7 +194,7 @@ class bbb
error_log("create_meeting: $id ");
}
$meetingName = isset($params['meeting_name']) ? $params['meeting_name'] : api_get_course_id().'-'.api_get_session_id();
$meetingName = isset($params['meeting_name']) ? $params['meeting_name'] : $this->getCurrentVideoConferenceName();
$welcomeMessage = isset($params['welcome_msg']) ? $params['welcome_msg'] : null;
$record = isset($params['record']) && $params['record'] ? 'true' : 'false';
$duration = isset($params['duration']) ? intval($params['duration']) : 0;
@ -235,17 +263,31 @@ class bbb
$courseId = api_get_course_int_id();
$sessionId = api_get_session_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? AND meeting_name = ? AND status = 1 ' =>
array($courseId, $sessionId, $meetingName)
)
);
if ($this->hasGroupSupport()) {
$groupId = api_get_group_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? AND meeting_name = ? AND group_id = ? AND status = 1 ' =>
array($courseId, $sessionId, $meetingName, $groupId)
)
);
}
$meetingData = Database::select(
'*',
$this->table,
array(
'where' => array(
'c_id = ? AND session_id = ? AND meeting_name = ? AND status = 1 ' =>
array($courseId, $sessionId, $meetingName)
)
),
$conditions,
'first'
);
if ($this->debug) {
error_log("meeting_exists ".print_r($meetingData, 1));
}
@ -345,7 +387,7 @@ class bbb
if ($meetingInfoExists) {
$joinParams = array(
'meetingId' => $meetingData['remote_id'], // -- REQUIRED - A unique id for the meeting
'username' => $this->user_complete_name, //-- REQUIRED - The name that will display for the user in the meeting
'username' => $this->userCompleteName, //-- REQUIRED - The name that will display for the user in the meeting
'password' => $pass, //-- REQUIRED - The attendee or moderator password, depending on what's passed here
//'createTime' => api_get_utc_datetime(), //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
'userID' => api_get_user_id(), //-- OPTIONAL - string
@ -396,17 +438,32 @@ class bbb
public function getMeetings()
{
$pass = $this->getUserMeetingPassword();
$courseId = api_get_course_int_id();
$sessionId = api_get_session_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? ' => array(
$courseId,
$sessionId,
),
),
);
if ($this->hasGroupSupport()) {
$groupId = api_get_group_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? AND group_id = ? ' =>
array($courseId, $sessionId, $groupId)
)
);
}
$meetingList = Database::select(
'*',
$this->table,
array(
'where' => array(
'c_id = ? AND session_id = ? ' => array(
api_get_course_int_id(),
api_get_session_id(),
),
),
)
$conditions
);
$isGlobal = $this->isGlobalConference();
$newMeetingList = array();
@ -614,7 +671,7 @@ class bbb
if ($meetingDB['status'] == 1) {
$joinParams = array(
'meetingId' => $meetingDB['remote_id'], //-- REQUIRED - A unique id for the meeting
'username' => $this->user_complete_name, //-- REQUIRED - The name that will display for the user in the meeting
'username' => $this->userCompleteName, //-- REQUIRED - The name that will display for the user in the meeting
'password' => $pass, //-- REQUIRED - The attendee or moderator password, depending on what's passed here
'createTime' => '', //-- OPTIONAL - string. Leave blank ('') unless you set this correctly.
'userID' => '', // -- OPTIONAL - string
@ -732,12 +789,35 @@ class bbb
{
$courseId = api_get_course_int_id();
$sessionId = api_get_session_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? AND status = 1 ' => array(
$courseId,
$sessionId,
),
),
);
if ($this->hasGroupSupport()) {
$groupId = api_get_group_id();
$conditions = array(
'where' => array(
'c_id = ? AND session_id = ? AND group_id = ? AND status = 1 ' => array(
$courseId,
$sessionId,
$groupId
),
),
);
}
$meetingData = Database::select(
'*',
$this->table,
array('where' => array('c_id = ? AND session_id = ? AND status = 1 ' => array($courseId, $sessionId))),
$conditions,
'first'
);
if (empty($meetingData)) {
return 0;
}
@ -850,7 +930,7 @@ class bbb
}
/**
* Checks if the videoconference server is running.
* Checks if the video conference server is running.
* Function currently disabled (always returns 1)
* @return bool True if server is running, false otherwise
* @assert () === false
@ -890,12 +970,6 @@ class bbb
header("Location: $url");
exit;
}
// js
/*echo '<script>';
echo 'window.location = "'.$url.'"';
echo '</script>';
exit;*/
}
/**
@ -926,6 +1000,11 @@ class bbb
return 'url_'.api_get_current_access_url_id();
}
if ($this->hasGroupSupport()) {
return api_get_course_id().'-'.api_get_session_id().'-'.api_get_group_id();
}
return api_get_course_id().'-'.api_get_session_id();
}

@ -17,12 +17,16 @@ class BBBPlugin extends Plugin
public $isCoursePlugin = true;
// When creating a new course this settings are added to the course
public $course_settings = array(
array(
public $course_settings = [
[
'name' => 'big_blue_button_record_and_store',
'type' => 'checkbox'
)
);
'type' => 'checkbox',
],
[
'name' => 'bbb_enable_conference_in_groups',
'type' => 'checkbox',
]
];
/**
* BBBPlugin constructor.
@ -30,17 +34,36 @@ class BBBPlugin extends Plugin
protected function __construct()
{
parent::__construct(
'2.3',
'2.4',
'Julio Montoya, Yannick Warnier',
[
'tool_enable' => 'boolean',
'host' => 'text',
'salt' => 'text',
'enable_global_conference' => 'boolean',
'enable_conference_in_course_groups' => 'boolean',
]
);
}
/**
* @param string $variable
* @return bool
*/
public function validateCourseSetting($variable)
{
if ($variable == 'bbb_enable_conference_in_groups') {
if ($this->get('enable_conference_in_course_groups') === 'true') {
return true;
} else {
return false;
}
}
return true;
}
/**
* @return BBBPlugin|null
*/
@ -59,6 +82,7 @@ class BBBPlugin extends Plugin
$sql = "CREATE TABLE IF NOT EXISTS $table (
id INT unsigned NOT NULL auto_increment PRIMARY KEY,
c_id INT unsigned NOT NULL DEFAULT 0,
group_id INT unsigned NOT NULL DEFAULT 0,
meeting_name VARCHAR(255) NOT NULL DEFAULT '',
attendee_pw VARCHAR(255) NOT NULL DEFAULT '',
moderator_pw VARCHAR(255) NOT NULL DEFAULT '',
@ -75,7 +99,7 @@ class BBBPlugin extends Plugin
)";
Database::query($sql);
//Installing course settings
// Installing course settings
$this->install_course_fields_in_all_courses();
}
@ -88,25 +112,26 @@ class BBBPlugin extends Plugin
$t_options = Database::get_main_table(TABLE_MAIN_SETTINGS_OPTIONS);
$t_tool = Database::get_course_table(TABLE_TOOL_LIST);
// New settings
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_tool_enable'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_salt'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_host'";
Database::query($sql);
$variables = [
'bbb_salt',
'bbb_host',
'bbb_tool_enable',
'enable_global_conference',
'enable_conference_in_course_groups',
'bbb_plugin',
'bbb_plugin_host',
'bbb_plugin_salt'
];
foreach ($variables as $variable) {
$sql = "DELETE FROM $t_settings WHERE variable = '$variable'";
Database::query($sql);
}
//Old settings deleting just in case
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_plugin'";
Database::query($sql);
$sql = "DELETE FROM $t_options WHERE variable = 'bbb_plugin'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_plugin_host'";
Database::query($sql);
$sql = "DELETE FROM $t_settings WHERE variable = 'bbb_plugin_salt'";
Database::query($sql);
//hack to get rid of Database::query warning (please add c_id...)
// hack to get rid of Database::query warning (please add c_id...)
$sql = "DELETE FROM $t_tool WHERE name = 'bbb' AND c_id != 0";
Database::query($sql);
@ -114,7 +139,7 @@ class BBBPlugin extends Plugin
$sql = "DROP TABLE IF EXISTS $t";
Database::query($sql);
//Deleting course settings
// Deleting course settings
$this->uninstall_course_fields_in_all_courses($this->course_settings);
}
}

@ -105,6 +105,7 @@ if ($conferenceManager) {
break;
}
}
$meetings = $bbb->getMeetings();
if (!empty($meetings)) {

@ -488,13 +488,6 @@ class TestMainApi extends UnitTestCase {
$this->assertTrue($_plugins[$location]);
}
function testApiIsPluginInstalled(){
$plugin_name = false;
$plugin_list = true;
$res = api_is_plugin_installed($plugin_list, $plugin_name);
$this->assertTrue(is_bool($res));
}
function testApiTimeToHms(){
$seconds = -1;
ob_start();

Loading…
Cancel
Save