Browse Source

Merge from 1.11.x

jmontoyaa 7 years ago
parent
commit
1c2d4f020f
57 changed files with 710 additions and 472 deletions
  1. 1 1
      main/admin/access_url_edit_users_to_url.php
  2. 3 1
      main/admin/course_intro_pdf_import.php
  3. 9 2
      main/admin/course_request_edit.php
  4. 28 8
      main/admin/course_request_review.php
  5. 76 16
      main/admin/sub_language.php
  6. 7 4
      main/badge/issued.php
  7. 3 3
      main/coursecopy/create_backup.php
  8. 1 1
      main/create_course/add_course.php
  9. 16 40
      main/dashboard/dashboard_controller.php
  10. 1 1
      main/document/create_document.php
  11. 2 2
      main/document/edit_document.php
  12. 3 2
      main/dropbox/dropbox_class.inc.php
  13. 25 2
      main/exercise/exercise.class.php
  14. 2 2
      main/exercise/fill_blanks.class.php
  15. 7 11
      main/gamification/my_progress.php
  16. 1 1
      main/inc/ajax/chat.ajax.php
  17. 34 28
      main/inc/ajax/skill.ajax.php
  18. 14 27
      main/inc/lib/career.lib.php
  19. 2 2
      main/inc/lib/chat.lib.php
  20. 37 20
      main/inc/lib/course_home.lib.php
  21. 13 2
      main/inc/lib/course_request.lib.php
  22. 2 2
      main/inc/lib/display.lib.php
  23. 5 4
      main/inc/lib/document.lib.php
  24. 15 13
      main/inc/lib/formvalidator/FormValidator.class.php
  25. 2 0
      main/inc/lib/formvalidator/Rule/allowed_tags.inc.php
  26. 12 10
      main/inc/lib/internationalization.lib.php
  27. 13 3
      main/inc/lib/message.lib.php
  28. 5 1
      main/lp/learnpath.class.php
  29. 7 3
      main/lp/lp_controller.php
  30. 0 1
      main/lp/lp_final_item.php
  31. 1 1
      main/lp/lp_impress.php
  32. 7 1
      main/lp/lp_list.php
  33. 125 168
      main/mySpace/index.php
  34. 10 0
      main/mySpace/myStudents.php
  35. 63 17
      main/mySpace/users.php
  36. 3 5
      main/session/session_edit.php
  37. 7 1
      main/social/group_view.php
  38. 5 12
      main/wiki/wiki.inc.php
  39. 1 1
      src/CoreBundle/Entity/Repository/SessionRepository.php
  40. 1 2
      src/CoreBundle/Entity/Repository/TemplatesRepository.php
  41. 3 2
      src/CourseBundle/Component/CourseCopy/Course.php
  42. 5 5
      src/CourseBundle/Component/CourseCopy/CourseArchiver.php
  43. 15 14
      src/CourseBundle/Component/CourseCopy/CourseRestorer.php
  44. 13 4
      src/CourseBundle/Component/CourseCopy/CourseSelectForm.php
  45. 5 0
      src/CourseBundle/Entity/Repository/CStudentPublicationRepository.php
  46. 2 1
      src/SettingsBundle/DependencyInjection/Configuration.php
  47. 3 1
      src/SettingsBundle/Manager/SettingsManager.php
  48. 20 3
      src/SkillBundle/Entity/SkillRelItem.php
  49. 2 0
      src/UserBundle/Entity/User.php
  50. 1 1
      tests/behat/behat.yml
  51. 14 10
      tests/behat/features/accessCompanyReports.feature
  52. 1 1
      tests/behat/features/adminFillUsers.feature
  53. 0 1
      tests/behat/features/bootstrap/FeatureContext.php
  54. 1 1
      tests/behat/features/course.feature
  55. 1 2
      tests/behat/features/toolExercise.feature
  56. 54 4
      tests/behat/features/toolWork.feature
  57. 1 1
      tests/scripts/fix_restored_learnpaths.php

+ 1 - 1
main/admin/access_url_edit_users_to_url.php

@@ -104,7 +104,7 @@ if (isset($_POST['form_sent']) && $_POST['form_sent']) {
                 foreach ($result['users_added'] as $user) {
                     $user_info = api_get_user_info($user);
                     if (!empty($user_info)) {
-                        $user_added_list[] = $i.'. '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, null, null, $user_info['username']);
+                        $user_added_list[] = $i.'. '.api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, null, $user_info['username']);
                         $i++;
                     }
                 }

+ 3 - 1
main/admin/course_intro_pdf_import.php

@@ -73,7 +73,9 @@ Display::display_header($tool_name);
         </div>
         <div class="control-group">
             <div class="control">
-                <button type="submit" class="save" value="<?php echo get_lang('Import'); ?>"><?php echo get_lang('Import'); ?></button>
+                <button type="submit" class="save" value="<?php echo get_lang('Import'); ?>">
+                    <?php echo get_lang('Import'); ?>
+                </button>
             </div>
         </div>
         <input type="hidden" name="formSent" value="1"/>

+ 9 - 2
main/admin/course_request_edit.php

@@ -76,7 +76,12 @@ if ($course_validation_feature) {
         $form->addRule('wanted_code', get_lang('ThisFieldIsRequired'), 'required');
 
         // The teacher.
-        $titular = $form->addText('tutor_name', get_lang('Professor'), null, ['size' => '60', 'disabled' => 'disabled']);
+        $titular = $form->addText(
+            'tutor_name',
+            get_lang('Professor'),
+            null,
+            ['size' => '60', 'disabled' => 'disabled']
+        );
 
         // Description of the requested course.
         $form->addElement('textarea', 'description', get_lang('Description'));
@@ -101,7 +106,9 @@ if ($course_validation_feature) {
         if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED) {
             $submit_buttons[] = $form->addButtonSave(get_lang('Accept'), 'accept_button', true);
         }
-        if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED && $course_request_info['status'] != COURSE_REQUEST_REJECTED) {
+        if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED &&
+            $course_request_info['status'] != COURSE_REQUEST_REJECTED
+        ) {
             $submit_buttons[] = $form->addButtonCancel(get_lang('Reject'), 'reject_button', true);
         }
         if ($course_request_info['status'] != COURSE_REQUEST_ACCEPTED && intval($course_request_info['info']) <= 0) {

+ 28 - 8
main/admin/course_request_review.php

@@ -177,6 +177,7 @@ function get_request_data($from, $number_of_items, $column, $direction)
  */
 function email_filter($teacher)
 {
+    $teacher = Database::escape_string($teacher);
     $sql = "SELECT user_id FROM ".Database::get_main_table(TABLE_MAIN_COURSE_REQUEST)." 
             WHERE tutor_name LIKE '".$teacher."'";
     $res = Database::query($sql);
@@ -202,8 +203,17 @@ function modify_filter($id)
             Display::return_icon('request_info.gif', get_lang('AskAdditionalInfo'), ['style' => 'vertical-align: middle;', 'onclick' => 'javascript: if (!confirm(\''.addslashes(api_htmlentities(sprintf(get_lang('AdditionalInfoWillBeAsked'), $code), ENT_QUOTES)).'\')) return false;']).'</a>';
     }
     if (DELETE_ACTION_ENABLED) {
-        $result .= '&nbsp;<a href="?delete_course_request='.$id.'">'
-            .Display::return_icon('delete.png', get_lang('DeleteThisCourseRequest'), ['style' => 'vertical-align: middle;', 'onclick' => 'javascript: if (!confirm(\''.addslashes(api_htmlentities(sprintf(get_lang('ACourseRequestWillBeDeleted'), $code), ENT_QUOTES)).'\')) return false;']).'</a>';
+        $message = addslashes(api_htmlentities(sprintf(get_lang('ACourseRequestWillBeDeleted'), $code), ENT_QUOTES));
+        $result .= '&nbsp;<a href="?delete_course_request='.$id.'">';
+        $result .= Display::return_icon(
+            'delete.png',
+            get_lang('DeleteThisCourseRequest'),
+            [
+                'style' => 'vertical-align: middle;',
+                'onclick' => 'javascript: if (!confirm(\''.$message.'\')) return false;',
+            ]
+        );
+        $result .= '</a>';
     }
 
     return $result;
@@ -239,11 +249,14 @@ $form->addButtonSearch(get_lang('Search'));
 
 // The action bar.
 echo '<div style="float: right; margin-top: 5px; margin-right: 5px;">';
-//echo '<a href="course_list.php">'.Display::return_icon('courses.gif', get_lang('CourseList')).get_lang('CourseList').'</a>';
-echo ' <a href="course_request_accepted.php">'.
-    Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).get_lang('AcceptedCourseRequests').'</a>';
-echo ' <a href="course_request_rejected.php">'.
-    Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).get_lang('RejectedCourseRequests').'</a>';
+echo ' <a href="course_request_accepted.php">';
+echo Display::return_icon('course_request_accepted.gif', get_lang('AcceptedCourseRequests')).
+    get_lang('AcceptedCourseRequests');
+echo '</a>';
+echo ' <a href="course_request_rejected.php">';
+echo Display::return_icon('course_request_rejected.gif', get_lang('RejectedCourseRequests')).
+    get_lang('RejectedCourseRequests');
+echo '</a>';
 echo '</div>';
 echo '<div class="actions">';
 $form->display();
@@ -251,7 +264,14 @@ echo '</div>';
 
 // Create a sortable table with the course data.
 $offet = DELETE_ACTION_ENABLED ? 1 : 0;
