Browse Source

Merge 1.11.x

jmontoyaa 8 years ago
parent
commit
3c897e9545

+ 15 - 17
.travis.yml

@@ -12,6 +12,15 @@ before_install:
   - sudo apt-get update -qq
   - sudo apt-get install -qq mysql-server
   - sudo apt-get install -qq apache2 libapache2-mod-fastcgi
+  # enable php-fpm
+  - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
+  - sudo a2enmod rewrite actions fastcgi alias
+  - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
+  # configure apache virtual hosts
+  - sudo cp -f tests/travis-apache /etc/apache2/sites-available/default
+  - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/default
+  - sudo service apache2 restart
   # Install additional PHP packages (check http://docs.travis-ci.com/user/ci-environment/#CI-environment-OS
   # for pre-installed packages)
   #- sudo apt-get install -qq php5-imagick
@@ -19,17 +28,15 @@ before_install:
   # php is compiled with --enable-fpm, so no install of FPM is needed.
   # However, not installing it generates errors with service php5-fpm restart
   # further down (need to use php-fpm without 5)
-  - sudo apt-get install -qq php5-cli php5-fpm
+  #- sudo apt-get install -qq php5-cli php5-fpm
 
 before_script:
-  - php5 -v
-  - php5 -m
-  - composer self-update
+  - php -d memory_limit=2G $(which composer) -v update
   # Previously, fxp/composer-asset-plugin was required but was causing a lot of trouble updating. Now it's disabled.
   #- composer global require "fxp/composer-asset-plugin:1.0.3"
   # You can either use the composer install method and face the Github limit
   #- composer install -n
-  - composer update
+  #- composer update
   # ...OR you can try the option --prefer-dist, that will reuse composer packages cache
   #- composer update --prefer-dist
   # ...OR you can try the --prefer-source option to download from source whenever it's possible (but it's much slower)
@@ -43,23 +50,14 @@ before_script:
   # Continue...
   - phpenv config-add tests/travis-php-config.ini
   # enable php-fpm
-  - sudo /etc/init.d/php5-fpm stop
-  - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
-  - sudo a2enmod rewrite actions fastcgi alias
-  - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-  - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm
   # configure apache virtual hosts
-  - sudo cp -f tests/travis-apache /etc/apache2/sites-available/default
-  - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/default
-  - sudo service apache2 restart
-  - sudo service php5-fpm restart
-  - php5 -v
+  - php -v
   # install Chash, a database, and then install Chamilo
   - git clone https://github.com/chamilo/chash
   - cd chash
   - composer install
   - composer update
-  - php5 -d phar.readonly=0 createPhar.php
+  - php -d phar.readonly=0 createPhar.php
   - chmod +x chash.phar
   - sudo mv chash.phar /usr/local/bin/chash
   #- cd ..
@@ -74,7 +72,7 @@ before_script:
   - cd /home/travis/build/chamilo/chamilo-lms
   # There's an issue with Chash, starting in version 1.10, whereby PHP CLI on Travis-ci is PHP5.3, whatever the version you ask for.
   # This effectively breaks the installer and renders these tests useless. We are looking for a solution (for example using containers)
-  - sudo chash chash:chamilo_install --no-interaction --sitename="Chamilo" --site_url="http://localhost/" --institution="Chamilo" --institution_url="https://chamilo.org" --encrypt_method="sha1" --firstname="John" --lastname="Doe" --language="english" --driver="mysqlnd" --host="localhost" --port="3306" --dbname="chamilo" --dbuser="root" --permissions_for_new_directories="0777" --permissions_for_new_files="0666" --linux-user="www-data" --linux-group="www-data" --username="admin" --password="admin" --email="admin@example.com" --phone="555-5555" 1.10.x
+  - sudo chash chash:chamilo_install --no-interaction --sitename="Chamilo" --site_url="http://localhost/" --institution="Chamilo" --institution_url="https://chamilo.org" --encrypt_method="sha1" --firstname="John" --lastname="Doe" --language="english" --driver="pdo_mysql" --host="localhost" --port="3306" --dbname="chamilo" --dbuser="root" --permissions_for_new_directories="0777" --permissions_for_new_files="0666" --linux-user="www-data" --linux-group="www-data" --username="admin" --password="admin" --email="admin@example.com" --phone="555-5555" 1.10.x
 
 script:
   # - phpunit -c tests/phpunit

+ 8 - 0
app/Resources/public/css/base.css

@@ -128,6 +128,14 @@ a.thumbnail:hover{
   padding-top: 10px;
   margin-top: 5px;
 }
+#toolbar-admin.navbar{
+    margin-bottom: 0;
+    border-radius: 0;
+    border: none;
+}
+header{
+    padding-top: 20px;
+}
 .blackboard_show {
     float:left;
     position:absolute;

+ 3 - 3
main/glossary/glossary_ajax_request.php

@@ -46,14 +46,14 @@ if (isset($_POST['glossary_id']) &&
     $my_glossary_name = api_convert_encoding($my_glossary_name, $charset, 'UTF-8');
     $my_glossary_name = trim($my_glossary_name);
 
-    $glossary_description = GlossaryManager::get_glossary_term_by_glossary_name(
+    $glossaryInfo = GlossaryManager::get_glossary_term_by_glossary_name(
         $my_glossary_name
     );
-
+    
     $glossary_description = str_replace(
         $path_image_search,
         $path_image,
-        $glossary_description
+        $glossaryInfo['description']
     );
 
     if (is_null($glossary_description) || strlen(trim($glossary_description)) == 0) {

+ 76 - 27
main/glossary/index.php

@@ -63,21 +63,21 @@ switch ($action) {
         $form->addElement('header', get_lang('TermAddNew'));
         $form->addElement(
             'text',
-            'glossary_title',
+            'name',
             get_lang('TermName'),
             array('id' => 'glossary_title')
         );
 
         $form->addElement(
             'html_editor',
-            'glossary_comment',
+            'description',
             get_lang('TermDefinition'),
             null,
             array('ToolbarSet' => 'Glossary', 'Height' => '300')
         );
         $form->addButtonCreate(get_lang('TermAddButton'), 'SubmitGlossary');
         // setting the rules
-        $form->addRule('glossary_title', get_lang('ThisFieldIsRequired'), 'required');
+        $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
         // The validation or display
         if ($form->validate()) {
             $check = Security::check_token('post');
@@ -110,41 +110,46 @@ switch ($action) {
             // Setting the form elements
             $form->addElement('header', get_lang('TermEdit'));
             $form->addElement('hidden', 'glossary_id');
-            $form->addElement('text', 'glossary_title', get_lang('TermName'));
+            $form->addElement('text', 'name', get_lang('TermName'));
 
             $form->addElement(
                 'html_editor',
-                'glossary_comment',
+                'description',
                 get_lang('TermDefinition'),
                 null,
                 array('ToolbarSet' => 'Glossary', 'Height' => '300')
             );
-            $element = $form->addElement('text', 'insert_date', get_lang('CreationDate'));
-            $element->freeze();
-            $element = $form->addElement('text', 'update_date', get_lang('UpdateDate'));
-            $element->freeze();
-            $form->addButtonUpdate(get_lang('TermUpdateButton'), 'SubmitGlossary');
 
             // setting the defaults
             $glossary_data = GlossaryManager::get_glossary_information($_GET['glossary_id']);
 
             // Date treatment for timezones
             if (!empty($glossary_data['insert_date'])) {
-                $glossary_data['insert_date'] = api_get_local_time($glossary_data['insert_date']);
+                $glossary_data['insert_date'] = Display::tip(
+                    date_to_str_ago($glossary_data['insert_date']),
+                    api_get_local_time($glossary_data['insert_date'])
+                );
             } else {
-                $glossary_data['insert_date']  = '';
+                $glossary_data['insert_date'] = '';
             }
 
             if (!empty($glossary_data['update_date'])) {
-                $glossary_data['update_date'] = api_get_local_time($glossary_data['update_date']);
+                $glossary_data['update_date'] = Display::tip(
+                    date_to_str_ago($glossary_data['update_date']),
+                    api_get_local_time($glossary_data['update_date'])
+                );
             } else {
-                $glossary_data['update_date']  = '';
+                 $glossary_data['update_date'] = '';
             }
 
+            $form->addLabel(get_lang('CreationDate'), $glossary_data['insert_date']);
+            $form->addLabel(get_lang('UpdateDate'), $glossary_data['update_date']);
+
+            $form->addButtonUpdate(get_lang('TermUpdateButton'), 'SubmitGlossary');
             $form->setDefaults($glossary_data);
 
             // setting the rules
-            $form->addRule('glossary_title', get_lang('ThisFieldIsRequired'), 'required');
+            $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
 
             // The validation or display
             if ($form->validate()) {
@@ -193,7 +198,10 @@ switch ($action) {
         );
         $form->addElement('header', '', get_lang('ImportGlossary'));
         $form->addElement('file', 'file', get_lang('ImportCSVFileLocation'));
+
         $form->addElement('checkbox', 'replace', null, get_lang('DeleteAllGlossaryTerms'));
+        $form->addElement('checkbox', 'update', null, get_lang('UpdateExistingGlossaryTerms'));
+
         $form->addButtonImport(get_lang('Import'), 'SubmitImport');
         $content = $form->returnForm();
 
@@ -201,21 +209,31 @@ switch ($action) {
         $content .= '<pre>
                 <strong>term</strong>;<strong>definition</strong>;
                 "Hello";"Hola";
-                "Good";"Bueno";</pre>';
+                "Goodbye";"Adiós";
+        </pre>';
 
         if ($form->validate()) {
+            $termsDeleted = [];
+
             //this is a bad idea //jm
             if (isset($_POST['replace']) && $_POST['replace']) {
                 foreach (GlossaryManager::get_glossary_terms() as $term) {
-                    if (!GlossaryManager::delete_glossary($term['id'])) {
+                    if (!GlossaryManager::delete_glossary($term['id'], false)) {
                         Display::addFlash(
                             Display::return_message(get_lang("CannotDeleteGlossary") . ':' . $term['id'], 'error')
                         );
+                    } else {
+                        $termsDeleted[] = $term['name'];
                     }
                 }
             }
+
+            $updateTerms = isset($_POST['update']) && $_POST['update'] ? true : false;
+
             $data = Import::csv_reader($_FILES['file']['tmp_name']);
             $goodList = [];
+            $updatedList = [];
+            $addedList = [];
             $badList = [];
             $doubles = [];
             $added = [];
@@ -225,20 +243,22 @@ switch ($action) {
                 $termsToAdd = [];
                 foreach ($data as $item) {
                     $items = [
-                        'glossary_title' => $item['term'],
-                        'glossary_comment' => $item['definition']
+                        'name' => $item['term'],
+                        'description' => $item['definition']
                     ];
                     $termsToAdd[] = $items;
                     $termsPerKey[$item['term']] = $items;
                 }
 
                 if (empty($termsToAdd)) {
-                    Display::return_message(get_lang("NothingToAdd"), 'warning');
+                    Display::addFlash(
+                        Display::return_message(get_lang('NothingToAdd'), 'warning')
+                    );
                     header('Location: '.$currentUrl);
                     exit;
                 }
 
-                $repeatItems = array_count_values(array_column($termsToAdd, 'glossary_title'));
+                $repeatItems = array_count_values(array_column($termsToAdd, 'name'));
                 foreach ($repeatItems as $item => $count) {
                     if ($count > 1) {
                         $doubles[] = $item;
@@ -249,19 +269,48 @@ switch ($action) {
 
                 foreach ($uniqueTerms as $itemTerm) {
                     $item = $termsPerKey[$itemTerm];
-                    $result = GlossaryManager::save_glossary($item, false);
 
-                    if ($result) {
-                        $goodList[] = $item['glossary_title'];
+                    if ($updateTerms) {
+                        $glossaryInfo = GlossaryManager::get_glossary_term_by_glossary_name($item['name']);
+
+                        if (!empty($glossaryInfo)) {
+                            $glossaryInfo['description'] = $item['description'];
+                            GlossaryManager::update_glossary($glossaryInfo, false);
+                            $updatedList[] = $item['name'];
+                        } else {
+                            $result = GlossaryManager::save_glossary($item, false);
+                            if ($result) {
+                                $addedList[] = $item['name'];
+                            } else {
+                                $badList[] = $item['name'];
+                            }
+                        }
                     } else {
-                        $badList[] = $item['glossary_title'];
+                        $result = GlossaryManager::save_glossary($item, false);
+                        if ($result) {
+                            $addedList[] = $item['name'];
+                        } else {
+                            $badList[] = $item['name'];
+                        }
                     }
                 }
             }
 
-            if (count($goodList) > 0) {
+            if (count($termsDeleted) > 0) {
+                Display::addFlash(
+                    Display::return_message(get_lang("TermDeleted").': '.implode(', ', $termsDeleted))
+                );
+            }
+
+            if (count($updatedList) > 0) {
+                Display::addFlash(
+                    Display::return_message(get_lang("TermsUpdated").': '.implode(', ', $updatedList))
+                );
+            }
+
+            if (count($addedList) > 0) {
                 Display::addFlash(
-                    Display::return_message(get_lang("TermsImported").': '.implode(', ', $goodList))
+                    Display::return_message(get_lang("TermsAdded").': '.implode(', ', $addedList))
                 );
             }
 

+ 12 - 2
main/inc/ajax/model.ajax.php

@@ -1074,13 +1074,23 @@ switch ($action) {
                 } else {
                     $session_date_string = implode(' ', $session_date);
                 }
-                $sessionUrl = api_get_path(WEB_CODE_PATH).'mySpace/course.php?session_id='.$session['id'];
+
+                $detailButtons = [];
+                $detailButtons[] = Display::url(
+                    Display::return_icon('works.png', get_lang('Works')),
+                    api_get_path(WEB_CODE_PATH) . 'mySpace/works.php'
+                );
+                $detailButtons[] = Display::url(
+                    Display::return_icon('2rightarrow.png'),
+                    api_get_path(WEB_CODE_PATH) . 'mySpace/course.php?session_id=' . $session['id']
+                );
+
                 $result[] = array(
                     'name' => $session['name'],
                     'date' => $session_date_string,
                     'course_per_session' => $count_courses_in_session,
                     'student_per_session' => $count_users_in_session,
-                    'details' => Display::url(Display::return_icon('2rightarrow.png'), $sessionUrl)
+                    'details' => implode(' ', $detailButtons)
                 );
             }
         }

+ 82 - 95
main/inc/lib/glossary.lib.php

@@ -7,6 +7,11 @@ use ChamiloSession as Session;
  * Class GlossaryManager
  * This library provides functions for the glossary tool.
  * Include/require it in your code to use its functionality.
+ *
+ * @author Julio Montoya
+ * @author Christian Fasanando
+ * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium januari 2009, dokeos 1.8.6
+ *
  * @package chamilo.library
  */
 class GlossaryManager
@@ -63,7 +68,7 @@ class GlossaryManager
      * @author Isaac Flores <florespaz_isaac@hotmail.com>
      * @param string $glossary_name The glossary term name
      *
-     * @return string The glossary description
+     * @return array The glossary info
      */
     public static function get_glossary_term_by_glossary_name($glossary_name)
     {
@@ -71,33 +76,31 @@ class GlossaryManager
         $session_id = api_get_session_id();
         $course_id = api_get_course_int_id();
         $sql_filter = api_get_session_condition($session_id);
-        $sql = 'SELECT description FROM '.$glossary_table.'
+        $sql = 'SELECT * FROM '.$glossary_table.'
 		        WHERE
 		            c_id = '.$course_id.' AND
 		            name LIKE trim("'.Database::escape_string($glossary_name).'")'.$sql_filter;
         $rs = Database::query($sql);
         if (Database::num_rows($rs) > 0) {
-            $row = Database::fetch_array($rs);
-
-            return $row['description'];
-        } else {
+            $row = Database::fetch_array($rs, 'ASSOC');
 
-            return '';
+            return $row;
         }
+
+        return [];
     }
 
     /**
      * This functions stores the glossary in the database
      *
-     * @param array    Array of title + description (glossary_title => $title, glossary_comment => $comment)
+     * @param array  $values  Array of title + description (name => $title, description => $comment)
+     *
      * @return mixed   Term id on success, false on failure
-     * @author Christian Fasanando <christian.fasanando@dokeos.com>
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
+     *
      */
     public static function save_glossary($values, $showMessage = true)
     {
-        if (!is_array($values) || !isset($values['glossary_title'])) {
+        if (!is_array($values) || !isset($values['name'])) {
             return false;
         }
 
@@ -111,7 +114,7 @@ class GlossaryManager
         $session_id = api_get_session_id();
 
         // check if the glossary term already exists
-        if (GlossaryManager::glossary_exists($values['glossary_title'])) {
+        if (GlossaryManager::glossary_exists($values['name'])) {
             // display the feedback message
             if ($showMessage) {
                 Display::addFlash(
@@ -124,8 +127,8 @@ class GlossaryManager
             $params = [
                 'glossary_id' => 0,
                 'c_id' => api_get_course_int_id(),
-                'name' => $values['glossary_title'],
-                'description' => $values['glossary_comment'],
+                'name' => $values['name'],
+                'description' => $values['description'],
                 'display_order' => $max_glossary_item + 1,
                 'session_id' => $session_id,
             ];
@@ -160,33 +163,33 @@ class GlossaryManager
      *
      * @param array $values an array containing all the form elements
      * @return boolean True on success, false on failure
-     * @author Christian Fasanando <christian.fasanando@dokeos.com>
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
-    public static function update_glossary($values)
+    public static function update_glossary($values, $showMessage = true)
     {
         // Database table definition
         $t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
         $course_id = api_get_course_int_id();
 
         // check if the glossary term already exists
-        if (GlossaryManager::glossary_exists($values['glossary_title'], $values['glossary_id'])) {
+        if (GlossaryManager::glossary_exists($values['name'], $values['glossary_id'])) {
             // display the feedback message
-            Display::addFlash(
-                Display::return_message(get_lang('GlossaryTermAlreadyExistsYouShouldEditIt'), 'error')
-            );
+            if ($showMessage) {
+                Display::addFlash(
+                    Display::return_message(get_lang('GlossaryTermAlreadyExistsYouShouldEditIt'), 'error')
+                );
+            }
 
             return false;
         } else {
             $sql = "UPDATE $t_glossary SET
-                        name 		= '".Database::escape_string($values['glossary_title'])."',
-                        description	= '".Database::escape_string($values['glossary_comment'])."'
+                        name = '".Database::escape_string($values['name'])."',
+                        description	= '".Database::escape_string($values['description'])."'
 					WHERE
 					    c_id = $course_id AND
 					    glossary_id = ".intval($values['glossary_id']);
             $result = Database::query($sql);
             if ($result === false) {
+
                 return false;
             }
 
@@ -199,11 +202,12 @@ class GlossaryManager
                 api_get_user_id()
             );
 
-            // display the feedback message
-            Display::addFlash(
-                Display::return_message(get_lang('TermUpdated'))
-            );
-
+            if ($showMessage) {
+                // display the feedback message
+                Display::addFlash(
+                    Display::return_message(get_lang('TermUpdated'))
+                );
+            }
         }
 
         return true;
@@ -212,9 +216,6 @@ class GlossaryManager
     /**
      * Get the maximum display order of the glossary item
      * @return integer Maximum glossary display order
-     * @author Christian Fasanando <christian.fasanando@dokeos.com>
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function get_max_glossary_item()
     {
@@ -242,8 +243,6 @@ class GlossaryManager
      * @param integer  $not_id ID to counter-check if the term exists with this ID as well (optional)
      * @return bool    True if term exists
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function glossary_exists($term, $not_id = '')
     {
@@ -271,9 +270,8 @@ class GlossaryManager
      * Get one specific glossary term data
      *
      * @param integer $glossary_id ID of the flossary term
-     * @return mixed   Array(glossary_id,glossary_title,glossary_comment,glossary_display_order) or false on error
+     * @return mixed   Array(glossary_id,name,description,glossary_display_order) or false on error
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
      */
     public static function get_glossary_information($glossary_id)
     {
@@ -285,8 +283,8 @@ class GlossaryManager
         }
         $sql = "SELECT
                     g.glossary_id 		as glossary_id,
-                    g.name 				as glossary_title,
-                    g.description 		as glossary_comment,
+                    g.name 				as name,
+                    g.description 		as description,
                     g.display_order		as glossary_display_order,
                     ip.insert_date      as insert_date,
                     ip.lastedit_date    as update_date,
@@ -303,31 +301,37 @@ class GlossaryManager
         if ($result === false || Database::num_rows($result) != 1) {
             return false;
         }
+
         return Database::fetch_array($result);
     }
 
     /**
      * Delete a glossary term (and re-order all the others)
      *
-     * @param integer The id of the glossary term to delete
+     * @param integer $glossary_id
+     * @param bool $showMessage
+     *
      * @return bool    True on success, false on failure
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
-    public static function delete_glossary($glossary_id)
+    public static function delete_glossary($glossary_id, $showMessage = true)
     {
         // Database table definition
         $t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
         $course_id = api_get_course_int_id();
 
-        if (empty($glossary_id)) {
+        $glossaryInfo = self::get_glossary_information($glossary_id);
+
+        if (empty($glossaryInfo)) {
+
             return false;
         }
 
+        $glossary_id = (int) $glossary_id;
+
         $sql = "DELETE FROM $t_glossary 
                 WHERE 
                     c_id = $course_id AND 
-                    glossary_id='".intval($glossary_id)."'";
+                    glossary_id='".$glossary_id."'";
         $result = Database::query($sql);
         if ($result === false || Database::affected_rows($result) < 1) {
             return false;
@@ -337,7 +341,7 @@ class GlossaryManager
         api_item_property_update(
             api_get_course_info(),
             TOOL_GLOSSARY,
-            intval($glossary_id),
+            $glossary_id,
             'delete',
             api_get_user_id()
         );
@@ -345,9 +349,11 @@ class GlossaryManager
         // reorder the remaining terms
         GlossaryManager::reorder_glossary();
 
-        Display::addFlash(
-            Display::return_message(get_lang('TermDeleted'))
-        );
+        if ($showMessage) {
+            Display::addFlash(
+                Display::return_message(get_lang('TermDeleted').': '.$glossaryInfo['name'])
+            );
+        }
 
         return true;
     }
@@ -357,9 +363,8 @@ class GlossaryManager
      * the glossary terms
      * @param  string  View ('table' or 'list'). Optional parameter.
      * Defaults to 'table' and prefers glossary_view from the session by default.
+     *
      * @return string
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function display_glossary($view = 'table')
     {
@@ -372,14 +377,14 @@ class GlossaryManager
         // action links
         //echo '<div class="actions">';
         $actionsLeft = '';
-        if (api_is_allowed_to_edit(null,true)) {
+        if (api_is_allowed_to_edit(null, true)) {
             $actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=addglossary&msg=add?'.api_get_cidreq().'">'.
                 Display::return_icon('new_glossary_term.png',get_lang('TermAddNew'),'', ICON_SIZE_MEDIUM).'</a>';
         }
 
         $actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=export">'.
             Display::return_icon('export_csv.png',get_lang('ExportGlossaryAsCSV'),'',ICON_SIZE_MEDIUM).'</a>';
-        if (api_is_allowed_to_edit(null,true)) {
+        if (api_is_allowed_to_edit(null, true)) {
             $actionsLeft .= '<a href="index.php?'.api_get_cidreq().'&action=import">'.
                 Display::return_icon('import_csv.png',get_lang('ImportGlossary'),'',ICON_SIZE_MEDIUM).'</a>';
         }
@@ -417,7 +422,7 @@ class GlossaryManager
 
         $content = $toolbar;
 
-        if (!$view || $view == 'table') {
+        if (!$view || $view === 'table') {
             $table = new SortableTable(
                 'glossary',
                 array('GlossaryManager', 'get_number_glossary_terms'),
@@ -434,7 +439,7 @@ class GlossaryManager
             $content .= $table->return_table();
         }
 
-        if ($view == 'list') {
+        if ($view === 'list') {
             $content .= GlossaryManager::displayGlossaryList();
         }
 
@@ -443,9 +448,7 @@ class GlossaryManager
 
     /**
      * Display the glossary terms in a list
-     * @return bool    True
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
+     * @return bool true
      */
     public static function displayGlossaryList()
     {
@@ -466,8 +469,6 @@ class GlossaryManager
      * @param  int     Session ID filter (optional)
      * @return integer Count of glossary terms
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function get_number_glossary_terms($session_id=0)
     {
@@ -499,17 +500,14 @@ class GlossaryManager
     /**
      * Get all the data of a glossary
      *
-     * @param integer From which item
-     * @param integer Number of items to collect
-     * @param string  Name of column on which to order
-     * @param string  Whether to sort in ascending (ASC) or descending (DESC)
-     * @return unknown
+     * @param int $from From which item
+     * @param int $number_of_items Number of items to collect
+     * @param string  $column Name of column on which to order
+     * @param string $direction  Whether to sort in ascending (ASC) or descending (DESC)
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>
-     * @author Julio Montoya fixing this function, adding intvals
-     * @version januari 2009, dokeos 1.8.6
+     * @return array
      */
-    public static  function get_glossary_data($from, $number_of_items, $column, $direction)
+    public static function get_glossary_data($from, $number_of_items, $column, $direction)
     {
         $_user = api_get_user_info();
         $view = Session::read('glossary_view');
@@ -521,7 +519,7 @@ class GlossaryManager
         if (api_is_allowed_to_edit(null, true)) {
             $col2 = " glossary.glossary_id	as col2, ";
         } else {
-            $col2 = " ";
+            $col2 = ' ';
         }
 
         //condition for the session
@@ -568,7 +566,7 @@ class GlossaryManager
             $session_img = api_get_session_image($data['session_id'], $_user['status']);
             $array[0] = $data[0] . $session_img;
 
-            if (!$view || $view == 'table') {
+            if (!$view || $view === 'table') {
                 $array[1] = str_replace(array('<p>', '</p>'), array('', '<br />'), $data[1]);
             } else {
                 $array[1] = $data[1];
@@ -587,12 +585,10 @@ class GlossaryManager
      * Update action icons column
      *
      * @param integer $glossary_id
-     * @param array   Parameters to use to affect links
-     * @param array   The line of results from a query on the glossary table
-     * @return string HTML string for the action icons columns
+     * @param array   $url_params Parameters to use to affect links
+     * @param array   $row The line of results from a query on the glossary table
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
+     * @return string HTML string for the action icons columns
      */
     public static function actions_filter($glossary_id, $url_params, $row)
     {
@@ -600,9 +596,7 @@ class GlossaryManager
         $return = '<a href="'.api_get_self().'?action=edit_glossary&amp;glossary_id='.$glossary_id.'&'.api_get_cidreq().'&msg=edit">'.
             Display::return_icon('edit.png',get_lang('Edit'),'',22).'</a>';
         $glossary_data = GlossaryManager::get_glossary_information($glossary_id);
-
-        $glossary_term = $glossary_data['glossary_title'];
-
+        $glossary_term = $glossary_data['name'];
         if (api_is_allowed_to_edit(null, true)) {
             if ($glossary_data['session_id'] == api_get_session_id()) {
                 $return .= '<a href="'.api_get_self().'?action=delete_glossary&amp;glossary_id='.$glossary_id.'&'.api_get_cidreq().'" onclick="return confirmation(\''.$glossary_term.'\');">'.
@@ -620,26 +614,22 @@ class GlossaryManager
      *
      * @return string  HTML string including JavaScript
      *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function javascript_glossary()
     {
         return "<script>
-        function confirmation (name) {
-            if (confirm(\" ".get_lang("TermConfirmDelete")." \"+ name + \" ?\"))
-                {return true;}
-            else
-                {return false;}
-        }
+            function confirmation (name) {
+                if (confirm(\" ".get_lang("TermConfirmDelete")." \"+ name + \" ?\")) {
+                    return true;
+                } else {
+                    return false;
+                }
+            }
         </script>";
     }
 
     /**
      * Re-order glossary
-     *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function reorder_glossary()
     {
@@ -665,9 +655,6 @@ class GlossaryManager
      *
      * @param string $direction
      * @param string $glossary_id
-     *
-     * @author Patrick Cool <patrick.cool@ugent.be>, Ghent University, Belgium
-     * @version januari 2009, dokeos 1.8.6
      */
     public static function move_glossary($direction, $glossary_id)
     {
@@ -675,7 +662,7 @@ class GlossaryManager
         $t_glossary = Database :: get_course_table(TABLE_GLOSSARY);
 
         // sort direction
-        if ($direction == 'up') {
+        if ($direction === 'up') {
             $sortorder = 'DESC';
         } else {
             $sortorder = 'ASC';
@@ -730,6 +717,6 @@ class GlossaryManager
         $html .= '</body></html>';
         $courseCode = api_get_course_id();
         $pdf = new PDF();
-        $pdf->content_to_pdf($html, '', get_lang('Glossary').'_'.$courseCode, $course_code);
+        $pdf->content_to_pdf($html, '', get_lang('Glossary').'_'.$courseCode, $courseCode);
     }
 }

+ 11 - 7
main/inc/lib/internationalization.lib.php

@@ -644,15 +644,19 @@ function api_format_date($time, $format = null, $language = null)
  * Example: $date = '2008-03-07 15:44:08';
  * 			date_to_str($date) it will return 3 days, 20 hours
  * The given date should be in the timezone chosen by the user or administrator. Use api_get_local_time() to get it...
+ * You can use it like this:
+ * Display::tip(date_to_str_ago($dateInUtc), api_get_local_time($dateInUtc));
+ *
+ * @param  string $date The string has to be the result of a date function in this format -> date('Y-m-d H:i:s', time());
+ * @return string $timeZone
  *
- * @param  string The string has to be the result of a date function in this format -> date('Y-m-d H:i:s', time());
- * @return string The difference between the current date and the parameter in a literal way "3 days, 2 hour" *
  * @author Julio Montoya
  */
 
 function date_to_str_ago($date, $timeZone = 'UTC')
 {
-    if ($date == '0000-00-00 00:00:00')  {
+    if ($date === '0000-00-00 00:00:00')  {
+        
         return '';
     }
 
@@ -1965,15 +1969,15 @@ function _api_convert_encoding_supports($encoding) {
 function apiGetHumanDateTime($date, $showTime = true, $humanForm = false) {
     if ($showTime) {
         if ($humanForm) {
-           return $date->format('j M Y H:i:s');    
+           return $date->format('j M Y H:i:s');
         } else {
-           return $date->format('Y-m-d H:i:s');     
+           return $date->format('Y-m-d H:i:s');
         }
     } else {
         if ($humanForm) {
-           return $date->format('j M Y');    
+           return $date->format('j M Y');
         } else {
-           return $date->format('Y-m-d');     
+           return $date->format('Y-m-d');
         }
     }
 }

+ 57 - 39
main/inc/lib/tracking.lib.php

@@ -5,6 +5,9 @@ use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
 use CpChart\Classes\pCache as pCache;
 use CpChart\Classes\pData as pData;
 use CpChart\Classes\pImage as pImage;
+use Chamilo\UserBundle\Entity\User;
+use Chamilo\CoreBundle\Entity\Course;
+use Chamilo\CoreBundle\Entity\Session;
 
 /**
  *  Class Tracking
@@ -4299,9 +4302,7 @@ class Tracking
                 $html .= Display::page_subheader(
                     Display::return_icon('course.png', get_lang('MyCourses'), array(), ICON_SIZE_SMALL).' '.get_lang('MyCourses')
                 );
-                $html .= '<div class="table-responsive">';
-                $html .= '<table class="table table-striped table-hover">';
-                $html .= '<thead>';
+                $html .= '<table class="data_table" width="100%">';
                 $html .= '<tr>
                           '.Display::tag('th', get_lang('Course'), array('width'=>'300px')).'
                           '.Display::tag('th', get_lang('TimeSpentInTheCourse'), array('class'=>'head')).'
@@ -4310,7 +4311,6 @@ class Tracking
                           '.Display::tag('th', get_lang('LastConnexion'), array('class'=>'head')).'
                           '.Display::tag('th', get_lang('Details'), array('class'=>'head')).'
                         </tr>';
-                $html .= '</thead><tbody>';
 
                 foreach ($courses as $course_code => $course_title) {
                     $courseInfo = api_get_course_info($course_code);
@@ -4377,8 +4377,7 @@ class Tracking
                     $html .= '</a>';
                     $html .= '</td></tr>';
                 }
-                $html .= '</tbody></table>';
-                $html .= '</div>';
+                $html .= '</table>';
             }
         }
 
@@ -4489,9 +4488,7 @@ class Tracking
                 Display::return_icon('session.png', get_lang('Sessions'), array(), ICON_SIZE_SMALL) . ' ' . get_lang('Sessions')
             );
 
-            $html .= '<div class="table-responsive">';
-            $html .= '<table class="table table-striped table-hover">';
-            $html .= '<thead>';
+            $html .= '<table class="data_table" width="100%">';
             $html .= '<tr>
                   '.Display::tag('th', get_lang('Session'), array('width'=>'300px')).'
                   '.Display::tag('th', get_lang('PublishedExercises'), array('width'=>'300px')).'
@@ -4499,8 +4496,6 @@ class Tracking
                   '.Display::tag('th', get_lang('AverageExerciseResult'), array('class'=>'head')).'
                   '.Display::tag('th', get_lang('Details'), array('class'=>'head')).'
                   </tr>';
-            $html .= '</thead>';
-            $html .= '<tbody>';
 
             foreach ($course_in_session as $my_session_id => $session_data) {
                 $course_list  = $session_data['course_list'];
@@ -4577,8 +4572,7 @@ class Tracking
                 $html .= Display::tag('td', $icon);
                 $html .= '</tr>';
             }
-            $html .= '</tbody>';
-            $html .= '</table></div><br />';
+            $html .= '</table><br />';
             $html .= Display::div($main_session_graph, array('id'=>'session_graph','class'=>'chart-session', 'style'=>'position:relative; text-align: center;') );
 
             // Checking selected session.
@@ -4590,11 +4584,9 @@ class Tracking
 
                 $html .= Display::tag('h3',$session_data['name'].' - '.get_lang('CourseList'));
 
-                $html .= '<div class="table-responsive">';
-                $html .= '<table class="table table-hover table-striped">';
+                $html .= '<table class="data_table" width="100%">';
                 //'.Display::tag('th', get_lang('DoneExercises'),         array('class'=>'head')).'
                 $html .= '
-                    <thead>
                     <tr>
                       <th width="300px">'.get_lang('Course').'</th>
                       '.Display::tag('th', get_lang('PublishedExercises'),    	array('class'=>'head')).'
@@ -4606,10 +4598,7 @@ class Tracking
                       '.Display::tag('th', get_lang('Score').Display::return_icon('info3.gif', get_lang('ScormAndLPTestTotalAverage'), array ('align' => 'absmiddle', 'hspace' => '3px')), array('class'=>'head')).'
                       '.Display::tag('th', get_lang('LastConnexion'),         	array('class'=>'head')).'
                       '.Display::tag('th', get_lang('Details'),               	array('class'=>'head')).'
-                    </tr>
-                    </thead>
-                    <tbody>
-                ';
+                    </tr>';
 
                 foreach ($course_list as $course_data) {
                     $course_code  = $course_data['code'];
@@ -4726,7 +4715,7 @@ class Tracking
                     $html .= Display::tag('td', $details, array('align'=>'center'));
                     $html .= '</tr>';
                 }
-                $html .= '</tbody></table></div>';
+                $html .= '</table>';
             }
         }
 
@@ -4751,22 +4740,18 @@ class Tracking
             $course_info = CourseManager::get_course_information($course);
 
             $html .= Display::page_subheader($course_info['title']);
-            $html .= '<div class="table-responsive">';
-            $html .= '<table class="table table-striped table-hover">';
+            $html .= '<table class="data_table" width="100%">';
 
             //Course details
             $html .= '
-                <thead>
                 <tr>
-                <th>'.get_lang('Exercises').'</th>
-                <th>'.get_lang('Attempts').'</th>
-                <th>'.get_lang('BestAttempt').'</th>
-                <th>'.get_lang('Ranking').'</th>
-                <th>'.get_lang('BestResultInCourse').'</th>
-                <th>'.get_lang('Statistics').' '.Display :: return_icon('info3.gif', get_lang('OnlyBestResultsPerStudent'), array('align' => 'absmiddle', 'hspace' => '3px')).'</th>
-                </tr>
-                </thead>
-                <tbody>';
+                <th class="head" style="color:#000">'.get_lang('Exercises').'</th>
+                <th class="head" style="color:#000">'.get_lang('Attempts').'</th>
+                <th class="head" style="color:#000">'.get_lang('BestAttempt').'</th>
+                <th class="head" style="color:#000">'.get_lang('Ranking').'</th>
+                <th class="head" style="color:#000">'.get_lang('BestResultInCourse').'</th>
+                <th class="head" style="color:#000">'.get_lang('Statistics').' '.Display :: return_icon('info3.gif', get_lang('OnlyBestResultsPerStudent'), array('align' => 'absmiddle', 'hspace' => '3px')).'</th>
+                </tr>';
 
             if (empty($session_id)) {
                 $user_list = CourseManager::get_user_list_from_course_code(
@@ -4930,19 +4915,17 @@ class Tracking
             } else {
                 $html .= '<tr><td colspan="5" align="center">'.get_lang('NoEx').'</td></tr>';
             }
-            $html .= '</tbody></table></div>';
+            $html .= '</table>';
 
 
             // LP table results
-            $html .= '<div class="table-responsive">';
-            $html .='<table class="table table-striped table-hover">';
-            $html .= '<thead><tr>';
+            $html .='<table class="data_table">';
             $html .= Display::tag('th', get_lang('Learnpaths'), array('class'=>'head', 'style'=>'color:#000'));
             $html .= Display::tag('th', get_lang('LatencyTimeSpent'), array('class'=>'head', 'style'=>'color:#000'));
             $html .= Display::tag('th', get_lang('Progress'), array('class'=>'head', 'style'=>'color:#000'));
             $html .= Display::tag('th', get_lang('Score'), array('class'=>'head', 'style'=>'color:#000'));
             $html .= Display::tag('th', get_lang('LastConnexion'), array('class'=>'head', 'style'=>'color:#000'));
-            $html .= '</tr></thead><tbody>';
+            $html .= '</tr>';
 
             $list = new LearnpathList(
                 api_get_user_id(),
@@ -5000,7 +4983,7 @@ class Tracking
                         </td>
                       </tr>';
             }
-            $html .='</tbody></table></div>';
+            $html .='</table>';
 
             $html .= self::displayUserSkills($user_id, $course_info['id'], $session_id);
         }
@@ -5792,6 +5775,41 @@ class Tracking
         return $data;
     }
 
+    /**
+         * @param User $user
+         * @param string $tool
+         * @param Course $course
+         * @param Session|null $session Optional.
+         * @return \Chamilo\CourseBundle\Entity\CStudentPublication|null
+         * @throws \Doctrine\ORM\NonUniqueResultException
+         */
+        public static function getLastStudentPublication(User $user, $tool, Course $course, Session $session = null)
+        {
+            return Database::getManager()
+                ->createQuery("
+                    SELECT csp
+                    FROM ChamiloCourseBundle:CStudentPublication csp
+                    INNER JOIN ChamiloCourseBundle:CItemProperty cip
+                        WITH (
+                            csp.iid = cip.ref AND
+                            csp.sessionId = cip.session AND
+                            csp.cId = cip.course AND
+                            csp.userId = cip.lasteditUserId
+                        )
+                    WHERE
+                        cip.session = :session AND cip.course = :course AND cip.lasteditUserId = :user AND cip.tool = :tool
+                    ORDER BY csp.iid DESC
+                ")
+                ->setMaxResults(1)
+                ->setParameters([
+                    'tool' => $tool,
+                    'session' => $session,
+                    'course' => $course,
+                    'user' => $user
+                ])
+                ->getOneOrNullResult();
+        }
+
     /**
      * Get the HTML code for show a block with the achieved user skill on course/session
      * @param int $userId

+ 2 - 1
main/inc/lib/userportal.lib.php

@@ -920,7 +920,8 @@ class IndexManager
         );
 
         $setting = api_get_plugin_setting('bbb', 'enable_global_conference');
-        if ($setting === 'true') {
+        $settingLink = api_get_plugin_setting('bbb', 'enable_global_conference_link');
+        if ($setting === 'true' && $settingLink === true) {
             $url = api_get_path(WEB_PLUGIN_PATH).'bbb/start.php?global=1';
             $content = Display::url(get_lang('LaunchVideoConferenceRoom'), $url);
             $html .= self::show_right_block(

+ 0 - 1
main/install/index.php

@@ -945,7 +945,6 @@ if (@$_POST['step2']) {
         $connection->executeQuery('CREATE TABLE version (version varchar(255), PRIMARY KEY(version));');
 
         // Tickets
-
         $table = Database::get_main_table(TABLE_TICKET_PROJECT);
 
         // Default Project Table Ticket

+ 1 - 2
main/mySpace/course.php

@@ -6,7 +6,6 @@
  */
 
 ob_start();
-$nameTools = 'Cours';
 $cidReset = true;
 
 require_once '../inc/global.inc.php';
@@ -57,7 +56,7 @@ if (api_get_setting('add_users_by_coach') == 'true') {
     }
 }
 
-Display :: display_header($nameTools);
+Display :: display_header(get_lang('Courses'));
 
 $a_courses = array();
 if (api_is_drh() || api_is_session_admin() || api_is_platform_admin()) {

+ 107 - 0
main/mySpace/works.php

@@ -0,0 +1,107 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Courses reporting
+ * @package chamilo.reporting
+ */
+
+require_once '../inc/global.inc.php';
+
+if (api_is_student()) {
+    api_not_allowed(true);
+    exit;
+}
+
+$em = Database::getManager();
+$session = null;
+$sessionsInfo = SessionManager::getSessionsFollowedByUser(api_get_user_id(), COURSEMANAGER);
+$coursesData = [];
+
+$form = new FormValidator('work_report');
+$selectSession = $form->addSelect('session', get_lang('Session'), [0 => get_lang('None')]);
+$form->addButtonFilter(get_lang('Filter'));
+
+foreach ($sessionsInfo as $sessionInfo) {
+    $selectSession->addOption($sessionInfo['name'], $sessionInfo['id']);
+}
+
+if ($form->validate()) {
+    $sessionId = $form->exportValue('session');
+    $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
+}
+
+if ($session) {
+    $userSubscriptions = $session->getUsers();
+    $sessionCourses = $session->getCourses();
+
+    foreach ($sessionCourses as $sessionCourse) {
+        $course = $sessionCourse->getCourse();
+        $userCourseSubscriptions = $session->getUserCourseSubscriptionsByStatus($course, 0);
+        $courseInfo = [
+            'title' => $course->getTitle()
+        ];
+
+        $table = new HTML_Table(['class' => 'table table-hover table-striped']);
+        $table->setHeaderContents(0, 0, get_lang('OfficialCode'));
+        $table->setHeaderContents(0, 1, get_lang('StudentName'));
+        $table->setHeaderContents(0, 2, get_lang('TimeSpentOnThePlatform'));
+        $table->setHeaderContents(0, 3, get_lang('FirstLoginInPlatform'));
+        $table->setHeaderContents(0, 4, get_lang('LatestLoginInPlatform'));
+        $table->setHeaderContents(0, 5, get_lang('Course'));
+        $table->setHeaderContents(0, 6, get_lang('Progress'));
+        $table->setHeaderContents(0, 7, get_lang('SentDate'));
+
+        foreach ($userCourseSubscriptions as $userCourseSubscription) {
+            $user = $userCourseSubscription->getUser();
+            
+            $lastPublication = Tracking::getLastStudentPublication($user, 'work', $course, $session);
+            $lastPublicationFormatted = null;
+
+            if ($lastPublication) {
+                $lastPublicationFormatted = api_format_date(
+                    $lastPublication->getSentDate()->getTimestamp(),
+                    DATE_TIME_FORMAT_SHORT
+                );
+            }
+
+            $data = [
+                $user->getOfficialCode(),
+                $user->getCompleteName(),
+                api_time_to_hms(
+                    Tracking::get_time_spent_on_the_platform($user->getId())
+                ),
+                Tracking::get_first_connection_date($user->getId()),
+                Tracking::get_last_connection_date($user->getId()),
+                Tracking::get_avg_student_score($user->getId(), $course->getCode(), null, $session->getId()),
+                Tracking::get_avg_student_progress($user->getId(), $course->getCode(), null, $session->getId()),
+                $lastPublicationFormatted
+            ];
+
+            $table->addRow($data);
+        }
+
+        $coursesData[] = [
+            'title' => $course->getTitle(),
+            'detail_table' => $table->toHtml()
+        ];
+    }
+}
+
+$interbreadcrumb[] = [
+    'url' => api_get_path(WEB_CODE_PATH) . 'mySpace/index.php',
+    'name' => get_lang('MySpace')
+];
+
+$view = new Template(get_lang('WorkReport'));
+$view->assign('header', get_lang('WorkReport'));
+$view->assign('form', $form->returnForm());
+
+if ($session) {
+    $view->assign('session', ['name' => $session->getName()]);
+    $view->assign('courses', $coursesData);
+}
+
+$template = $view->get_template('my_space/works.tpl');
+$content = $view->fetch($template);
+$view->assign('content', $content);
+$view->display_one_col_template();

+ 0 - 10
main/template/default/layout/topbar.tpl

@@ -61,16 +61,6 @@
                     {% endif %}
 
                     <ul class="nav navbar-nav navbar-right">
-                        <li><a href="{{ _p.web_main }}social/home.php"><img src="{{ _u.avatar_small }}"/></a></li>
-                        <li class="dropdown">
-                            <a class="dropdown-toggle" data-toggle="dropdown"  href="#">{{ _u.complete_name }}<b class="caret"></b></a>
-                            <ul class="dropdown-menu">
-                                <li><a href="{{ _p.web_main }}social/home.php">{{ "Profile"|get_lang }}</a></li>
-                                <li><a href="{{ _p.web_main }}calendar/agenda_js.php?type=personal">{{ "MyAgenda"|get_lang }}</a></li>
-                                <li><a href="{{ _p.web_main }}messages/inbox.php">{{ "Inbox"|get_lang }}</a></li>
-                                <li><a href="{{ _p.web_main }}auth/my_progress.php">{{ "MyReporting"|get_lang }}</a></li>
-                            </ul>
-                        </li>
                         <li><a href="{{  _p.web }}index.php?logout=logout&uid={{_u.user_id}}">{{ "Logout"|get_lang }}</a></li>
                     </ul>
                 </div> <!-- /nav collapse -->

+ 8 - 0
main/template/default/my_space/works.tpl

@@ -0,0 +1,8 @@
+{{ form }}
+{% if session %}
+    <h3 class="page-header">{{ session.name }}</h3>
+    {% for course in courses %}
+        <h4>{{ course.title }}</h4>
+        {{ course.detail_table }}
+    {% endfor %}
+{% endif %}

+ 0 - 1
plugin/bbb/config.php

@@ -4,7 +4,6 @@
 /* bbb parameters that will be registered in the course settings */
 
 require_once __DIR__ . '/../../main/inc/global.inc.php';
-require_once api_get_path(LIBRARY_PATH).'plugin.class.php';
 
 require_once 'lib/bbb.lib.php';
 require_once 'lib/bbb_api.php';

+ 2 - 1
plugin/bbb/lib/bbb.lib.php

@@ -175,8 +175,9 @@ class bbb
             $params['group_id'] = api_get_group_id();
         }
 
+        $courseCode = is_null($courseCode) ? '' : $courseCode;
         $params['attendee_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $courseCode;
-        $attendeePassword =  $params['attendee_pw'];
+        $attendeePassword = $params['attendee_pw'];
         $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->getModMeetingPassword();
         $moderatorPassword = $params['moderator_pw'];
 

+ 3 - 1
plugin/bbb/lib/bbb_plugin.class.php

@@ -42,6 +42,7 @@ class BBBPlugin extends Plugin
                 'salt' => 'text',
                 'enable_global_conference' => 'boolean',
                 'enable_conference_in_course_groups' => 'boolean',
+                'enable_global_conference_link' => 'boolean'
             ]
         );
     }
@@ -52,7 +53,7 @@ class BBBPlugin extends Plugin
      */
     public function validateCourseSetting($variable)
     {
-        if ($variable == 'bbb_enable_conference_in_groups') {
+        if ($variable === 'bbb_enable_conference_in_groups') {
             if ($this->get('enable_conference_in_course_groups') === 'true') {
 
                 return true;
@@ -117,6 +118,7 @@ class BBBPlugin extends Plugin
             'bbb_host',
             'bbb_tool_enable',
             'enable_global_conference',
+            'enable_global_conference_link',
             'enable_conference_in_course_groups',
             'bbb_plugin',
             'bbb_plugin_host',

+ 1 - 1
tests/main/inc/lib/glossary.lib.test.php

@@ -52,7 +52,7 @@ class TestGlossary extends UnitTestCase {
 	function testGetGlossaryTermByGlossaryName() {
 		$glossary_name = '';
 		$res = GlossaryManager::get_glossary_term_by_glossary_name($glossary_name);
-		$this->assertTrue(is_string($res));
+		$this->assertTrue(is_array($res));
 	}
 
 	function testUpdateGlossary() {