-$table = new SortableTable('course_requests_review', 'get_number_of_requests', 'get_request_data', 4 + $offet, 20, 'DESC');
+$table = new SortableTable(
+    'course_requests_review',
+    'get_number_of_requests',
+    'get_request_data',
+    4 + $offet,
+    20,
+    'DESC'
+);
 //$table->set_additional_parameters($parameters);
 if (DELETE_ACTION_ENABLED) {
     $table->set_header(0, '', false);

+ 76 - 16
main/admin/sub_language.php

@@ -167,7 +167,9 @@ function search_language_term(
                 }
                 if ($founded) {
                     //loading variable from the english array
-                    $sub_language_name_variable = $sub_language_array[$lang_file][$parent_name_variable];
+                    $sub_language_name_variable = isset($sub_language_array[$lang_file][$parent_name_variable])
+                        ? $sub_language_array[$lang_file][$parent_name_variable]
+                        : '';
                     //loading variable from the english array
                     $english_name_variable = $english_language_array[$lang_file][$parent_name_variable];
 
@@ -178,14 +180,31 @@ function search_language_term(
                         $size =4;
                     }*/
 
-                    $obj_text = '<textarea rows="10" cols="40" name="txt|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="txtid_'.$language_files_to_load_keys[$lang_file].'_'.$parent_name_variable.'" >'.$sub_language_name_variable.'</textarea>';
-                    $obj_button = '<button class="save" type="button" name="btn|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="btnid_'.$parent_name_variable.'"  />'.get_lang('Save').'</button>';
+                    $obj_text = Display::tag(
+                        'textarea',
+                        $sub_language_name_variable,
+                        [
+                            'rows' => 10,
+                            'cols' => 40,
+                            'name' => 'txt|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                            'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$parent_name_variable,
+                        ]
+                    );
+                    $obj_button = Display::button(
+                        'btn|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                        get_lang('Save'),
+                        [
+                            'class' => 'save  btn btn-default btn-sm',
+                            'type' => 'button',
+                            'id' => 'btnid_'.$parent_name_variable,
+                        ]
+                    );
 
-                    $list_info[] = [
+                    $list_info[$parent_name_variable] = [
                         $lang_file.'.inc.php',
                         $parent_name_variable,
-                        $english_name_variable,
-                        $parent_variable_value,
+                        htmlentities($english_name_variable),
+                        htmlentities($parent_variable_value),
                         $obj_text,
                         $obj_button,
                     ];
@@ -197,6 +216,10 @@ function search_language_term(
         if ($search_in_english || $search_in_variable) {
             $variables = $english_language_array[$lang_file];
             foreach ($variables as $name_variable => $variable_value) {
+                if (isset($list_info[$name_variable])) {
+                    continue;
+                }
+
                 if (is_array($variable_value)) {
                     continue;
                 }
@@ -233,10 +256,25 @@ function search_language_term(
                         $parent_variable_value = $parent_language_array[$lang_file][$name_variable];
                     }
                     //config buttons
-                    $obj_text = '<textarea rows="10" cols="40" name="txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable.'" >'.
-                        $sub_language_name_variable.'
-                        </textarea>';
-                    $obj_button = '<button class="save" type="button" name="btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="btnid_'.$name_variable.'"  />'.get_lang('Save').'</button>';
+                    $obj_text = Display::tag(
+                        'textarea',
+                        $sub_language_name_variable,
+                        [
+                            'rows' => 10,
+                            'cols' => 40,
+                            'name' => 'txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                            'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable,
+                        ]
+                    );
+                    $obj_button = Display::button(
+                        'btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                        get_lang('Save'),
+                        [
+                            'class' => 'save btn btn-default btn-sm',
+                            'type' => 'button',
+                            'id' => 'btnid_'.$name_variable,
+                        ]
+                    );
 
                     //loading variable from the english array
                     $english_name_variable = $english_language_array[$lang_file][$name_variable];
@@ -244,8 +282,8 @@ function search_language_term(
                     $list_info[] = [
                         $lang_file.'.inc.php',
                         $name_variable,
-                        $english_name_variable,
-                        $parent_variable_value,
+                        htmlentities($english_name_variable),
+                        htmlentities($parent_variable_value),
                         $obj_text,
                         $obj_button,
                     ];
@@ -272,11 +310,32 @@ function search_language_term(
                 }
                 if ($founded) {
                     //loading variable from the english array
-                    $sub_language_name_variable = $sub_language_array[$lang_file][$name_variable];
-                    $parent_variable_value = $parent_language_array[$lang_file][$name_variable];
+                    $sub_language_name_variable = isset($sub_language_array[$lang_file][$name_variable])
+                        ? $sub_language_array[$lang_file][$name_variable]
+                        : '';
+                    $parent_variable_value = isset($parent_language_array[$lang_file][$name_variable])
+                        ? $parent_language_array[$lang_file][$name_variable]
+                        : '';
                     //config buttons
-                    $obj_text = '<textarea rows="10" cols="40" name="txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable.'" >'.$sub_language_name_variable.'</textarea>';
-                    $obj_button = '<button class="save" type="button" name="btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file].'" id="btnid_'.$name_variable.'"  />'.get_lang('Save').'</button>';
+                    $obj_text = Display::tag(
+                        'textarea',
+                        $sub_language_name_variable,
+                        [
+                            'rows' => 10,
+                            'cols' => 40,
+                            'name' => 'txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                            'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable,
+                        ]
+                    );
+                    $obj_button = Display::button(
+                        'btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
+                        get_lang('Save'),
+                        [
+                            'class' => 'save btn btn-default btn-sm',
+                            'type' => 'button',
+                            'id' => 'btnid_'.$name_variable,
+                        ]
+                    );
 
                     //loading variable from the english array
                     $english_name_variable = $english_language_array[$lang_file][$name_variable];
@@ -322,6 +381,7 @@ $table->set_header(2, get_lang('EnglishName'));
 $table->set_header(3, get_lang('OriginalName'));
 $table->set_header(4, get_lang('Translation'), false);
 $table->set_header(5, get_lang('Action'), false);
+$table->setHideColumn(0);
 $table->display();
 
 Display :: display_footer();

+ 7 - 4
main/badge/issued.php

@@ -1,6 +1,7 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CoreBundle\Entity\SkillRelUser;
 use Chamilo\CoreBundle\Entity\SkillRelUserComment;
 
 /**
@@ -21,6 +22,7 @@ if (empty($issue)) {
 }
 
 $entityManager = Database::getManager();
+/** @var SkillRelUser $skillIssue */
 $skillIssue = $entityManager->find('ChamiloCoreBundle:SkillRelUser', $issue);
 
 if (!$skillIssue) {
@@ -68,10 +70,12 @@ $skillInfo = [
     'courses' => [],
 ];
 
+$titleContent = sprintf(get_lang('IHaveObtainedSkillXOnY'), $skillInfo['name'], api_get_setting('siteName'));
+
 // Open Graph Markup
 $htmlHeadXtra[] = "
     <meta property='og:type' content='article' />
-    <meta property='og:title' content='".sprintf(get_lang('IHaveObtainedSkillXOnY'), $skillInfo['name'], api_get_setting('siteName'))."' />
+    <meta property='og:title' content='".$titleContent."' />
     <meta property='og:url' content='".api_get_path(WEB_PATH)."badge/".$issue."' />
     <meta property='og:description' content='".$skillInfo['description']."' />
     <meta property='og:image' content='".$skillInfo['badge_image']."' />
@@ -87,14 +91,14 @@ if ($skillIssue->getAcquiredLevel()) {
     $currentSkillLevel = $skillLevelRepo->find(['id' => $skillIssue->getAcquiredLevel()])->getName();
 }
 
-$argumentationAuthor = api_get_user_info($skillIssue->getArgumentationAuthorId());
+$author = api_get_user_info($skillIssue->getArgumentationAuthorId());
 
 $skillIssueInfo = [
     'id' => $skillIssue->getId(),
     'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT),
     'acquired_level' => $currentSkillLevel,
     'argumentation_author_id' => $skillIssue->getArgumentationAuthorId(),
-    'argumentation_author_name' => api_get_person_name($argumentationAuthor['firstname'], $argumentationAuthor['lastname']),
+    'argumentation_author_name' => $author['complete_name'],
     'argumentation' => $skillIssue->getArgumentation(),
     'source_name' => $skillIssue->getSourceName(),
     'user_id' => $skillIssue->getUser()->getId(),
@@ -128,7 +132,6 @@ foreach ($skillIssueComments as $comment) {
 }
 
 $acquiredLevel = [];
-
 $profile = $skillRepo->find($skillId)->getProfile();
 
 if (!$profile) {

+ 3 - 3
main/coursecopy/create_backup.php

@@ -46,8 +46,6 @@ Display::display_header($nameTools);
 // Display the tool title
 echo Display::page_header($nameTools);
 
-/*	MAIN CODE */
-
 if (Security::check_token('post') && (
         (
             isset($_POST['action']) &&
@@ -70,7 +68,9 @@ if (Security::check_token('post') && (
 
     $zip_file = CourseArchiver::createBackup($course);
     echo Display::return_message(get_lang('BackupCreated'), 'confirm');
-    echo '<br /><a class="btn btn-primary btn-large" href="'.api_get_path(WEB_CODE_PATH).'course_info/download.php?archive='.$zip_file.'&'.api_get_cidreq().'">
+    echo '<br />
+        <a class="btn btn-primary btn-large" 
+        href="'.api_get_path(WEB_CODE_PATH).'course_info/download.php?archive='.$zip_file.'&'.api_get_cidreq().'">
     '.get_lang('Download').'</a>';
 } elseif (Security::check_token('post') && (
         isset($_POST['backup_option']) &&

+ 1 - 1
main/create_course/add_course.php

@@ -52,7 +52,7 @@ $htmlHeadXtra[] = '<script>
     function setFocus(){
         $("#title").focus();
     }
-    $(window).on("load", function (e) {
+    $(window).on("load", function () {
         setFocus();
     });
 </script>';

+ 16 - 40
main/dashboard/dashboard_controller.php

@@ -30,6 +30,7 @@ class DashboardController
      */
     public function display()
     {
+        $tpl = new Template(get_lang('Dashboard'));
         $user_id = $this->user_id;
         $dashboard_blocks = DashboardManager::get_enabled_dashboard_blocks();
         $user_block_data = DashboardManager::get_user_block_data($user_id);
@@ -79,17 +80,22 @@ class DashboardController
         $configuration_link = null;
         if (api_is_platform_admin()) {
             $configuration_link = '<a href="'.api_get_path(WEB_CODE_PATH).'admin/settings.php?category=Plugins">'
-                .Display::return_icon('settings.png', get_lang('ConfigureDashboardPlugin'), '', ICON_SIZE_MEDIUM).'</a>';
+                .Display::return_icon(
+                    'settings.png',
+                    get_lang('ConfigureDashboardPlugin'),
+                    '',
+                    ICON_SIZE_MEDIUM
+                ).'</a>';
         }
 
-        $content = '<div class="actions">';
-        $content .= $link_blocks_view.$link_list_view.$configuration_link;
-        $content .= '</div>';
+        $actions = Display::toolbarAction('toolbar', [0 => $link_blocks_view.$link_list_view.$configuration_link]);
+        $tpl->assign('actions', $actions);
 
         // block dashboard view
+        $columns = [];
+        $blockList = null;
         if (isset($view) && $view == 'blocks') {
             if (isset($blocks) && count($blocks) > 0) {
-                $columns = [];
                 // group content html by number of column
                 if (is_array($blocks)) {
                     $tmp_columns = [];
@@ -100,46 +106,16 @@ class DashboardController
                         }
                     }
                 }
-
-                $content .= '<div id="columns" class="row">';
-                if (count($columns) > 0) {
-                    $columns_name = array_keys($columns);
-                    // blocks for column 1
-                    if (in_array('column_1', $columns_name)) {
-                        $content .= '<div id="column1" class="col-md-6">';
-                        foreach ($columns['column_1'] as $data) {
-                            $content .= $data;
-                        }
-                        $content .= '</div>';
-                    } else {
-                        $content .= '<div id="column1" class="col-md-6">';
-                        $content .= '&nbsp;';
-                        $content .= '</div>';
-                    }
-                    // blocks for column 2
-                    if (in_array('column_2', $columns_name)) {
-                        // blocks for column 1
-                        $content .= '<div id="column2" class="col-md-6">';
-                        foreach ($columns['column_2'] as $data) {
-                            $content .= $data;
-                        }
-                        $content .= '</div>';
-                    } else {
-                        $content .= '<div id="column2" class="col-md-6">';
-                        $content .= '&nbsp;';
-                        $content .= '</div>';
-                    }
-                }
-                $content .= '</div>';
-            } else {
-                $content .= '<div style="margin-top:20px;">'.get_lang('YouHaveNotEnabledBlocks').'</div>';
             }
         } else {
             $user_id = api_get_user_id();
-            $content .= DashboardManager::display_user_dashboard_list($user_id);
+            $blockList = DashboardManager::display_user_dashboard_list($user_id);
+            $tpl->assign('blocklist', $blockList);
         }
 
-        $tpl = new Template(get_lang('Dashboard'));
+        $tpl->assign('columns', $columns);
+        $template = $tpl->get_template('dashboard/index.tpl');
+        $content = $tpl->fetch($template);
         $tpl->assign('content', $content);
         $tpl->display_one_col_template();
     }

+ 1 - 1
main/document/create_document.php

@@ -47,7 +47,7 @@ function setFocus() {
    $("#document_title").focus();
 }
 
-$(window).on("load", function (e) {
+$(window).on("load", function () {
 	setFocus();
 });
 

+ 2 - 2
main/document/edit_document.php

@@ -393,7 +393,7 @@ if ($owner_id == api_get_user_id() ||
 
     if (($extension == 'htm' || $extension == 'html') && $condition) {
         if (empty($readonly) && $readonly == 0) {
-            $form->addHtmlEditor('content', '', true, true, $editorConfig);
+            $form->addHtmlEditor('content', get_lang('Content'), true, true, $editorConfig);
         }
     }
 
@@ -565,7 +565,7 @@ function show_return($document_id, $path, $call_from_tool = '', $slide_id = 0, $
             Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('DocumentsOverview'), '', ICON_SIZE_MEDIUM).'</a>';
         $actionsLeft .= '<a href="javascript:history.back(1)">'.Display::return_icon('draw.png', get_lang('BackTo').' '.get_lang('Write'), [], 32).'</a>';
         $actionsLeft .= '<a id="hide_bar_template" href="#" role="button">'.Display::return_icon('expand.png', get_lang('Expand'), ['id' => 'expand'], ICON_SIZE_MEDIUM).Display::return_icon('contract.png', get_lang('Collapse'), ['id' => 'contract', 'class' => 'hide'], ICON_SIZE_MEDIUM).'</a>';
-    } elseif ($call_from_tool == 'editpaint') {
+    } elseif ($call_from_tool == 'editpaint' && api_get_setting('enabled_support_pixlr') === 'true') {
         $actionsLeft .= '<a href="'.$url.'">'.
             Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('DocumentsOverview'), [], ICON_SIZE_MEDIUM).'</a>';
         $actionsLeft .= '<a href="javascript:history.back(1)">'.Display::return_icon('paint.png', get_lang('BackTo').' '.get_lang('Paint'), [], 32).'</a>';

+ 3 - 2
main/dropbox/dropbox_class.inc.php

@@ -152,7 +152,8 @@ class Dropbox_Work
 
             $this->id = Database::insert(Database::get_course_table(TABLE_DROPBOX_FILE), $params);
             if ($this->id) {
-                $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)." SET id = iid WHERE iid = {$this->id}";
+                $sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)." SET id = iid 
+                        WHERE iid = {$this->id}";
                 Database::query($sql);
             }
         }
@@ -402,7 +403,7 @@ class Dropbox_SentWork extends Dropbox_Work
         $this->recipients = [];
         $sql = "SELECT dest_user_id, feedback_date, feedback
                 FROM ".Database::get_course_table(TABLE_DROPBOX_POST)."
-                WHERE c_id = $course_id AND file_id = ".intval($id)."";
+                WHERE c_id = $course_id AND file_id = ".intval($id);
         $result = Database::query($sql);
         while ($res = Database::fetch_array($result, 'ASSOC')) {
             // Check for deleted users

+ 25 - 2
main/exercise/exercise.class.php

@@ -3340,7 +3340,7 @@ class Exercise
         $hotspot_delineation_result = [],
         $showTotalScoreAndUserChoicesInLastAttempt = true
     ) {
-        global $debug;
+        $debug = false;
         //needed in order to use in the exercise_attempt() for the time
         global $learnpath_id, $learnpath_item_id;
         require_once api_get_path(LIBRARY_PATH).'geometry.lib.php';
@@ -3354,7 +3354,7 @@ class Exercise
             error_log('$from:  '.$from);
             error_log('$saved_results: '.intval($saved_results));
             error_log('$from_database: '.intval($from_database));
-            error_log('$show_result: '.$show_result);
+            error_log('$show_result: '.intval($show_result));
             error_log('$propagate_neg: '.$propagate_neg);
             error_log('$exerciseResultCoordinates: '.print_r($exerciseResultCoordinates, 1));
             error_log('$hotspot_delineation_result: '.print_r($hotspot_delineation_result, 1));
@@ -3706,6 +3706,9 @@ class Exercise
                                     exe_id = $exeId AND
                                     question_id= ".intval($questionId);
                         $result = Database::query($sql);
+                        if ($debug) {
+                            error_log($sql);
+                        }
                         $str = $answerFromDatabase = Database::result($result, 0, 'answer');
                     }
 
@@ -3866,11 +3869,20 @@ class Exercise
                                 $studentAnswer = isset($choice[$i]) ? $choice[$i] : '';
                                 $correctAnswer = $listCorrectAnswers['words'][$i];
 
+                                if ($debug) {
+                                    error_log("Student answer: $i");
+                                    error_log($studentAnswer);
+                                }
+
                                 // This value is the user input, not escaped while correct answer is escaped by ckeditor
                                 // Works with cyrillic alphabet and when using ">" chars see #7718 #7610 #7618
                                 // ENT_QUOTES is used in order to transform ' to &#039;
                                 if (!$from_database) {
                                     $studentAnswer = FillBlanks::clearStudentAnswer($studentAnswer);
+                                    if ($debug) {
+                                        error_log("Student answer cleaned:");
+                                        error_log($studentAnswer);
+                                    }
                                 }
 
                                 $isAnswerCorrect = 0;
@@ -3881,9 +3893,15 @@ class Exercise
                                     $totalScore += $answerWeighting[$i];
                                     $isAnswerCorrect = 1;
                                 }
+                                if ($debug) {
+                                    error_log("isAnswerCorrect $i: $isAnswerCorrect");
+                                }
 
                                 $studentAnswerToShow = $studentAnswer;
                                 $type = FillBlanks::getFillTheBlankAnswerType($correctAnswer);
+                                if ($debug) {
+                                    error_log("Fill in blank type: $type");
+                                }
                                 if ($type == FillBlanks::FILL_THE_BLANK_MENU) {
                                     $listMenu = FillBlanks::getFillTheBlankMenuAnswers($correctAnswer, false);
                                     if ($studentAnswer != '') {
@@ -3908,6 +3926,11 @@ class Exercise
                                 $studentAnswer = trim($listStudentAnswerTemp[$i]);
                                 $studentAnswerToShow = $studentAnswer;
 
+                                if ($debug) {
+                                    error_log("Student answer: $i");
+                                    error_log($studentAnswer);
+                                }
+
                                 $found = false;
                                 for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) {
                                     $correctAnswer = $listTeacherAnswerTemp[$j];

+ 2 - 2
main/exercise/fill_blanks.class.php

@@ -671,10 +671,11 @@ class FillBlanks extends Question
                 $listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer);
                 $listSeveral = array_map(
                     function ($item) {
-                        return self::trimOption($item);
+                        return self::trimOption(api_html_entity_decode($item));
                     },
                     $listSeveral
                 );
+                $studentAnswer = htmlspecialchars($studentAnswer);
                 $result = in_array($studentAnswer, $listSeveral);
                 break;
             case self::FILL_THE_BLANK_STANDARD:
@@ -684,7 +685,6 @@ class FillBlanks extends Question
                 $result = $studentAnswer == self::trimOption($correctAnswer);
                 break;
         }
-        //var_dump($result);
 
         return $result;
     }

+ 7 - 11
main/gamification/my_progress.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CoreBundle\Entity\Repository\TrackECourseAccessRepository;
+
 /**
  * See the progress for a user when the gamification mode is active.
  *
@@ -24,19 +26,14 @@ $userId = api_get_user_id();
 $sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0;
 $allowAccess = false;
 
-$userManager = UserManager::getManager();
 $entityManager = Database::getManager();
+$user = api_get_user_entity($userId);
 
-$user = $userManager->findUserBy(['id' => $userId]);
-
-if (empty($sessionId)) {
-    $trackCourseAccessRepository = $entityManager->getRepository(
-        'ChamiloCoreBundle:TrackECourseAccess'
-    );
-
+if (empty($sessionId) && $user) {
+    /** @var TrackECourseAccessRepository $trackCourseAccessRepository */
+    $trackCourseAccessRepository = $entityManager->getRepository('ChamiloCoreBundle:TrackECourseAccess');
     $lastCourseAccess = $trackCourseAccessRepository->getLastAccessByUser($user);
     $lastSessionId = 0;
-
     if ($lastCourseAccess) {
         $lastSessionId = $lastCourseAccess->getSessionId();
     }
@@ -54,10 +51,9 @@ if (empty($sessionId)) {
 }
 
 $sessionCourseSubscriptions = $user->getSessionCourseSubscriptions();
-$currentSession = $entityManager->find('ChamiloCoreBundle:Session', $sessionId);
+$currentSession = api_get_session_entity($sessionId);
 
 $sessionList = [];
-
 foreach ($sessionCourseSubscriptions as $subscription) {
     $session = $subscription->getSession();
 

+ 1 - 1
main/inc/ajax/chat.ajax.php

@@ -57,7 +57,7 @@ switch ($action) {
         $chat->startSession();
         break;
     case 'get_previous_messages':
-        $userId = isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : null;
+        $userId = isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : 0;
         $visibleMessages = isset($_REQUEST['visible_messages']) ? $_REQUEST['visible_messages'] : null;
         if (empty($userId)) {
             return '';

+ 34 - 28
main/inc/ajax/skill.ajax.php

@@ -34,18 +34,21 @@ switch ($action) {
         }
         break;
     case 'find_skills':
-        $skills = $skill->find('all', ['where' => ['name LIKE %?% ' => $_REQUEST['q']]]);
-        $return_skills = [[
+        $returnSkills = [[
             'items' => [],
         ]];
-        foreach ($skills as $skill) {
-            $return_skills['items'][] = [
-                'id' => $skill['id'],
-                'text' => $skill['name'],
-            ];
+
+        if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
+            $skills = $skill->find('all', ['where' => ['name LIKE %?% ' => $_REQUEST['q']]]);
+            foreach ($skills as $skill) {
+                $returnSkills['items'][] = [
+                    'id' => $skill['id'],
+                    'text' => $skill['name'],
+                ];
+            }
         }
         header('Content-Type: application/json');
-        echo json_encode($return_skills);
+        echo json_encode($returnSkills);
         break;
     case 'get_gradebooks':
         $gradebooks = $gradebook_list = $gradebook->get_all();
@@ -64,12 +67,14 @@ switch ($action) {
         echo json_encode($gradebook_list);
         break;
     case 'find_gradebooks':
-        $gradebooks = $gradebook->find('all', ['where' => ['name LIKE %?% ' => $_REQUEST['tag']]]);
         $return = [];
-        foreach ($gradebooks as $item) {
-            $item['key'] = $item['name'];
-            $item['value'] = $item['id'];
-            $return[] = $item;
+        if (isset($_REQUEST['tag']) && !empty($_REQUEST['tag'])) {
+            $gradebooks = $gradebook->find('all', ['where' => ['name LIKE %?% ' => $_REQUEST['tag']]]);
+            foreach ($gradebooks as $item) {
+                $item['key'] = $item['name'];
+                $item['value'] = $item['id'];
+                $return[] = $item;
+            }
         }
         echo json_encode($return);
         break;
@@ -207,7 +212,7 @@ switch ($action) {
         break;
     case 'profile_matches':
         $skill_rel_user = new SkillRelUser();
-        $skills = (!empty($_REQUEST['skill_id']) ? $_REQUEST['skill_id'] : []);
+        $skills = !empty($_REQUEST['skill_id']) ? $_REQUEST['skill_id'] : [];
         $total_skills_to_search = $skills;
         $users = $skill_rel_user->getUserBySkills($skills);
         $user_list = [];
@@ -342,22 +347,23 @@ switch ($action) {
         }
         break;
     case 'search_skills':
-        $skills = $skill->find(
-            'all',
-            [
-                'where' => ['name LIKE %?% ' => $_REQUEST['q']],
-            ]
-        );
         $returnSkills = [];
-        foreach ($skills as $skill) {
-            $returnSkills[] = [
-                'id' => $skill['id'],
-                'text' => $skill['name'],
-            ];
+        if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
+            $skills = $skill->find(
+                'all',
+                [
+                    'where' => ['name LIKE %?% ' => $_REQUEST['q']],
+                ]
+            );
+            foreach ($skills as $skill) {
+                $returnSkills[] = [
+                    'id' => $skill['id'],
+                    'text' => $skill['name'],
+                ];
+            }
         }
-        echo json_encode([
-            'items' => $returnSkills,
-        ]);
+
+        echo json_encode(['items' => $returnSkills]);
         break;
     case 'search_skills_in_course':
         $courseId = isset($_REQUEST['course_id']) ? (int) $_REQUEST['course_id'] : 0;

+ 14 - 27
main/inc/lib/career.lib.php

@@ -365,9 +365,7 @@ class Career extends Model
                     foreach ($items as $vertex) {
                         if ($vertex instanceof Vertex) {
                             $groupCourseList[$group][] = $vertex->getId();
-                            $connectionList = $vertex->getAttribute(
-                                'Connections'
-                            );
+                            $connectionList = $vertex->getAttribute('Connections');
                             $firstConnection = '';
                             $secondConnection = '';
                             if (!empty($connectionList)) {
@@ -525,8 +523,6 @@ class Career extends Model
                         if (empty($connectionList)) {
                             continue;
                         }
-                        $firstConnection = '';
-                        $secondConnection = '';
                         $simpleFirstConnection = '';
                         $simpleSecondConnection = '';
 
@@ -535,28 +531,22 @@ class Career extends Model
                         if ($pos === false) {
                             $pos = strpos($explode[0], 'G');
                             if (is_numeric($pos)) {
-                                // group_123 id
+                                // Is group
                                 $groupValueId = (int) str_replace(
                                     'G',
                                     '',
                                     $explode[0]
                                 );
-                                $secondConnection = 'group_'.$groupValueId;
-                                $firstConnection = 'row_'.(int) $rowId;
                                 $groupDrawLine[$groupValueId] = true;
-
-                                $simpleSecondConnection = 'g'.$groupValueId;
-                                $simpleFirstConnection = 'v'.(int) $rowId;
+                                $simpleFirstConnection = 'g'.(int) $groupValueId;
                             } else {
                                 // Course block (row_123 id)
                                 if (!empty($explode[0])) {
-                                    $firstConnection = 'row_'.(int) $explode[0];
                                     $simpleFirstConnection = 'v'.(int) $explode[0];
                                 }
                             }
                         } else {
                             // subgroup__123 id
-                            $firstConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[0]);
                             $simpleFirstConnection = 'sg'.(int) str_replace('SG', '', $explode[0]);
                         }
 
@@ -575,31 +565,23 @@ class Career extends Model
                                     '',
                                     $value
                                 );
-                                $secondConnection = 'group_'.$groupValueId;
                                 $simpleSecondConnection = 'g'.(int) $groupValueId;
                                 $groupDrawLine[$groupValueId] = true;
                             } else {
                                 // Course block (row_123 id)
                                 if (!empty($explode[0]) && isset($explode[1])) {
-                                    $secondConnection = 'row_'.(int) $explode[1];
                                     $simpleSecondConnection = 'v'.(int) $explode[1];
                                 }
                             }
                         } else {
-                            $secondConnection = 'subgroup_'.(int) str_replace('SG', '', $explode[1]);
                             $simpleSecondConnection = 'sg'.(int) str_replace('SG', '', $explode[1]);
                         }
 
-                        if (!empty($firstConnection) && !empty($firstConnection)) {
+                        if (!empty($simpleFirstConnection) && !empty($simpleSecondConnection)) {
                             $simpleConnectionList[] = [
                                 'from' => $simpleFirstConnection,
                                 'to' => $simpleSecondConnection,
                             ];
-                            $connections .= self::createConnection(
-                                $firstConnection,
-                                $secondConnection,
-                                ['Left', 'Right']
-                            );
                         }
                     }
                 }
@@ -633,9 +615,7 @@ class Career extends Model
         }
 
         $graphHtml .= '</div>';
-//        $graphHtml .= $connections;
         $graphHtml .= '<style>
-            panel-title
              #career_grid {
                  display: grid;
                  grid-gap: 40px;
@@ -711,8 +691,6 @@ class Career extends Model
                     $subGroupListData[$subGroupId]['min_y'] = $y;
                 }
 
-                /*$originalRow--;
-                $column--;*/
                 $subGroupListData[$subGroupId]['max_width'] = ($column + 1) * ($width + $graph->xGap) - $subGroupListData[$subGroupId]['min_x'];
                 $subGroupListData[$subGroupId]['max_height'] = ($originalRow + 1) * ($height + $graph->yGap) - $subGroupListData[$subGroupId]['min_y'];
             }
@@ -729,7 +707,6 @@ class Career extends Model
                 $subGroupList[] = $vertexData;
             }
         }
-
         // Create connections (arrows)
         if (!empty($simpleConnectionList)) {
             $connectionList = [];
@@ -841,6 +818,16 @@ class Career extends Model
         return $graphHtml;
     }
 
+    /**
+     * @param array    $groupCourseList
+     * @param array    $vertexList
+     * @param int      $addRow
+     * @param stdClass $graph
+     * @param int      $group
+     * @param array    $connections
+     *
+     * @return string
+     */
     public static function parseVertexList($groupCourseList, $vertexList, $addRow = 0, &$graph, $group, &$connections)
     {
         if (empty($vertexList)) {

+ 2 - 2
main/inc/lib/chat.lib.php

@@ -349,12 +349,12 @@ class Chat extends Model
         $printResult = true,
         $sanitize = true
     ) {
-        $user_friend_relation = SocialManager::get_relation_between_contacts(
+        $relation = SocialManager::get_relation_between_contacts(
             $fromUserId,
             $to_user_id
         );
 
-        if ($user_friend_relation == USER_RELATION_TYPE_FRIEND) {
+        if ($relation == USER_RELATION_TYPE_FRIEND) {
             $now = api_get_utc_datetime();
             $user_info = api_get_user_info($to_user_id, true);
             $this->saveWindow($to_user_id);

+ 37 - 20
main/inc/lib/course_home.lib.php

@@ -34,7 +34,11 @@ class CourseHome
             case 'Basic':
                 $condition_display_tools = ' WHERE a.c_id = '.$course_id.' AND  a.link=t.link AND t.position="basic" ';
                 if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
-                    $condition_display_tools = ' WHERE a.c_id = '.$course_id.' AND a.link=t.link AND (t.position="basic" OR a.name = "'.TOOL_TRACKING.'") ';
+                    $condition_display_tools = ' WHERE 
+                        a.c_id = '.$course_id.' AND 
+                        a.link=t.link AND
+                         (t.position="basic" OR a.name = "'.TOOL_TRACKING.'") 
+                    ';
                 }
 
                 $sql = "SELECT a.*, t.image img, t.row, t.column  
@@ -44,13 +48,20 @@ class CourseHome
             case 'External':
                 if (api_is_allowed_to_edit()) {
                     $sql = "SELECT a.*, t.image img FROM $TBL_ACCUEIL a, $TABLE_TOOLS t
-                            WHERE a.c_id = $course_id AND ((a.link=t.link AND t.position='external')
-                            OR (a.visibility <= 1 AND (a.image = 'external.gif' OR a.image = 'scormbuilder.gif' OR t.image = 'blog.gif') AND a.image=t.image))
+                            WHERE 
+                              a.c_id = $course_id AND 
+                              ((a.link=t.link AND t.position='external') OR 
+                              (a.visibility <= 1 AND 
+                              (a.image = 'external.gif' OR a.image = 'scormbuilder.gif' OR t.image = 'blog.gif') AND 
+                              a.image=t.image))
                             ORDER BY a.id";
                 } else {
                     $sql = "SELECT a.*, t.image img FROM $TBL_ACCUEIL a, $TABLE_TOOLS t
-                            WHERE a.c_id = $course_id AND (a.visibility = 1 AND ((a.link=t.link AND t.position='external')
-                            OR ((a.image = 'external.gif' OR a.image = 'scormbuilder.gif' OR t.image = 'blog.gif') AND a.image=t.image)))
+                            WHERE 
+                              a.c_id = $course_id AND 
+                              (a.visibility = 1 AND ((a.link=t.link AND t.position='external') OR 
+                              ((a.image = 'external.gif' OR a.image = 'scormbuilder.gif' OR t.image = 'blog.gif') AND 
+                              a.image=t.image)))
                             ORDER BY a.id";
                 }
                 break;
@@ -164,12 +175,14 @@ class CourseHome
 
             // VISIBLE
             if (($tool['visibility'] ||
-                    ((api_is_coach() || api_is_course_tutor()) && $tool['name'] == TOOL_TRACKING)) ||
+                ((api_is_coach() || api_is_course_tutor()) && $tool['name'] == TOOL_TRACKING)) ||
                 $cat == 'courseAdmin' || $cat == 'platformAdmin'
             ) {
                 if (strpos($tool['name'], 'visio_') !== false) {
                     $cell_content .= '<a  href="javascript: void(0);" onclick="javascript: window.open(\''.$tool['link'].$link_annex.'\',\'window_visio'.api_get_course_id().'\',config=\'height=\'+730+\', width=\'+1020+\', left=2, top=2, toolbar=no, menubar=no, scrollbars=yes, resizable=yes, location=no, directories=no, status=no\')" target="'.$tool['target'].'"><img src="'.$tool['img'].'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">'.$tool_name.'</a>';
-                } elseif (strpos($tool['name'], 'chat') !== false && api_get_course_setting('allow_open_chat_window')) {
+                } elseif (strpos($tool['name'], 'chat') !== false &&
+                    api_get_course_setting('allow_open_chat_window')
+                ) {
                     // don't replace img with display::return_icon because $tool['img'] = api_get_path(WEB_IMG_PATH).$tool['img']
                     $cell_content .= '<a href="javascript: void(0);" onclick="javascript: window.open(\''.$tool['link'].$link_annex.'\',\'window_chat'.api_get_course_id().'\',config=\'height=\'+600+\', width=\'+825+\', left=2, top=2, toolbar=no, menubar=no, scrollbars=yes, resizable=yes, location=no, directories=no, status=no\')" target="'.$tool['target'].'"><img src="'.$tool['img'].'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">'.$tool_name.'</a>';
                 } else {
@@ -187,11 +200,11 @@ class CourseHome
                     } else {
                         // don't replace img with display::return_icon because $tool['img'] = api_get_path(WEB_IMG_PATH).$tool['img']
                         $cell_content .= '<a href="'.$tool['link'].$link_annex.'" target="'.$tool['target'].'" class="text-muted">
-                                            <img src="'.str_replace(".gif", "_na.gif", $tool['img']).'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">'.$tool_name.'</a>';
+                            <img src="'.str_replace(".gif", "_na.gif", $tool['img']).'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">'.$tool_name.'</a>';
                     }
                 } else {
-                    $cell_content .= '<img src="'.str_replace(".gif", "_na.gif", $tool['img']).'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">';
                     // don't replace img with display::return_icon because $tool['img'] = api_get_path(WEB_IMG_PATH).$tool['img']
+                    $cell_content .= '<img src="'.str_replace(".gif", "_na.gif", $tool['img']).'" title="'.$tool_name.'" alt="'.$tool_name.'" align="absmiddle" border="0">';
                     $cell_content .= '<span class="text-muted">'.$tool_name.'</span>';
                 }
             }
@@ -256,7 +269,9 @@ class CourseHome
             case TOOL_PUBLIC:
                 $condition_display_tools = ' WHERE c_id = '.$course_id.' AND visibility = 1 ';
                 if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
-                    $condition_display_tools = ' WHERE c_id = '.$course_id.' AND (visibility = 1 OR (visibility = 0 AND name = "'.TOOL_TRACKING.'")) ';
+                    $condition_display_tools = ' WHERE 
+                        c_id = '.$course_id.' AND 
+                        (visibility = 1 OR (visibility = 0 AND name = "'.TOOL_TRACKING.'")) ';
                 }
                 $result = Database::query("SELECT * FROM $course_tool_table $condition_display_tools ORDER BY id");
                 $col_link = "##003399";
@@ -373,13 +388,13 @@ class CourseHome
 
                 $tool_name = self::translate_tool_name($tool);
                 $html .= Display::return_icon(
-                        $tool['image'],
-                        $tool_name,
-                        [],
-                        null,
-                        ICON_SIZE_MEDIUM
-                    ).'&nbsp;'.$tool_name.
-                    '</a>';
+                    $tool['image'],
+                    $tool_name,
+                    [],
+                    null,
+                    ICON_SIZE_MEDIUM
+                ).'&nbsp;'.$tool_name.
+                '</a>';
 
                 // This part displays the links to hide or remove a tool.
                 // These links are only visible by the course manager.
@@ -495,7 +510,9 @@ class CourseHome
 
         switch ($course_tool_category) {
             case TOOL_STUDENT_VIEW:
-                $conditions = ' WHERE visibility = 1 AND (category = "authoring" OR category = "interaction" OR category = "plugin") ';
+                $conditions = ' WHERE visibility = 1 AND 
+                                (category = "authoring" OR category = "interaction" OR category = "plugin") AND 
+                                name <> "notebookteacher" ';
                 if ((api_is_coach() || api_is_course_tutor()) && $_SESSION['studentview'] != 'studentview') {
                     $conditions = ' WHERE (
                         visibility = 1 AND (
@@ -909,7 +926,7 @@ class CourseHome
                     if (!empty($tool['adminlink'])) {
                         $item['extra'] = '<a href="'.$tool['adminlink'].'">'.
                             Display::return_icon('edit.gif', get_lang('Edit')).
-                            '</a>';
+                        '</a>';
                     }
                 }
 
@@ -1108,7 +1125,7 @@ class CourseHome
                     <td>'.get_lang('GeneralCoach').': '.'<b>'.$coachInfo['complete_name'].'</b></td></tr>';
         $output .= '<tr>
                         <td>'.get_lang('SessionIdentifier').': '.
-            Display::return_icon('star.png', ' ', ['align' => 'absmiddle']).'
+                            Display::return_icon('star.png', ' ', ['align' => 'absmiddle']).'
                         </td>
                         <td>'.get_lang('Date').': '.'<b>'.$msgDate.'</b>
                         </td>

+ 13 - 2
main/inc/lib/course_request.lib.php

@@ -167,7 +167,12 @@ class CourseRequestManager
 
         $sender_name_teacher = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
         $sender_email_teacher = $user_info['mail'];
-        $recipient_name_admin = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
+        $recipient_name_admin = api_get_person_name(
+            api_get_setting('administratorName'),
+            api_get_setting('administratorSurname'),
+            null,
+            PERSON_NAME_EMAIL_ADDRESS
+        );
         $recipient_email_admin = api_get_setting('emailAdministrator');
 
         $userInfo = api_get_user_info($user_id);
@@ -197,7 +202,13 @@ class CourseRequestManager
         $email_body_teacher .= api_get_person_name($user_info['firstname'], $user_info['lastname'], null, null, $email_language).",\n\n";
         $email_body_teacher .= $email_body;
         $email_body_teacher .= "\n".get_lang('Formula', null, $email_language)."\n";
-        $email_body_teacher .= api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, null, $email_language)."\n";
+        $email_body_teacher .= api_get_person_name(
+                api_get_setting('administratorName'),
+                api_get_setting('administratorSurname'),
+                null,
+                null,
+                $email_language
+            )."\n";
         $email_body_teacher .= get_lang('Manager', null, $email_language).' '.api_get_setting('siteName')."\n";
         $email_body_teacher .= get_lang('Phone', null, $email_language).': '.api_get_setting('administratorTelephone')."\n";
         $email_body_teacher .= get_lang('Email', null, $email_language).': '.api_get_setting('emailAdministrator', null, $email_language)."\n";

+ 2 - 2
main/inc/lib/display.lib.php

@@ -1715,8 +1715,8 @@ class Display
                 $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($session_info['firstname'], $session_info['lastname']);
             }
 
-            if (
-                ($session_info['access_end_date'] == '0000-00-00 00:00:00' && $session_info['access_start_date'] == '0000-00-00 00:00:00') ||
+            if (($session_info['access_end_date'] == '0000-00-00 00:00:00' &&
+                $session_info['access_start_date'] == '0000-00-00 00:00:00') ||
                 (empty($session_info['access_end_date']) && empty($session_info['access_start_date']))
             ) {
                 if (isset($session_info['duration']) && !empty($session_info['duration'])) {

+ 5 - 4
main/inc/lib/document.lib.php

@@ -6630,6 +6630,7 @@ class DocumentManager
      */
     private static function getButtonEdit($isReadOnly, array $documentData, $extension, $isCertificateMode)
     {
+        $extension = strtolower($extension);
         $iconEn = Display::return_icon('edit.png', get_lang('Modify'));
         $iconDis = Display::return_icon('edit_na.png', get_lang('Modify'));
         $courseParams = api_get_cidreq();
@@ -6657,8 +6658,8 @@ class DocumentManager
             }
 
             if (
-                in_array($extension, ['png', 'jpg', 'jpeg', 'bmp', 'gif']) ||
-                ($extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true')
+                in_array($extension, ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'pxd']) &&
+                    api_get_setting('enabled_support_pixlr') == 'true'
             ) {
                 return Display::url($iconEn, "edit_paint.php?$courseParams&id=$document_id");
             }
@@ -6695,8 +6696,8 @@ class DocumentManager
         }
 
         if (
-            in_array($extension, ['png', 'jpg', 'jpeg', 'bmp', 'gif']) ||
-            ($extension == 'pxd' && api_get_setting('enabled_support_pixlr') == 'true')
+            in_array($extension, ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'pxd']) &&
+                api_get_setting('enabled_support_pixlr') == 'true'
         ) {
             return Display::url($iconEn, "edit_paint.php?$courseParams&id=$document_id");
         }

+ 15 - 13
main/inc/lib/formvalidator/FormValidator.class.php

@@ -280,10 +280,11 @@ EOT;
     /**
      * @param string $name
      * @param string $value
+     * @param array  $attributes
      */
-    public function addHidden($name, $value)
+    public function addHidden($name, $value, $attributes = [])
     {
-        $this->addElement('hidden', $name, $value);
+        $this->addElement('hidden', $name, $value, $attributes);
     }
 
     /**
@@ -1745,7 +1746,7 @@ EOT;
                 previewMaxHeight: 50,
                 previewCrop: true,
                 dropzone: $('#dropzone'),                                
-            }).on('fileuploadadd', function (e, data) {
+            }).on('fileuploadadd', function (e, data) {                
                 data.context = $('<div class=\"row\" />').appendTo('#files');
                 $.each(data.files, function (index, file) {
                     var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);                    
@@ -1756,13 +1757,9 @@ EOT;
                     file = data.files[index],
                     node = $(data.context.children()[index]);
                 if (file.preview) {
-                    data.context
-                        .prepend($('<div class=\"col-sm-2\">').html(file.preview))
-                    ;
+                    data.context.prepend($('<div class=\"col-sm-2\">').html(file.preview));
                 } else {
-                    data.context
-                        .prepend($('<div class=\"col-sm-2\">').html('".$icon."'))
-                    ;
+                    data.context.prepend($('<div class=\"col-sm-2\">').html('".$icon."'));
                 }
                 if (index + 1 === data.files.length) {
                     data.context.find('button')
@@ -1784,15 +1781,20 @@ EOT;
                         $(data.context.children()[index]).parent().wrap(link);
                         // Update file name with new one from Chamilo
                         $(data.context.children()[index]).parent().find('.file_name').html(file.name);
-                        var successMessage = $('<div class=\"col-sm-3\">').html(
+                        var message = $('<div class=\"col-sm-3\">').html(
                             $('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('UplUploadSucceeded'))."')
                         );
-                        $(data.context.children()[index]).parent().append(successMessage);                    
+                        $(data.context.children()[index]).parent().append(message);                    
                     } else if (file.error) {
-                        var error = $('<div class=\"col-sm-3\">').html(
+                        var link = $('<div>')
+                            .attr({class : 'panel-image'})                            ;
+                        $(data.context.children()[index]).parent().wrap(link);
+                        // Update file name with new one from Chamilo
+                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);
+                        var message = $('<div class=\"col-sm-3\">').html(
                             $('<span class=\"message-image-danger\"/>').text(file.error)
                         );
-                        $(data.context.children()[index]).parent().append(error);                        
+                        $(data.context.children()[index]).parent().append(message);
                     }
                 });                
                 $('#dropzone').removeClass('hover');                

+ 2 - 0
main/inc/lib/formvalidator/Rule/allowed_tags.inc.php

@@ -314,6 +314,7 @@ $allowed_tags_student['video']['preload'] = [];
 $allowed_tags_student['video']['src'] = [];
 $allowed_tags_student['video']['controls'] = [];
 $allowed_tags_student['video']['id'] = [];
+$allowed_tags_student['video']['class'] = [];
 
 $allowed_tags_student['audio'] = [];
 $allowed_tags_student['audio']['autoplay'] = [];
@@ -323,6 +324,7 @@ $allowed_tags_student['audio']['preload'] = [];
 $allowed_tags_student['audio']['controls'] = [];
 $allowed_tags_student['audio']['muted'] = [];
 $allowed_tags_student['audio']['id'] = [];
+$allowed_tags_student['audio']['class'] = [];
 
 $allowed_tags_student['source'] = [];
 $allowed_tags_student['source']['type'] = [];

+ 12 - 10
main/inc/lib/internationalization.lib.php

@@ -420,10 +420,6 @@ function api_get_local_time(
     if (is_null($from_timezone)) {
         $from_timezone = 'UTC';
     }
-    // Determining the timezone to be converted to
-    if (is_null($to_timezone)) {
-        $to_timezone = api_get_timezone();
-    }
 
     // If time is a timestamp, convert it to a string
     if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
@@ -433,6 +429,7 @@ function api_get_local_time(
         $from_timezone = 'UTC';
         $time = gmdate('Y-m-d H:i:s');
     }
+
     if (is_numeric($time)) {
         $time = intval($time);
         if ($return_null_if_invalid_date) {
@@ -450,6 +447,11 @@ function api_get_local_time(
     }
 
     try {
+        // Determining the timezone to be converted to
+        if (is_null($to_timezone)) {
+            $to_timezone = api_get_timezone();
+        }
+
         $date = new DateTime($time, new DateTimezone($from_timezone));
         $date->setTimezone(new DateTimeZone($to_timezone));
 
@@ -789,8 +791,7 @@ function api_get_months_long($language = null)
  * @param string     $language   (optional)
  *                               The language id. If it is omitted, the current interface language is assumed.
  *                               This parameter has meaning with the format PERSON_NAME_COMMON_CONVENTION only.
- * @param string     $encoding   (optional)    The used internally by this function
- *                               character encoding. If it is omitted, the platform character set will be used by default.
+ * @param string     $username
  *
  * @return string The result is sort of full name of the person.
  *                Sample results:
@@ -809,7 +810,6 @@ function api_get_person_name(
     $title = null,
     $format = null,
     $language = null,
-    $encoding = null,
     $username = null
 ) {
     static $valid = [];
@@ -2186,7 +2186,8 @@ function _api_get_character_map_name($encoding)
  */
 
 /**
- * A reverse function from php-core function strnatcmp(), performs string comparison in reverse natural (alpha-numerical) order.
+ * A reverse function from php-core function strnatcmp(),
+ * performs string comparison in reverse natural (alpha-numerical) order.
  *
  * @param string $string1 the first string
  * @param string $string2 the second string
@@ -2201,10 +2202,11 @@ function _api_strnatrcmp($string1, $string2)
 /**
  * Sets/Gets internal character encoding of the common string functions within the PHP mbstring extension.
  *
- * @param string $encoding (optional)	When this parameter is given, the function sets the internal encoding
+ * @param string $encoding (optional)    When this parameter is given, the function sets the internal encoding
  *
  * @return string When $encoding parameter is not given, the function returns the internal encoding.
- *                Note: This function is used in the global initialization script for setting the internal encoding to the platform's character set.
+ *                Note: This function is used in the global initialization script for setting the
+ *                internal encoding to the platform's character set.
  *
  * @see http://php.net/manual/en/function.mb-internal-encoding
  */

+ 13 - 3
main/inc/lib/message.lib.php

@@ -1077,15 +1077,25 @@ class MessageManager
             $userInfo = api_get_user_info($senderId);
             if ($request === true) {
                 $message[1] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.$userInfo['complete_name_with_username'].'</a>';
-                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace("\\", "", $title).'</a>';
+                $message[2] = '<a onclick="show_sent_message('.$messageId.')" href="javascript:void(0)">'.str_replace(
+                        "\\",
+                        "",
+                        $title
+                    ).'</a>';
                 //date stays the same
                 $message[3] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
-                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(get_lang('DeleteMessage')).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
+                $message[4] = '&nbsp;&nbsp;<a title="'.addslashes(
+                        get_lang('DeleteMessage')
+                    ).'" onclick="delete_one_message_outbox('.$messageId.')" href="javascript:void(0)"  >'.
                     Display::returnFontAwesomeIcon('trash', 2).'</a>';
             } else {
                 $message[1] = '<a '.$class.' onclick="show_sent_message('.$messageId.')" href="../messages/view_message.php?id_send='.$messageId.'">'.$title.'</a><br />'.$userInfo['complete_name_with_username'];
                 $message[2] = api_convert_and_format_date($sendDate, DATE_TIME_FORMAT_LONG);
-                $message[3] = '<a title="'.addslashes(get_lang('DeleteMessage')).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmDeleteMessage')))."'".')) return false;" >'.
+                $message[3] = '<a title="'.addslashes(
+                        get_lang('DeleteMessage')
+                    ).'" href="outbox.php?action=deleteone&id='.$messageId.'"  onclick="javascript:if(!confirm('."'".addslashes(
+                        api_htmlentities(get_lang('ConfirmDeleteMessage'))
+                    )."'".')) return false;" >'.
                     Display::returnFontAwesomeIcon('trash', 2).'</a>';
             }
 

+ 5 - 1
main/lp/learnpath.class.php

@@ -12947,7 +12947,11 @@ EOD;
      */
     private static function get_level_for_item($items, $currentItemId)
     {
-        $parentItemId = $items[$currentItemId]->parent;
+        $parentItemId = 0;
+        if (isset($items[$currentItemId])) {
+            $parentItemId = $items[$currentItemId]->parent;
+        }
+
         if ($parentItemId == 0) {
             return 0;
         } else {

+ 7 - 3
main/lp/lp_controller.php

@@ -46,7 +46,7 @@ $htmlHeadXtra[] = '<script>
 function setFocus(){
     $("#idTitle").focus();
 }
-$(window).on("load", function (e) {
+$(window).on("load", function () {
     setFocus();
 });
 </script>';
@@ -997,8 +997,12 @@ switch ($action) {
                 $hide_toc_frame = null;
             }
             $_SESSION['oLP']->set_hide_toc_frame($hide_toc_frame);
-            $_SESSION['oLP']->set_prerequisite($_REQUEST['prerequisites']);
-            $_SESSION['oLP']->set_use_max_score($_REQUEST['use_max_score']);
+            $_SESSION['oLP']->set_prerequisite(
+                isset($_POST['prerequisites']) ? (int) $_POST['prerequisites'] : 0
+            );
+            $_SESSION['oLP']->set_use_max_score(
+                isset($_POST['use_max_score']) ? 1 : 0
+            );
 
             $subscribeUsers = isset($_REQUEST['subscribe_users']) ? 1 : 0;
             $_SESSION['oLP']->setSubscribeUsers($subscribeUsers);

+ 0 - 1
main/lp/lp_final_item.php

@@ -110,7 +110,6 @@ if ($accessGranted == false) {
     );
     // If not gradebook has been defined
     if (empty($catLoad)) {
-        // TODO: Missing validation of learning path completion
         $finalItemTemplate = generateLPFinalItemTemplate(
             $id,
             $courseCode,

+ 1 - 1
main/lp/lp_impress.php

@@ -39,7 +39,7 @@ if (!api_is_allowed_to_edit(null, true) && intval($visibility) == 0) {
 }
 /** @var learnpath $lp */
 $lp = Session::read('oLP');
-if ($lp) {
+if (!$lp) {
     api_not_allowed(true);
 }
 

+ 7 - 1
main/lp/lp_list.php

@@ -176,7 +176,7 @@ $data = [];
 foreach ($categories as $item) {
     $categoryId = $item->getId();
 
-    if (!learnpath::categoryIsVisibleForStudent($item, $user)) {
+    if ($user && !learnpath::categoryIsVisibleForStudent($item, $user)) {
         continue;
     }
 
@@ -889,6 +889,12 @@ foreach ($categories as $item) {
 // Deleting the objects
 Session::erase('oLP');
 Session::erase('lpobject');
+Session::erase('scorm_view_id');
+Session::erase('scorm_item_id');
+Session::erase('exerciseResult');
+Session::erase('objExercise');
+Session::erase('questionList');
+
 learnpath::generate_learning_path_folder($courseInfo);
 DocumentManager::removeGeneratedAudioTempFile();
 

+ 125 - 168
main/mySpace/index.php

@@ -15,10 +15,12 @@ $cidReset = true;
 require_once __DIR__.'/../inc/global.inc.php';
 
 $htmlHeadXtra[] = api_get_jqgrid_js();
+$htmlHeadXtra[] = '<script type="text/javascript" src="'
+    .api_get_path(WEB_PUBLIC_PATH).'assets/jquery.easy-pie-chart/dist/jquery.easypiechart.js"></script>';
 // the section (for the tabs)
 $this_section = SECTION_TRACKING;
 //for HTML editor repository
-Session::erase('this_section');
+//Session::erase('this_section');
 
 ob_start();
 $nameTools = get_lang('MySpace');
@@ -36,10 +38,10 @@ $skipData = api_get_configuration_value('tracking_skip_generic_data');
 
 // Access control
 api_block_anonymous_users();
-
+/*
 if (!$export_csv) {
-    Display :: display_header($nameTools);
-}
+     Display :: display_header($nameTools);
+} */
 
 if ($is_session_admin) {
     header('location:session.php');
@@ -127,43 +129,87 @@ if ($is_drh) {
     );
 }
 
-echo '<div id="actions" class="actions">';
-echo '<span style="float:right">';
+$actionsRight = '';
+$actionsLeft = '';
 if ($display == 'useroverview' || $display == 'sessionoverview' || $display == 'courseoverview') {
-    echo '<a href="'.api_get_self().'?display='.$display.'&export=csv&view='.$view.'">';
-    echo Display::return_icon("export_csv.png", get_lang('ExportAsCSV'), [], 32);
-    echo '</a>';
+    $actionsRight .= Display::url(
+        Display::return_icon(
+            "export_csv.png",
+            get_lang('ExportAsCSV'),
+            null,
+            ICON_SIZE_MEDIUM
+        ),
+        api_get_self().'?display='.$display.'&export=csv&view='.$view
+    );
 }
-echo '<a href="javascript: void(0);" onclick="javascript: window.print()">'.
-    Display::return_icon('printer.png', get_lang('Print'), '', ICON_SIZE_MEDIUM).'</a>';
-echo '</span>';
+$actionsRight .= Display::url(
+    Display::return_icon(
+        'printer.png',
+        get_lang('Print'),
+        null,
+        ICON_SIZE_MEDIUM
+    ),
+    'javascript: void(0);',
+    ['onclick' => 'javascript: window.print()']
+);
 
 if (!empty($session_id) &&
-    !in_array($display, ['accessoverview', 'lpprogressoverview', 'progressoverview', 'exerciseprogress', 'surveyoverview'])
+    !in_array(
+        $display,
+        ['accessoverview', 'lpprogressoverview', 'progressoverview', 'exerciseprogress', 'surveyoverview']
+    )
 ) {
-    echo '<a href="index.php">'.Display::return_icon('back.png', get_lang('Back'), '', ICON_SIZE_MEDIUM).'</a>';
+    $actionsLeft .= Display::url(
+        Display::return_icon(
+            'back.png',
+            get_lang('Back'),
+            null,
+            ICON_SIZE_MEDIUM
+        ),
+        'index.php'
+    );
     if (!api_is_platform_admin()) {
         if (api_get_setting('add_users_by_coach') == 'true') {
             if ($is_coach) {
-                echo "<div align=\"right\">";
-                echo '<a href="user_import.php?id_session='.$session_id.'&action=export&amp;type=xml">'.
-                        Display::return_icon('excel.gif', get_lang('ImportUserList')).'&nbsp;'.get_lang('ImportUserList').'</a>';
-                echo "</div><br />";
+                $actionsLeft .= Display::url(
+                    Display::return_icon(
+                        'excel.png',
+                        get_lang('ImportUserList'),
+                        null,
+                        ICON_SIZE_MEDIUM
+                    ),
+                    'user_import.php?id_session='.$session_id.'&action=export&amp;type=xml'
+                );
             }
         }
     } else {
-        echo "<div align=\"right\">";
-        echo '<a href="user_import.php?id_session='.$session_id.'&action=export&amp;type=xml">'.
-                Display::return_icon('excel.gif', get_lang('ImportUserList')).'&nbsp;'.get_lang('ImportUserList').'</a>';
-        echo "</div><br />";
+        Display::url(
+            Display::return_icon(
+                'excel.png',
+                get_lang('ImportUserList'),
+                null,
+                ICON_SIZE_MEDIUM
+            ),
+            'user_import.php?id_session='.$session_id.'&action=export&amp;type=xml'
+        );
     }
 } else {
-    echo Display::url(
-        Display::return_icon('stats.png', get_lang('MyStats'), '', ICON_SIZE_MEDIUM),
+    $actionsLeft .= Display::url(
+        Display::return_icon(
+            'stats.png',
+            get_lang('MyStats'),
+            null,
+            ICON_SIZE_MEDIUM
+        ),
         api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
     );
-    echo Display::url(
-        Display::return_icon("certificate_list.png", get_lang("GradebookSeeListOfStudentsCertificates"), [], ICON_SIZE_MEDIUM),
+    $actionsLeft .= Display::url(
+        Display::return_icon(
+            "certificate_list.png",
+            get_lang("GradebookSeeListOfStudentsCertificates"),
+            null,
+            ICON_SIZE_MEDIUM
+        ),
         api_get_path(WEB_CODE_PATH)."gradebook/certificate_report.php"
     );
 }
@@ -171,17 +217,18 @@ if (!empty($session_id) &&
 // Actions menu
 $nb_menu_items = count($menu_items);
 if (empty($session_id) ||
-    in_array($display, ['accessoverview', 'lpprogressoverview', 'progressoverview', 'exerciseprogress', 'surveyoverview'])
+    in_array(
+        $display,
+        ['accessoverview', 'lpprogressoverview', 'progressoverview', 'exerciseprogress', 'surveyoverview']
+    )
 ) {
     if ($nb_menu_items > 1) {
         foreach ($menu_items as $key => $item) {
-            echo $item;
+            $actionsLeft .= $item;
         }
     }
 }
 
-echo '</div>';
-
 $userId = api_get_user_id();
 $stats = Tracking::getStats($userId, true);
 
@@ -213,103 +260,18 @@ $daysAgo = 7;
 $studentIds = [];
 $avg_courses_per_student = 0;
 
-$linkAddUser = null;
-$linkCourseDetailsAsTeacher = null;
-$linkAddCourse = null;
-$linkAddSession = null;
-
-if (api_is_platform_admin()) {
-    $linkAddUser = ' '.Display::url(
-        Display::return_icon('2rightarrow.png', get_lang('Add')),
-        api_get_path(WEB_CODE_PATH).'admin/dashboard_add_users_to_user.php?user='.api_get_user_id(),
-        ['class' => '']
-    );
-    $linkCourseDetailsAsTeacher = ' '.Display::url(
-        Display::return_icon('2rightarrow.png', get_lang('Details')),
-        api_get_path(WEB_CODE_PATH).'mySpace/course.php',
-        ['class' => '']
-    );
-    $linkAddCourse = ' '.Display::url(
-        Display::return_icon('2rightarrow.png', get_lang('Details')),
-        api_get_path(WEB_CODE_PATH).'mySpace/course.php?follow',
-        ['class' => '']
-    );
-    $linkAddSession = ' '.Display::url(
-        Display::return_icon('2rightarrow.png', get_lang('Add')),
-        api_get_path(WEB_CODE_PATH).'admin/dashboard_add_sessions_to_user.php?user='.api_get_user_id(),
-        ['class' => '']
-    );
-}
-
-echo Display::page_subheader(get_lang('Overview'));
-echo '<div class="report_section">
-        <table class="table table-bordered table-striped">
-            <tr>
-                <td>'.Display::url(
-                    get_lang('FollowedStudents'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/student.php'
-                ).'</td>
-                <td align="right">'.$numberStudents.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                    get_lang('FollowedStudentBosses'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/users.php?status='.STUDENT_BOSS
-                ).'</td>
-                <td align="right">'.$numberStudentBosses.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                    get_lang('FollowedTeachers'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/teachers.php'
-                ).
-                '</td>
-                <td align="right">'.$numberTeachers.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                get_lang('FollowedHumanResources'),
-                api_get_path(WEB_CODE_PATH).'mySpace/users.php?status='.DRH
-            ).
-            '</td>
-            <td align="right">'.$countHumanResourcesUsers.'</td>
-            </tr>
-            <tr>
-             <td>'.Display::url(
-                get_lang('FollowedUsers'),
-                api_get_path(WEB_CODE_PATH).'mySpace/users.php'
-            ).
-            '</td>
-                <td align="right">'.($numberStudents + $numberStudentBosses + $numberTeachers + $countHumanResourcesUsers).$linkAddUser.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                    get_lang('AssignedCourses'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/course.php'
-                ).
-                '</td>
-                <td align="right">'.$countCourses.$linkCourseDetailsAsTeacher.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                    get_lang('FollowedCourses'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/course.php?follow'
-                ).
-                '</td>
-                <td align="right">'.$countAssignedCourses.$linkAddCourse.'</td>
-            </tr>
-            <tr>
-                <td>'.Display::url(
-                    get_lang('FollowedSessions'),
-                    api_get_path(WEB_CODE_PATH).'mySpace/session.php'
-                ).
-                '</td>
-            <td align="right">'.$countSessions.$linkAddSession.'</td>
-            </tr>
-            </table>';
-echo '</div>';
-
-echo Display::page_subheader(get_lang('Students').' ('.$numberStudents.')');
+$view = new Template($nameTools);
+$view->assign('students', $numberStudents);
+$view->assign('studentbosses', $numberStudentBosses);
+$view->assign('numberTeachers', $numberTeachers);
+$view->assign('humanresources', $countHumanResourcesUsers);
+$view->assign(
+    'total_user',
+    $numberStudents + $numberStudentBosses + $numberTeachers + $countHumanResourcesUsers
+);
+$view->assign('studentboss', STUDENT_BOSS);
+$view->assign('drh', DRH);
+$view->assign('stats', $stats);
 
 $form = new FormValidator(
     'search_user',
@@ -317,7 +279,6 @@ $form = new FormValidator(
     api_get_path(WEB_CODE_PATH).'mySpace/student.php'
 );
 $form = Tracking::setUserSearchForm($form);
-$form->display();
 
 $skipData = api_get_configuration_value('tracking_skip_generic_data');
 
@@ -347,8 +308,18 @@ if ($skipData == false) {
         $csv_content[] = [get_lang('InactivesStudents'), $nb_inactive_students];
         $csv_content[] = [get_lang('AverageTimeSpentOnThePlatform'), $totalTimeSpent];
         $csv_content[] = [get_lang('AverageCoursePerStudent'), $avg_courses_per_student];
-        $csv_content[] = [get_lang('AverageProgressInLearnpath'), is_null($avgTotalProgress) ? null : round($avgTotalProgress, 2).'%'];
-        $csv_content[] = [get_lang('AverageResultsToTheExercices'), is_null($averageScore) ? null : round($averageScore, 2).'%'];
+        $csv_content[] = [
+            get_lang('AverageProgressInLearnpath'),
+            is_null($avgTotalProgress)
+                ? null
+                : round($avgTotalProgress, 2).'%',
+        ];
+        $csv_content[] = [
+            get_lang('AverageResultsToTheExercices'),
+            is_null($averageScore)
+                ? null
+                : round($averageScore, 2).'%',
+        ];
         $csv_content[] = [get_lang('AveragePostsInForum'), $posts];
         $csv_content[] = [get_lang('AverageAssignments'), $numberAssignments];
         $csv_content[] = [];
@@ -376,50 +347,36 @@ if ($skipData == false) {
             $sessionIdList,
             $studentIds
         );
-
-        // html part
-        echo '<div class="report_section">
-                <table class="table table-bordered table-striped">
-                    <tr>
-                        <td>'.get_lang('AverageCoursePerStudent').'</td>
-                        <td align="right">'.(is_null($avg_courses_per_student) ? '' : round($avg_courses_per_student, 2)).'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('InactivesStudents').'</td>
-                        <td align="right">'.$nb_inactive_students.'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('AverageTimeSpentOnThePlatform').'</td>
-                        <td align="right">'.(is_null($totalTimeSpent) ? '' : api_time_to_hms($totalTimeSpent)).'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('AverageProgressInLearnpath').'</td>
-                        <td align="right">'.(is_null($avgTotalProgress) ? '' : round($avgTotalProgress, 2).'%').'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('AvgCourseScore').'</td>
-                        <td align="right">'.(is_null($averageScore) ? '' : round($averageScore, 2).'%').'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('AveragePostsInForum').'</td>
-                        <td align="right">'.(is_null($posts) ? '' : round($posts, 2)).'</td>
-                    </tr>
-                    <tr>
-                        <td>'.get_lang('AverageAssignments').'</td>
-                        <td align="right">'.(is_null($numberAssignments) ? '' : round($numberAssignments, 2)).'</td>
-                    </tr>
-                </table>
-             </div>';
+        $report['AverageCoursePerStudent'] = is_null($avg_courses_per_student)
+            ? ''
+            : round($avg_courses_per_student, 2);
+        $report['InactivesStudents'] = $nb_inactive_students;
+        $report['AverageTimeSpentOnThePlatform'] = is_null($totalTimeSpent)
+            ? '00:00:00'
+            : api_time_to_hms($totalTimeSpent);
+        $report['AverageProgressInLearnpath'] = is_null($avgTotalProgress)
+            ? ''
+            : round($avgTotalProgress, 2).'%';
+        $report['AvgCourseScore'] = is_null($averageScore) ? '0' : round($averageScore, 2).'%';
+        $report['AveragePostsInForum'] = is_null($posts) ? '0' : round($posts, 2);
+        $report['AverageAssignments'] = is_null($numberAssignments) ? '' : round($numberAssignments, 2);
+        $view->assign('report', $report);
     }
 }
 
+$view->assign('header', $nameTools);
+$view->assign('form', $form->returnForm());
+$view->assign('actions', Display::toolbarAction('toolbar', [$actionsLeft, $actionsRight]));
+$view->assign('title', get_lang('Students').' ('.$numberStudents.')');
+
+$template = $view->get_template('my_space/index.tpl');
+$content = $view->fetch($template);
+$view->assign('content', $content);
+$view->display_one_col_template();
+
 // Send the csv file if asked
 if ($export_csv) {
     ob_end_clean();
     Export:: arrayToCsv($csv_content, 'reporting_index');
     exit;
 }
-
-if (!$export_csv) {
-    Display::display_footer();
-}

+ 10 - 0
main/mySpace/myStudents.php

@@ -418,6 +418,16 @@ if (!empty($student_id) && !empty($course_code)) {
         Display::return_icon('statistics.png', get_lang('AccessDetails'), '', ICON_SIZE_MEDIUM).
         '</a>';
 }
+
+$notebookTeacherEnable = api_get_plugin_setting('notebookteacher', 'enable_plugin_notebookteacher') === 'true';
+if ($notebookTeacherEnable && !empty($student_id) && !empty($course_code)) {
+    // link notebookteacher
+    $optionsLink = 'student_id='.$student_id.'&origin='.$origin.'&cidReq='.$course_code.'&id_session='.$sessionId;
+    echo '<a href="'.api_get_path(WEB_PLUGIN_PATH).'notebookteacher/src/index.php?'.$optionsLink.'">'.
+        Display::return_icon('notebookteacher.png', get_lang('Notebook'), '', ICON_SIZE_MEDIUM).
+    '</a>';
+}
+
 if (api_can_login_as($student_id)) {
     echo '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_list.php?action=login_as&user_id='.$student_id.'&sec_token='.$token.'">'.
         Display::return_icon('login_as.png', get_lang('LoginAs'), null, ICON_SIZE_MEDIUM).'</a>&nbsp;&nbsp;';

+ 63 - 17
main/mySpace/users.php

@@ -2,7 +2,7 @@
 /* For licensing terms, see /license.txt */
 
 /**
- * Student report.
+ * Report on users followed (filtered by status given in URL).
  *
  * @package chamilo.reporting
  */
@@ -10,6 +10,8 @@ $cidReset = true;
 
 require_once __DIR__.'/../inc/global.inc.php';
 
+$nameTools = get_lang('Users');
+
 $export_csv = isset($_GET['export']) && $_GET['export'] == 'csv' ? true : false;
 $keyword = isset($_GET['keyword']) ? Security::remove_XSS($_GET['keyword']) : null;
 $active = isset($_GET['active']) ? intval($_GET['active']) : 1;
@@ -109,7 +111,6 @@ function get_users($from, $limit, $column, $direction)
     }
 
     $all_datas = [];
-
     foreach ($students as $student_data) {
         $student_id = $student_data['user_id'];
         if (isset($_GET['id_session'])) {
@@ -153,6 +154,7 @@ function get_users($from, $limit, $column, $direction)
             $row[] = $student_data['lastname'];
             $row[] = $student_data['firstname'];
         }
+
         $string_date = Tracking::get_last_connection_date($student_id, true);
         $first_date = Tracking::get_first_connection_date($student_id);
         $row[] = $first_date;
@@ -165,6 +167,7 @@ function get_users($from, $limit, $column, $direction)
             $detailsLink = '<a href="myStudents.php?student='.$student_id.'">
 				            '.Display::return_icon('2rightarrow.png', get_lang('Details')).'</a>';
         }
+
         $row[] = $detailsLink;
         $all_datas[] = $row;
     }
@@ -183,11 +186,30 @@ $actionsLeft = '';
 
 if (api_is_drh()) {
     $menu_items = [
-        Display::url(Display::return_icon('stats.png', get_lang('MyStats'), '', ICON_SIZE_MEDIUM), api_get_path(WEB_CODE_PATH)."auth/my_progress.php"),
-        Display::url(Display::return_icon('user_na.png', get_lang('Students'), [], ICON_SIZE_MEDIUM), '#'),
-        Display::url(Display::return_icon('teacher.png', get_lang('Trainers'), [], ICON_SIZE_MEDIUM), 'teachers.php'),
-        Display::url(Display::return_icon('course.png', get_lang('Courses'), [], ICON_SIZE_MEDIUM), 'course.php'),
-        Display::url(Display::return_icon('session.png', get_lang('Sessions'), [], ICON_SIZE_MEDIUM), 'session.php'),
+        Display::url(
+            Display::return_icon('stats.png', get_lang('MyStats'), '', ICON_SIZE_MEDIUM),
+            api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
+        ),
+        Display::url(
+            Display::return_icon('user_na.png', get_lang('Students'), [], ICON_SIZE_MEDIUM),
+            '#'
+        ),
+        Display::url(
+            Display::return_icon('teacher.png', get_lang('Trainers'), [], ICON_SIZE_MEDIUM),
+            'teachers.php'
+        ),
+        Display::url(
+            Display::return_icon('course.png', get_lang('Courses'), [], ICON_SIZE_MEDIUM),
+            'course.php'
+        ),
+        Display::url(
+            Display::return_icon('session.png', get_lang('Sessions'), [], ICON_SIZE_MEDIUM),
+            'session.php'
+        ),
+        Display::url(
+            Display::return_icon('skills.png', get_lang('Skills'), [], ICON_SIZE_MEDIUM),
+            'skills.php'
+        ),
     ];
 
     $nb_menu_items = count($menu_items);
@@ -196,6 +218,28 @@ if (api_is_drh()) {
             $actionsLeft .= $item;
         }
     }
+} elseif (api_is_student_boss()) {
+    $actionsLeft .= Display::url(
+        Display::return_icon('stats.png', get_lang('MyStats'), '', ICON_SIZE_MEDIUM),
+        api_get_path(WEB_CODE_PATH)."auth/my_progress.php"
+    );
+    $actionsLeft .= Display::url(
+        Display::return_icon('user_na.png', get_lang('Students'), [], ICON_SIZE_MEDIUM),
+        '#'
+    );
+    $actionsLeft .= Display::url(
+        Display::return_icon("statistics.png", get_lang("CompanyReport"), [], ICON_SIZE_MEDIUM),
+        api_get_path(WEB_CODE_PATH)."mySpace/company_reports.php"
+    );
+    $actionsLeft .= Display::url(
+        Display::return_icon(
+            "certificate_list.png",
+            get_lang("GradebookSeeListOfStudentsCertificates"),
+            [],
+            ICON_SIZE_MEDIUM
+        ),
+        api_get_path(WEB_CODE_PATH)."gradebook/certificate_report.php"
+    );
 }
 
 $actionsRight = Display::url(
@@ -207,6 +251,7 @@ $actionsRight .= Display::url(
     Display::return_icon('export_csv.png', get_lang('ExportAsCSV'), [], ICON_SIZE_MEDIUM),
     api_get_self().'?export=csv&keyword='.$keyword
 );
+
 $toolbar = Display::toolbarAction('toolbar-user', [$actionsLeft, $actionsRight]);
 
 $table = new SortableTable(
@@ -255,8 +300,11 @@ if ($export_csv) {
     }
 }
 
-$form = new FormValidator('search_user', 'get', api_get_path(WEB_CODE_PATH).'mySpace/users.php');
-
+$form = new FormValidator(
+    'search_user',
+    'get',
+    api_get_path(WEB_CODE_PATH).'mySpace/users.php'
+);
 $form->addElement(
     'select',
     'status',
@@ -271,22 +319,20 @@ $form->addElement(
 $form = Tracking::setUserSearchForm($form);
 $form->setDefaults($params);
 
-// send the csv file if asked
-$content = $table->get_table_data();
-
 if ($export_csv) {
+    // send the csv file if asked
+    $content = $table->get_table_data();
     foreach ($content as &$row) {
         unset($row[4]);
     }
     $csv_content = array_merge($csv_header, $content);
     ob_end_clean();
-    Export :: arrayToCsv($csv_content, 'reporting_student_list');
+    Export::arrayToCsv($csv_content, 'reporting_student_list');
     exit;
 } else {
-    Display::display_header(get_lang('Users'));
+    Display::display_header($nameTools);
     echo $toolbar;
-    $page_title = get_lang('Users');
-    echo Display::page_subheader($page_title);
+    echo Display::page_subheader($nameTools);
     if (isset($active)) {
         if ($active) {
             $activeLabel = get_lang('ActiveUsers');
@@ -299,4 +345,4 @@ if ($export_csv) {
     $table->display();
 }
 
-Display :: display_footer();
+Display::display_footer();

+ 3 - 5
main/session/session_edit.php

@@ -223,16 +223,14 @@ function accessSwitcher(accessFromReady) {
         access = accessFromReady;
         $('[name=access]').val(access);
     }
-
     if (access == 1) {
-        $('#duration').hide();
+        $('#duration_div').hide();
         $('#date_fields').show();
+        emptyDuration();
     } else {
-
-        $('#duration').show();
+        $('#duration_div').show();
         $('#date_fields').hide();
     }
-    emptyDuration();
 }
 
 function emptyDuration() {

+ 7 - 1
main/social/group_view.php

@@ -278,7 +278,13 @@ if ($is_group_member || $group_info['visibility'] == GROUP_PERMISSION_OPEN) {
                 $userPicture = UserManager::getUserPicture($member['id']);
                 $member_content .= '<div class="col-md-3">';
                 $member_content .= '<div class="items-user">';
-                $member_name = Display::url(api_get_person_name(cut($member['user_info']['firstname'], 15), cut($member['user_info']['lastname'], 15)).'&nbsp;'.$icon, $member['user_info']['profile_url']);
+                $member_name = Display::url(
+                    api_get_person_name(
+                        cut($member['user_info']['firstname'], 15),
+                        cut($member['user_info']['lastname'], 15)
+                    ).'&nbsp;'.$icon,
+                    $member['user_info']['profile_url']
+                );
                 $member_content .= Display::div('<img class="img-circle" src="'.$userPicture.'"/>', ['class' => 'avatar']);
                 $member_content .= Display::div($member_name, ['class' => 'name']);
                 $member_content .= '</div>';

+ 5 - 12
main/wiki/wiki.inc.php

@@ -1922,8 +1922,7 @@ class Wiki
             }
             if ($exist == false) {
                 $sql = "INSERT INTO ".$tbl_wiki_mailcue." (c_id, id, user_id, type, group_id, session_id) VALUES
-                ($course_id, '".$id."','".api_get_user_id(
-                    )."','P','".$groupId."','".$session_id."')";
+                ($course_id, '".$id."','".api_get_user_id()."','P','".$groupId."','".$session_id."')";
                 Database::query($sql);
             }
             $status_notify = 1;
@@ -1977,8 +1976,7 @@ class Wiki
         $id = $row['id'];
         $sql = 'SELECT * FROM '.$tbl_wiki_mailcue.'
                 WHERE 
-                    c_id = '.$course_id.' AND id="'.$id.'" AND user_id="'.api_get_user_id(
-            ).'" AND type="D"';
+                    c_id = '.$course_id.' AND id="'.$id.'" AND user_id="'.api_get_user_id().'" AND type="D"';
         $result = Database::query($sql);
         $row = Database::fetch_array($result);
         $idm = $row['id'];
@@ -2053,8 +2051,7 @@ class Wiki
             $status_notify_all == 0
         ) {
             $sql = "INSERT INTO ".$tbl_wiki_mailcue." (c_id, user_id, type, group_id, session_id) VALUES
-            ($course_id, '".api_get_user_id(
-                )."','F','".$groupId."','".$session_id."')";
+            ($course_id, '".api_get_user_id()."','F','".$groupId."','".$session_id."')";
             Database::query($sql);
             $status_notify_all = 1;
         }
@@ -2106,9 +2103,7 @@ class Wiki
             //first, current author and time
             //Who is the author?
             $userinfo = api_get_user_info($lastuser);
-            $email_user_author = get_lang(
-                    'EditedBy'
-                ).': '.$userinfo['complete_name'];
+            $email_user_author = get_lang('EditedBy').': '.$userinfo['complete_name'];
 
             //When ?
             $year = substr($lastime, 0, 4);
@@ -2151,9 +2146,7 @@ class Wiki
             //first, current author and time
             //Who is the author of last message?
             $userinfo = api_get_user_info($lastuser);
-            $email_user_author = get_lang(
-                    'AddedBy'
-                ).': '.$userinfo['complete_name'];
+            $email_user_author = get_lang('AddedBy').': '.$userinfo['complete_name'];
 
             //When ?
             $year = substr($lastime, 0, 4);

+ 1 - 1
src/CoreBundle/Entity/Repository/SessionRepository.php

@@ -23,7 +23,7 @@ class SessionRepository extends EntityRepository
      *
      * @param Session $session The session
      *
-     * @return \Doctrine\ORM\QueryBuilder
+     * @return array
      */
     public function getCoursesOrderedByPosition(Session $session)
     {

+ 1 - 2
src/CoreBundle/Entity/Repository/TemplatesRepository.php

@@ -5,7 +5,6 @@ namespace Chamilo\CoreBundle\Entity\Repository;
 
 use Chamilo\CoreBundle\Entity\Course;
 use Chamilo\UserBundle\Entity\User;
-use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\ORM\EntityRepository;
 use Doctrine\ORM\Query\Expr\Join;
 
@@ -20,7 +19,7 @@ class TemplatesRepository extends EntityRepository
      * @param Course $course
      * @param User   $user
      *
-     * @return ArrayCollection
+     * @return array
      */
     public function getCourseTemplates(Course $course, User $user)
     {

+ 3 - 2
src/CourseBundle/Component/CourseCopy/Course.php

@@ -92,7 +92,8 @@ class Course
 
     /**
      * Returns sample text based on the imported course content.
-     * This sample text is to be used for course language or encoding detection if there is missing (meta)data in the archive.
+     * This sample text is to be used for course language or encoding
+     * detection if there is missing (meta)data in the archive.
      *
      * @return string the resulting sample text extracted from some common resources' data fields
      */
@@ -283,7 +284,7 @@ class Course
                             $resource->question = api_to_system_encoding($resource->question, $this->encoding);
                             $resource->description = api_to_system_encoding($resource->description, $this->encoding);
                             if (is_array($resource->answers) && count($resource->answers) > 0) {
-                                foreach ($resource->answers as $index => &$answer) {
+                                foreach ($resource->answers as &$answer) {
                                     $answer['answer'] = api_to_system_encoding($answer['answer'], $this->encoding);
                                     $answer['comment'] = api_to_system_encoding($answer['comment'], $this->encoding);
                                 }

+ 5 - 5
src/CourseBundle/Component/CourseCopy/CourseArchiver.php

@@ -124,14 +124,11 @@ class CourseArchiver
         // Copy all scorm documents to the temp-dir
         if (isset($course->resources[RESOURCE_SCORM]) && is_array($course->resources[RESOURCE_SCORM])) {
             foreach ($course->resources[RESOURCE_SCORM] as $document) {
-                $doc_dir = dirname($backup_dir.$document->path);
-                @mkdir($doc_dir, $perm_dirs, true);
-                copyDirTo($course->path.$document->path, $doc_dir, false);
+                copyDirTo($course->path.$document->path, $backup_dir.$document->path, false);
             }
         }
 
         // Copy calendar attachments.
-
         if (isset($course->resources[RESOURCE_EVENT]) && is_array($course->resources[RESOURCE_EVENT])) {
             $doc_dir = dirname($backup_dir.'/upload/calendar/');
             @mkdir($doc_dir, $perm_dirs, true);
@@ -213,7 +210,10 @@ class CourseArchiver
                     $date = $file_parts[0];
                     $ext = isset($file_parts[1]) ? $file_parts[1] : null;
                     if ($ext == 'zip' && ($user_id != null && $owner_id == $user_id || $user_id == null)) {
-                        $date = substr($date, 0, 4).'-'.substr($date, 4, 2).'-'.substr($date, 6, 2).' '.substr($date, 9, 2).':'.substr($date, 11, 2).':'.substr($date, 13, 2);
+                        $date =
+                            substr($date, 0, 4).'-'.substr($date, 4, 2).'-'.
+                            substr($date, 6, 2).' '.substr($date, 9, 2).':'.
+                            substr($date, 11, 2).':'.substr($date, 13, 2);
                         $backup_files[] = [
                             'file' => $file,
                             'date' => $date,

+ 15 - 14
src/CourseBundle/Component/CourseCopy/CourseRestorer.php

@@ -1101,23 +1101,24 @@ class CourseRestorer
                 if ($new_id) {
                     $sql = "UPDATE $table_forum SET forum_id = iid WHERE iid = $new_id";
                     Database::query($sql);
-                }
-
-                $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
+                    $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
 
-                $forum_topics = 0;
-                if (is_array($this->course->resources[RESOURCE_FORUMTOPIC])) {
-                    foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic) {
-                        if ($topic->obj->forum_id == $id) {
-                            $this->restore_topic($topic_id, $new_id, $sessionId);
-                            $forum_topics++;
+                    $forum_topics = 0;
+                    if (isset($this->course->resources[RESOURCE_FORUMTOPIC]) &&
+                        is_array($this->course->resources[RESOURCE_FORUMTOPIC])
+                    ) {
+                        foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic) {
+                            if ($topic->obj->forum_id == $id) {
+                                $this->restore_topic($topic_id, $new_id, $sessionId);
+                                $forum_topics++;
+                            }
                         }
                     }
-                }
-                if ($forum_topics > 0) {
-                    $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics."
-                            WHERE c_id = {$this->destination_course_id} AND forum_id = ".(int) $new_id;
-                    Database::query($sql);
+                    if ($forum_topics > 0) {
+                        $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics."
+                                WHERE c_id = {$this->destination_course_id} AND forum_id = ".(int) $new_id;
+                        Database::query($sql);
+                    }
                 }
             }
         }

+ 13 - 4
src/CourseBundle/Component/CourseCopy/CourseSelectForm.php

@@ -370,7 +370,10 @@ class CourseSelectForm
                     switch ($type) {
                         case RESOURCE_QUIZQUESTION:
                             foreach ($resources as $id => $resource) {
-                                echo '<input type="hidden" name="resource['.RESOURCE_QUIZQUESTION.']['.$id.']" id="resource['.RESOURCE_QUIZQUESTION.']['.$id.']" value="On" />';
+                                echo '<input 
+                                    type="hidden" 
+                                    name="resource['.RESOURCE_QUIZQUESTION.']['.$id.']" 
+                                    id="resource['.RESOURCE_QUIZQUESTION.']['.$id.']" value="On" />';
                             }
                             break;
                     }
@@ -390,7 +393,10 @@ class CourseSelectForm
                     switch ($type) {
                         case RESOURCE_SCORM:
                             foreach ($resources as $id => $resource) {
-                                echo '<input type="hidden" name="resource['.RESOURCE_SCORM.']['.$id.']" id="resource['.RESOURCE_SCORM.']['.$id.']" value="On" />';
+                                echo '<input 
+                                    type="hidden" 
+                                    name="resource['.RESOURCE_SCORM.']['.$id.']" 
+                                    id="resource['.RESOURCE_SCORM.']['.$id.']" value="On" />';
                             }
                             break;
                     }
@@ -702,7 +708,8 @@ class CourseSelectForm
             }
         }
         if ($avoid_serialize) {
-            //Documents are avoided due the huge amount of memory that the serialize php function "eats" (when there are directories with hundred/thousand of files)
+            // Documents are avoided due the huge amount of memory that the serialize php
+            // function "eats" (when there are directories with hundred/thousand of files)
             // this is a known issue of serialize
             $course->resources['document'] = null;
         }
@@ -713,7 +720,9 @@ class CourseSelectForm
                 echo '<input type="hidden" name="'.$key.'" value="'.$value.'"/>';
             }
         }
-        echo '<br /><button class="save" type="submit" onclick="checkLearnPath(\''.addslashes(get_lang('DocumentsWillBeAddedToo')).'\')">'.get_lang('Ok').'</button>';
+        echo '<br /><button class="save" type="submit" 
+            onclick="checkLearnPath(\''.addslashes(get_lang('DocumentsWillBeAddedToo')).'\')">'.
+            get_lang('Ok').'</button>';
         self::display_hidden_quiz_questions($course);
         self::display_hidden_scorm_directories($course);
         echo '</form>';

+ 5 - 0
src/CourseBundle/Entity/Repository/CStudentPublicationRepository.php

@@ -9,6 +9,11 @@ use Chamilo\UserBundle\Entity\User;
 use Doctrine\ORM\EntityRepository;
 use Doctrine\ORM\Query\Expr\Join;
 
+/**
+ * Class CStudentPublicationRepository.
+ *
+ * @package Chamilo\CourseBundle\Entity\Repository
+ */
 class CStudentPublicationRepository extends EntityRepository
 {
     /**

+ 2 - 1
src/SettingsBundle/DependencyInjection/Configuration.php

@@ -9,7 +9,8 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
 /**
  * This is the class that validates and merges configuration from your app/config files.
  *
- * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
+ * To learn more see.
+ * {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
  */
 class Configuration implements ConfigurationInterface
 {

+ 3 - 1
src/SettingsBundle/Manager/SettingsManager.php

@@ -760,7 +760,9 @@ class SettingsManager implements SettingsManagerInterface
             }
         }
         $settings->setParameters($parameters);
-        $persistedParameters = $this->repository->findBy(['category' => $this->convertServiceToNameSpace($settings->getSchemaAlias())]);
+        $persistedParameters = $this->repository->findBy(
+            ['category' => $this->convertServiceToNameSpace($settings->getSchemaAlias())]
+        );
         $persistedParametersMap = [];
 
         foreach ($persistedParameters as $parameter) {

+ 20 - 3
src/SkillBundle/Entity/SkillRelItem.php

@@ -27,7 +27,7 @@ class SkillRelItem
     /**
      * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Skill", inversedBy="items")
      * @ORM\JoinColumn(name="skill_id", referencedColumnName="id")
-     **/
+     */
     protected $skill;
 
     /**
@@ -92,7 +92,7 @@ class SkillRelItem
     protected $sessionId;
 
     /**
-     * @var \DateTime $created
+     * @var \DateTime
      *
      * @Gedmo\Timestampable(on="create")
      * @ORM\Column(name="created_at", type="datetime")
@@ -100,7 +100,7 @@ class SkillRelItem
     protected $createdAt;
 
     /**
-     * @var \DateTime $updated
+     * @var \DateTime
      *
      * @Gedmo\Timestampable(on="update")
      * @ORM\Column(name="updated_at", type="datetime")
@@ -222,11 +222,13 @@ class SkillRelItem
 
     /**
      * @param bool $requiresValidation
+     *
      * @return SkillRelItem
      */
     public function setRequiresValidation($requiresValidation)
     {
         $this->requiresValidation = $requiresValidation;
+
         return $this;
     }
 
@@ -240,11 +242,13 @@ class SkillRelItem
 
     /**
      * @param bool $isReal
+     *
      * @return SkillRelItem
      */
     public function setIsReal($isReal)
     {
         $this->isReal = $isReal;
+
         return $this;
     }
 
@@ -258,11 +262,13 @@ class SkillRelItem
 
     /**
      * @param \DateTime $createdAt
+     *
      * @return SkillRelItem
      */
     public function setCreatedAt($createdAt)
     {
         $this->createdAt = $createdAt;
+
         return $this;
     }
 
@@ -276,11 +282,13 @@ class SkillRelItem
 
     /**
      * @param \DateTime $updatedAt
+     *
      * @return SkillRelItem
      */
     public function setUpdatedAt($updatedAt)
     {
         $this->updatedAt = $updatedAt;
+
         return $this;
     }
 
@@ -294,11 +302,13 @@ class SkillRelItem
 
     /**
      * @param int $createdBy
+     *
      * @return SkillRelItem
      */
     public function setCreatedBy($createdBy)
     {
         $this->createdBy = $createdBy;
+
         return $this;
     }
 
@@ -312,11 +322,13 @@ class SkillRelItem
 
     /**
      * @param int $updatedBy
+     *
      * @return SkillRelItem
      */
     public function setUpdatedBy($updatedBy)
     {
         $this->updatedBy = $updatedBy;
+
         return $this;
     }
 
@@ -330,11 +342,13 @@ class SkillRelItem
 
     /**
      * @param int $itemType
+     *
      * @return SkillRelItem
      */
     public function setItemType($itemType)
     {
         $this->itemType = $itemType;
+
         return $this;
     }
 
@@ -348,11 +362,13 @@ class SkillRelItem
 
     /**
      * @param int $courseId
+     *
      * @return SkillRelItem
      */
     public function setCourseId($courseId)
     {
         $this->courseId = $courseId;
+
         return $this;
     }
 
@@ -366,6 +382,7 @@ class SkillRelItem
 
     /**
      * @param int $sessionId
+     *
      * @return SkillRelItem
      */
     public function setSessionId($sessionId)

+ 2 - 0
src/UserBundle/Entity/User.php

@@ -785,6 +785,8 @@ class User extends BaseUser implements ThemeUser //implements ParticipantInterfa
     }
 
     /**
+     * @todo don't use api_get_person_name
+     *
      * @return string
      */
     public function getCompleteName()

+ 1 - 1
tests/behat/behat.yml

@@ -9,7 +9,7 @@ default:
                 browser: chrome
             default_session: selenium2
             javascript_session: selenium2
-            files_path: "%paths.base%/../../public/"
+            files_path: "%paths.base%/../../"
     suites:
         default:
             paths: ["%paths.base%/features"]

+ 14 - 10
tests/behat/features/accessCompanyReports.feature

@@ -4,33 +4,37 @@ Feature: Access to portal reports as admin
   As an administrator
   I need to be able to access the portal reports
 
-  Background:
-    Given I am a platform administrator
-
   Scenario: See the company reports link on the admin page
-    Given I am on "/main/admin/index.php"
+    Given I am a platform administrator
+    And I am on "/main/admin/index.php"
     Then I should see "Reports"
 
   Scenario: Access the company report
-    Given I am on "/main/mySpace/company_reports.php"
+    Given I am a platform administrator
+    And I am on "/main/mySpace/company_reports.php"
     Then I should not see "not authorized"
 
   Scenario: Access the resumed version of the company report
-    Given I am on "/main/mySpace/company_reports_resumed.php"
+    Given I am a platform administrator
+    And I am on "/main/mySpace/company_reports_resumed.php"
     Then I should not see "not authorized"
 
   Scenario: See the company reports link on the admin page
-    Given I am on "/main/admin/teacher_time_report.php"
+    Given I am a platform administrator
+    And I am on "/main/admin/teacher_time_report.php"
     Then I should see "Teachers time report"
 
   Scenario: See the company reports link on the admin page
-    Given I am on "/main/admin/teacher_time_report.php"
+    Given I am a platform administrator
+    And I am on "/main/admin/teacher_time_report.php"
     Then I should not see "not authorized"
 
   Scenario: See the company reports link on the admin page
-    Given I am on "/main/admin/teachers_time_by_session_report.php"
+    Given I am a platform administrator
+    And I am on "/main/admin/teachers_time_by_session_report.php"
     Then I should see "Teachers time report by session"
 
   Scenario: See the company reports link on the admin page
-    Given I am on "/main/admin/teachers_time_by_session_report.php"
+    Given I am a platform administrator
+    And I am on "/main/admin/teachers_time_by_session_report.php"
     Then I should not see "not authorized"

+ 1 - 1
tests/behat/features/adminFillUsers.feature

@@ -26,7 +26,7 @@ Feature: User login
     Given I am an HR manager
     Then I should not see an ".alert-danger" element
 
-  Scenario: Login as student bott successfully
+  Scenario: Login as student boss successfully
     Given I am a student boss
     Then I should not see an ".alert-danger" element
 

+ 0 - 1
tests/behat/features/bootstrap/FeatureContext.php

@@ -111,7 +111,6 @@ class FeatureContext extends MinkContext
     }
 
     /**
-     *
      * @Given /^I am logged as "([^"]*)"$/
      */
     public function iAmLoggedAs($username)

+ 1 - 1
tests/behat/features/course.feature

@@ -9,7 +9,7 @@ Feature: Course tools basic testing
     Given I am a platform administrator
 
   Scenario: See the courses list
-    And I am on "/main/admin/course_list.php"
+    Given I am on "/main/admin/course_list.php"
     Then I should see "Course list"
     And I should not see "not authorized"
 

+ 1 - 2
tests/behat/features/toolExercise.feature

@@ -12,7 +12,6 @@ Feature: Exercise tool
     When I fill in the following:
       | category_name | Category 1 |
     And I fill in ckeditor field "category_description" with "Category 1 description"
-
     And I press "SubmitNote"
     Then I should see "Category added"
 
@@ -313,4 +312,4 @@ Feature: Exercise tool
   Scenario: Delete an exercise category
     Given I am on "/main/exercise/tests_category.php?cidReq=TEMP"
     And I follow "Delete"
-    Then I should see "Category deleted"
+    Then I should see "Category deleted"

+ 54 - 4
tests/behat/features/toolWork.feature

@@ -2,14 +2,64 @@ Feature: Work tool
   In order to use the work tool
   The teachers should be able to create works
 
-  Background:
+  Scenario: Create a work
     Given I am a platform administrator
     And I am on course "TEMP" homepage
-
-  Scenario: Create a work
-    Given I am on "/main/work/work.php?action=create_dir&cidReq=TEMP"
+    And I am on "/main/work/work.php?action=create_dir&cidReq=TEMP"
     When I fill in the following:
       | new_dir | Work 1 |
     And I fill in ckeditor field "description" with "Work description"
     And I press "submit"
     Then I should see "Directory created"
+
+  Scenario: Edit a work
+    Given I am a platform administrator
+    And I am on course "TEMP" homepage
+    And I am on "/main/work/work.php?cidReq=TEMP"
+    And wait for the page to be loaded
+    And I follow "Work 1"
+    Then I should see "Work description"
+    Then I follow "Edit"
+    Then I should see "Assignment name"
+    And wait for the page to be loaded
+    And I press "Validate"
+    Then I should see "Update successful"
+
+  Scenario: Send work as student
+    Given I am a student
+    And I am on "/main/work/work.php?cidReq=TEMP"
+    And wait for the page to be loaded
+    And I follow "Work 1"
+    Then I should see "Work 1"
+    Then I follow "Upload my assignment"
+    Then I should see "Upload a document"
+    Then I follow "Upload (Simple)"
+    Then I should see "File extension"
+    Then I attach the file "web/css/base.css" to "file"
+    And I press "Upload"
+    And wait for the page to be loaded
+    Then I should see "The file has been added to the list of publications"
+
+  Scenario: Check that work previously uploaded by student is available for the teacher.
+    Given I am a platform administrator
+    And I am on "/main/work/work.php?cidReq=TEMP"
+    And wait for the page to be loaded
+    And I follow "Work 1"
+    And wait for the page to be loaded
+    Then I should see "Work description"
+    Then I follow "Correct and rate"
+    Then I follow "Download"
+
+#  Scenario: Add a comment and a attachment to the work previously uploaded by student
+#    Given I am a platform administrator
+#    And I am on "/main/work/work.php?cidReq=TEMP"
+#    And wait for the page to be loaded
+#    And I follow "Work 1"
+#    Then I should see "Work description"
+#    And wait for the page to be loaded
+#    Then I follow "Correct and rate"
+#    Then I fill in ckeditor field "comment" with "This is a comment"
+#    Then I attach the file "web/css/base.css" to "attachment"
+#    And I press "Send message"
+#    Then I should see "You comment has been added"
+#    And I should see "Update successful"

+ 1 - 1
tests/scripts/fix_restored_learnpaths.php

@@ -1,7 +1,7 @@
 <?php
 /* For licensing terms, see /license.txt */
 
-//exit;
+exit;
 
 use Chamilo\CourseBundle\Entity\CLp;
 use Doctrine\ORM\Query\Expr\Join;