Browse Source

Minor - upgrade from 1.11.x

Julio Montoya 5 years ago
parent
commit
447a4c70f2
36 changed files with 765 additions and 769 deletions
  1. 1 1
      main/admin/access_url_edit_usergroup_to_url.php
  2. 9 19
      main/badge/assign.php
  3. 3 1
      main/exercise/Draggable.php
  4. 3 1
      main/exercise/MatchingDraggable.php
  5. 11 10
      main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php
  6. 0 34
      main/exercise/TestCategory.php
  7. 27 52
      main/exercise/UniqueAnswerImage.php
  8. 1 1
      main/exercise/admin.php
  9. 3 1
      main/exercise/calculated_answer.class.php
  10. 363 187
      main/exercise/exercise.class.php
  11. 3 4
      main/exercise/exercise_admin.php
  12. 4 6
      main/exercise/exercise_result.php
  13. 2 2
      main/exercise/exercise_show.php
  14. 20 10
      main/exercise/exercise_submit.php
  15. 80 101
      main/exercise/exercise_submit_modal.php
  16. 4 6
      main/exercise/global_multiple_answer.class.php
  17. 24 29
      main/exercise/hotspot_admin.inc.php
  18. 6 2
      main/exercise/matching.class.php
  19. 2 5
      main/exercise/multiple_answer.class.php
  20. 4 3
      main/exercise/multiple_answer_combination.class.php
  21. 7 6
      main/exercise/multiple_answer_true_false.class.php
  22. 2 2
      main/exercise/overview.php
  23. 6 6
      main/exercise/question.class.php
  24. 1 2
      main/exercise/question_list_admin.inc.php
  25. 4 1
      main/exercise/question_pool.php
  26. 74 57
      main/exercise/unique_answer.class.php
  27. 5 4
      main/exercise/unique_answer_no_option.class.php
  28. 7 10
      main/gradebook/gradebook_flatview.php
  29. 13 3
      main/gradebook/index.php
  30. 0 1
      main/gradebook/lib/be/category.class.php
  31. 47 41
      main/gradebook/lib/be/exerciselink.class.php
  32. 16 12
      main/gradebook/lib/be/studentpublicationlink.class.php
  33. 0 135
      main/gradebook/lib/fe/exportgradebook.php
  34. 11 10
      main/gradebook/lib/fe/gradebooktable.class.php
  35. 2 2
      main/gradebook/lib/flatview_data_generator.class.php
  36. 0 2
      main/inc/lib/template.lib.php

+ 1 - 1
main/admin/access_url_edit_usergroup_to_url.php

@@ -109,7 +109,7 @@ echo '</div>';
 api_display_tool_title($tool_name);
 
 $noUserGroupList = $userGroupList = [];
-$ajax_search = $add_type == 'unique' ? true : false;
+$ajax_search = $add_type === 'unique' ? true : false;
 
 if ($ajax_search) {
     $userGroups = UrlManager::get_url_rel_usergroup_data($access_url_id);

+ 9 - 19
main/badge/assign.php

@@ -2,7 +2,6 @@
 /* For licensing terms, see /license.txt */
 
 use Chamilo\CoreBundle\Entity\Skill;
-use Chamilo\CoreBundle\Entity\SkillRelUser;
 use Chamilo\UserBundle\Entity\User;
 use Skill as SkillManager;
 
@@ -289,22 +288,13 @@ if ($form->validate()) {
         exit;
     }
 
-    $skillUser = new SkillRelUser();
-    $skillUser->setUser($user);
-    $skillUser->setSkill($skill);
-
-    if ($showLevels) {
-        $level = $skillLevelRepo->find($values['acquired_level']);
-        $skillUser->setAcquiredLevel($level);
-    }
-
-    $skillUser->setArgumentation($values['argumentation']);
-    $skillUser->setArgumentationAuthorId(api_get_user_id());
-    $skillUser->setAcquiredSkillAt(new DateTime());
-    $skillUser->setAssignedBy(0);
-
-    $entityManager->persist($skillUser);
-    $entityManager->flush();
+    $skillUser = $skillManager->addSkillToUserBadge(
+        $user,
+        $skill,
+        $values['acquired_level'],
+        $values['argumentation'],
+        api_get_user_id()
+    );
 
     // Send email depending of children_auto_threshold
     $skillRelSkill = new SkillRelSkill();
@@ -334,9 +324,9 @@ if ($form->validate()) {
                     Display::addFlash(Display::return_message(get_lang('MessageSent')));
                     $url = api_get_path(WEB_CODE_PATH).'badge/assign.php?user='.$userId.'&id='.$parentId;
                     $link = Display::url($url, $url);
-                    $subject = get_lang("StudentHadEnoughSkills");
+                    $subject = get_lang('StudentHadEnoughSkills');
                     $message = sprintf(
-                        get_lang("StudentXHadEnoughSkillsToGetSkillXToAssignClickHereX"),
+                        get_lang('StudentXHadEnoughSkillsToGetSkillXToAssignClickHereX'),
                         UserManager::formatUserFullName($user),
                         $parentData['name'],
                         $link

+ 3 - 1
main/exercise/Draggable.php

@@ -217,7 +217,9 @@ class Draggable extends Question
 
         if ($exercise->showExpectedChoice()) {
             $header .= '<th>'.get_lang('YourChoice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
         } else {
             $header .= '<th>'.get_lang('ElementList').'</th>';
         }

+ 3 - 1
main/exercise/MatchingDraggable.php

@@ -274,7 +274,9 @@ class MatchingDraggable extends Question
         }
 
         if ($exercise->showExpectedChoice()) {
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
             $header .= '<th>'.get_lang('Status').'</th>';
         } else {
             $header .= '<th>'.get_lang('CorrespondsTo').'</th>';

+ 11 - 10
main/exercise/MultipleAnswerTrueFalseDegreeCertainty.php

@@ -77,7 +77,7 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question
             .'</th>';
 
         // show column comment when feedback is enable
-        if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+        if ($objEx->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
             $html .= '<th>'.get_lang('Comment').'</th>';
         }
         $html .= '</tr>';
@@ -173,7 +173,7 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question
             $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required');
 
             // show comment when feedback is enable
-            if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+            if ($objEx->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
                 $form->addElement(
                     'html_editor',
                     'comment['.$i.']',
@@ -306,19 +306,20 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question
     public function return_header(Exercise $exercise, $counter = null, $score = [])
     {
         $header = parent::return_header($exercise, $counter, $score);
-        $header .= '<table class="'
-            .$this->question_table_class
-            .'"><tr><th>'
-            .get_lang('Choice')
-            .'</th><th>'
-            .get_lang('ExpectedChoice')
-            .'</th><th>'
+        $header .= '<table class="'.$this->question_table_class.'"><tr>';
+        $header .= '<th>'.get_lang('Choice').'</th>';
+
+        if ($exercise->showExpectedChoiceColumn()) {
+            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+        }
+
+        $header .='<th>'
             .get_lang('Answer')
             .'</th><th colspan="2" style="text-align:center;">'
             .get_lang('YourDegreeOfCertainty')
             .'</th>'
         ;
-        if ($exercise->feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
+        if ($exercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
             $header .= '<th>'.get_lang('Comment').'</th>';
         } else {
             $header .= '<th>&nbsp;</th>';

+ 0 - 34
main/exercise/TestCategory.php

@@ -714,40 +714,6 @@ class TestCategory
         return $tabResult;
     }
 
-    /**
-     * return total score for test exe_id for all question in the category $in_cat_id for user
-     * If no question for this category, return "".
-     */
-    public static function getCatScoreForExeidForUserid($in_cat_id, $in_exe_id, $in_user_id)
-    {
-        $tbl_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
-        $tbl_question_rel_category = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
-        $in_cat_id = (int) $in_cat_id;
-        $in_exe_id = (int) $in_exe_id;
-        $in_user_id = (int) $in_user_id;
-
-        $query = "SELECT DISTINCT
-                        marks, 
-                        exe_id, 
-                        user_id, 
-                        ta.question_id, 
-                        category_id
-                  FROM $tbl_track_attempt ta 
-                  INNER JOIN $tbl_question_rel_category qrc
-                  ON (ta.question_id = qrc.question_id)
-                  WHERE
-                    qrc.category_id = $in_cat_id AND
-                    exe_id = $in_exe_id AND 
-                    user_id = $in_user_id";
-        $res = Database::query($query);
-        $score = '';
-        while ($data = Database::fetch_array($res)) {
-            $score += $data['marks'];
-        }
-
-        return $score;
-    }
-
     /**
      * Return the number max of question in a category
      * count the number of questions in all categories, and return the max.

+ 27 - 52
main/exercise/UniqueAnswerImage.php

@@ -43,13 +43,18 @@ class UniqueAnswerImage extends UniqueAnswer
         $numberAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0));
 
         $feedbackTitle = '';
-
-        if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
-            //Scenario
-            $commentTitle = '<th>'.get_lang('Comment').'</th>';
-            $feedbackTitle = '<th>'.get_lang('Scenario').'</th>';
-        } else {
-            $commentTitle = '<th >'.get_lang('Comment').'</th>';
+        switch ($objExercise->getFeedbackType()) {
+            case EXERCISE_FEEDBACK_TYPE_DIRECT:
+                // Scenario
+                $commentTitle = '<th width="20%">'.get_lang('Comment').'</th>';
+                $feedbackTitle = '<th width="20%">'.get_lang('Scenario').'</th>';
+                break;
+            case EXERCISE_FEEDBACK_TYPE_POPUP:
+                $commentTitle = '<th width="20%">'.get_lang('Comment').'</th>';
+                break;
+            default:
+                $commentTitle = '<th width="40%">'.get_lang('Comment').'</th>';
+                break;
         }
 
         $html = '<div class="alert alert-success" role="alert">'.
@@ -196,49 +201,17 @@ class UniqueAnswerImage extends UniqueAnswer
 
             $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required');
 
-            if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
-                $form->addHtmlEditor(
-                    'comment['.$i.']',
-                    null,
-                    null,
-                    false,
-                    $editorConfig
-                );
-                // Direct feedback
-                // Adding extra feedback fields
-                $group = [];
-                $group['try'.$i] = $form->createElement('checkbox', 'try'.$i, null, get_lang('TryAgain'));
-                $group['lp'.$i] = $form->createElement(
-                    'select',
-                    'lp'.$i,
-                    get_lang('SeeTheory').': ',
-                    $selectLpId
-                );
-                $group['destination'.$i] = $form->createElement(
-                    'select',
-                    'destination'.$i,
-                    get_lang('GoToQuestion').': ',
-                    $selectQuestion
-                );
-                $group['url'.$i] = $form->createElement(
-                    'text',
-                    'url'.$i,
-                    get_lang('Other').': ',
-                    [
-                        'class' => 'col-md-2',
-                        'placeholder' => get_lang('Other'),
-                    ]
-                );
-                $form->addGroup($group, 'scenario');
-
-                $renderer->setElementTemplate(
-                    '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}',
-                    'scenario'
-                );
-            } else {
-                $form->addHtmlEditor('comment['.$i.']', null, null, false, $editorConfig);
+            switch ($objExercise->getFeedbackType()) {
+                case EXERCISE_FEEDBACK_TYPE_DIRECT:
+                    $this->setDirectOptions($i, $form, $renderer, $selectLpId, $selectQuestion);
+                    break;
+                case EXERCISE_FEEDBACK_TYPE_POPUP:
+                default:
+                    $form->addHtmlEditor('comment['.$i.']', null, null, false, $editorConfig);
+                    break;
             }
-            $form->addText('weighting['.$i.']', null, null, ['class' => "col-md-1", 'value' => '0']);
+
+            $form->addText('weighting['.$i.']', null, null, ['class' => 'col-md-1', 'value' => '0']);
             $form->addHtml('</tr>');
         }
 
@@ -378,9 +351,11 @@ class UniqueAnswerImage extends UniqueAnswer
         if ($exercise->showExpectedChoice()) {
             $header = '<table class="'.$this->question_table_class.'">
 			<tr>
-				<th>'.get_lang('Choice').'</th>
-				<th>'.get_lang('ExpectedChoice').'</th>
-				<th>'.get_lang('Answer').'</th>';
+				<th>'.get_lang('Choice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
+            $header .= '<th>'.get_lang('Answer').'</th>';
             $header .= '<th>'.get_lang('Status').'</th>';
             $header .= '<th>'.get_lang('Comment').'</th>';
             $header .= '</tr>';

+ 1 - 1
main/exercise/admin.php

@@ -453,7 +453,7 @@ if (!$newQuestion && !$modifyQuestion && !$editQuestion && !isset($_GET['hotspot
 
 // if we are in question authoring, display warning to user is feedback not shown at the end of the test -ref #6619
 // this test to display only message in the question authoring page and not in the question list page too
-if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_EXAM) {
+if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_EXAM) {
     echo Display::return_message(get_lang('TestFeedbackNotShown'), 'normal');
 }
 

+ 3 - 1
main/exercise/calculated_answer.class.php

@@ -252,7 +252,9 @@ class CalculatedAnswer extends Question
         $header .= '<th>'.get_lang('Answer').'</th>';
         if ($exercise->showExpectedChoice()) {
             $header .= '<th>'.get_lang('YourChoice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
             $header .= '<th>'.get_lang('Status').'</th>';
         }
         $header .= '</tr>';

+ 363 - 187
main/exercise/exercise.class.php

@@ -1,8 +1,10 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CoreBundle\Entity\GradebookLink;
 use Chamilo\CoreBundle\Entity\TrackEHotspot;
 use ChamiloSession as Session;
+use Doctrine\DBAL\Types\Type;
 
 /**
  * Class Exercise.
@@ -84,6 +86,7 @@ class Exercise
     public $export = false;
     public $autolaunch;
     public $exerciseCategoryId;
+    public $pageResultConfiguration;
 
     /**
      * Constructor of the class.
@@ -123,6 +126,7 @@ class Exercise
         $this->globalCategoryId = null;
         $this->notifications = [];
         $this->exerciseCategoryId = 0;
+        $this->pageResultConfiguration;
 
         if (!empty($courseId)) {
             $courseInfo = api_get_course_info_by_id($courseId);
@@ -201,6 +205,10 @@ class Exercise
                 $this->notifications = explode(',', $object->notifications);
             }
 
+            if (!empty($object->page_result_configuration)) {
+                $this->pageResultConfiguration = $object->page_result_configuration;
+            }
+
             if (isset($object->show_previous_button)) {
                 $this->showPreviousButton = $object->show_previous_button == 1 ? true : false;
             }
@@ -219,7 +227,6 @@ class Exercise
             }
 
             $this->force_edit_exercise_in_lp = api_get_setting('lp.show_invisible_exercise_in_lp_toc') === 'true';
-
             $this->edit_exercise_in_lp = true;
             if ($this->exercise_was_added_in_lp) {
                 $this->edit_exercise_in_lp = $this->force_edit_exercise_in_lp == true;
@@ -309,14 +316,15 @@ class Exercise
         return $this->attempts;
     }
 
-    /** returns the number of FeedbackType  *
-     *  0=>Feedback , 1=>DirectFeedback, 2=>NoFeedback.
+    /**
+     * Returns the number of FeedbackType
+     *  0: Feedback , 1: DirectFeedback, 2: NoFeedback.
      *
      * @return int - exercise attempts
      */
-    public function selectFeedbackType()
+    public function getFeedbackType()
     {
-        return $this->feedback_type;
+        return (int) $this->feedback_type;
     }
 
     /**
@@ -416,7 +424,7 @@ class Exercise
      *
      * @return string html text : the text to display ay the end of the test
      */
-    public function selectTextWhenFinished()
+    public function getTextWhenFinished()
     {
         return $this->text_when_finished;
     }
@@ -644,10 +652,10 @@ class Exercise
                     ON (e.question_id = q.id AND e.c_id = ".$this->course_id." )
 					WHERE e.exercice_id	= '".$this->id."' ";
 
-            $orderCondition = "ORDER BY question_order";
+            $orderCondition = ' ORDER BY question_order ';
 
             if (!empty($sidx) && !empty($sord)) {
-                if ($sidx == 'question') {
+                if ($sidx === 'question') {
                     if (in_array(strtolower($sord), ['desc', 'asc'])) {
                         $orderCondition = " ORDER BY q.$sidx $sord";
                     }
@@ -657,8 +665,8 @@ class Exercise
             $sql .= $orderCondition;
             $limitCondition = null;
             if (isset($start) && isset($limit)) {
-                $start = intval($start);
-                $limit = intval($limit);
+                $start = (int) $start;
+                $limit = (int) $limit;
                 $limitCondition = " LIMIT $start, $limit";
             }
             $sql .= $limitCondition;
@@ -677,7 +685,7 @@ class Exercise
                     );
 
                     if (empty($category_labels)) {
-                        $category_labels = "-";
+                        $category_labels = '-';
                     }
 
                     // Question type
@@ -1088,7 +1096,7 @@ class Exercise
     /**
      * @return int
      */
-    public function selectSaveCorrectAnswers()
+    public function getSaveCorrectAnswers()
     {
         return $this->saveCorrectAnswers;
     }
@@ -1257,7 +1265,7 @@ class Exercise
      */
     public function updateSaveCorrectAnswers($value)
     {
-        $this->saveCorrectAnswers = $value;
+        $this->saveCorrectAnswers = (int) $value;
     }
 
     /**
@@ -1502,7 +1510,7 @@ class Exercise
         $random_answers = $this->random_answers;
         $active = $this->active;
         $propagate_neg = (int) $this->propagate_neg;
-        $saveCorrectAnswers = isset($this->saveCorrectAnswers) && $this->saveCorrectAnswers ? 1 : 0;
+        $saveCorrectAnswers = isset($this->saveCorrectAnswers) ? (int) $this->saveCorrectAnswers : 0;
         $review_answers = isset($this->review_answers) && $this->review_answers ? 1 : 0;
         $randomByCat = (int) $this->randomByCat;
         $text_when_finished = $this->text_when_finished;
@@ -1512,7 +1520,7 @@ class Exercise
 
         // If direct we do not show results
         $results_disabled = (int) $this->results_disabled;
-        if ($feedback_type == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+        if (in_array($feedback_type, [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
             $results_disabled = 0;
         }
         $expired_time = (int) $this->expired_time;
@@ -1576,6 +1584,10 @@ class Exercise
                     $notifications = implode(',', $notifications);
                     $paramsExtra['notifications'] = $notifications;
                 }
+
+                if (!empty($this->pageResultConfiguration)) {
+                    $paramsExtra['page_result_configuration'] = $this->pageResultConfiguration;
+                }
             }
 
             $params = array_merge($params, $paramsExtra);
@@ -1636,7 +1648,7 @@ class Exercise
                 'text_when_finished' => $text_when_finished,
                 'display_category_name' => $display_category_name,
                 'pass_percentage' => $pass_percentage,
-                'save_correct_answers' => (int) $saveCorrectAnswers,
+                'save_correct_answers' => $saveCorrectAnswers,
                 'propagate_neg' => $propagate_neg,
                 'hide_question_title' => $this->getHideQuestionTitle(),
             ];
@@ -1661,6 +1673,10 @@ class Exercise
                 }
             }
 
+            if (!empty($this->pageResultConfiguration)) {
+                $params['page_result_configuration'] = $this->pageResultConfiguration;
+            }
+
             $this->id = $this->iId = Database::insert($TBL_EXERCISES, $params);
 
             if ($this->id) {
@@ -1875,14 +1891,13 @@ class Exercise
             $type = 'full';
         }
 
-        // form title
+        // Form title
+        $form_title = get_lang('NewEx');
         if (!empty($_GET['exerciseId'])) {
             $form_title = get_lang('ModifyExercise');
-        } else {
-            $form_title = get_lang('NewEx');
         }
 
-        $form->addElement('header', $form_title);
+        $form->addHeader($form_title);
 
         // Title.
         if (api_get_configuration_value('save_titles_as_html')) {
@@ -1929,6 +1944,7 @@ class Exercise
             'Width' => '100%',
             'Height' => '150',
         ];
+
         if (is_array($type)) {
             $editor_config = array_merge($editor_config, $type);
         }
@@ -1943,56 +1959,9 @@ class Exercise
 
         $skillList = [];
         if ($type === 'full') {
-            //Can't modify a DirectFeedback question
-            if ($this->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_DIRECT) {
-                // feedback type
-                $radios_feedback = [];
-                $radios_feedback[] = $form->createElement(
-                    'radio',
-                    'exerciseFeedbackType',
-                    null,
-                    get_lang('ExerciseAtTheEndOfTheTest'),
-                    '0',
-                    [
-                        'id' => 'exerciseType_0',
-                        'onclick' => 'check_feedback()',
-                    ]
-                );
-
-                if (api_get_setting('enable_quiz_scenario') === 'true') {
-                    // Can't convert a question from one feedback to another
-                    // if there is more than 1 question already added
-                    if ($this->selectNbrQuestions() == 0) {
-                        $radios_feedback[] = $form->createElement(
-                            'radio',
-                            'exerciseFeedbackType',
-                            null,
-                            get_lang('DirectFeedback'),
-                            '1',
-                            [
-                                'id' => 'exerciseType_1',
-                                'onclick' => 'check_direct_feedback()',
-                            ]
-                        );
-                    }
-                }
-
-                $radios_feedback[] = $form->createElement(
-                    'radio',
-                    'exerciseFeedbackType',
-                    null,
-                    get_lang('NoFeedback'),
-                    '2',
-                    ['id' => 'exerciseType_2']
-                );
-                $form->addGroup(
-                    $radios_feedback,
-                    null,
-                    [
-                        get_lang('FeedbackType'),
-                        get_lang('FeedbackDisplayOptions'),
-                    ]
-                );
+            // Can't modify a DirectFeedback question.
+            if (!in_array($this->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
+                $this->setResultFeedbackGroup($form);
 
                 // Type of results display on the final page
                 $this->setResultDisabledGroup($form);
@@ -2026,41 +1995,7 @@ class Exercise
             } else {
                 // if is Direct feedback but has not questions we can allow to modify the question type
                 if ($this->getQuestionCount() === 0) {
-                    // feedback type
-                    $radios_feedback = [];
-                    $radios_feedback[] = $form->createElement(
-                        'radio',
-                        'exerciseFeedbackType',
-                        null,
-                        get_lang('ExerciseAtTheEndOfTheTest'),
-                        '0',
-                        ['id' => 'exerciseType_0', 'onclick' => 'check_feedback()']
-                    );
-
-                    if (api_get_setting('enable_quiz_scenario') == 'true') {
-                        $radios_feedback[] = $form->createElement(
-                            'radio',
-                            'exerciseFeedbackType',
-                            null,
-                            get_lang('DirectFeedback'),
-                            '1',
-                            ['id' => 'exerciseType_1', 'onclick' => 'check_direct_feedback()']
-                        );
-                    }
-                    $radios_feedback[] = $form->createElement(
-                        'radio',
-                        'exerciseFeedbackType',
-                        null,
-                        get_lang('NoFeedback'),
-                        '2',
-                        ['id' => 'exerciseType_2']
-                    );
-                    $form->addGroup(
-                        $radios_feedback,
-                        null,
-                        [get_lang('FeedbackType'), get_lang('FeedbackDisplayOptions')]
-                    );
-
+                    $this->setResultFeedbackGroup($form);
                     $this->setResultDisabledGroup($form);
 
                     // Type of questions disposition on page
@@ -2079,7 +2014,7 @@ class Exercise
                     $group->freeze();
 
                     // we force the options to the DirectFeedback exercisetype
-                    $form->addElement('hidden', 'exerciseFeedbackType', EXERCISE_FEEDBACK_TYPE_DIRECT);
+                    $form->addElement('hidden', 'exerciseFeedbackType', $this->getFeedbackType());
                     $form->addElement('hidden', 'exerciseType', ONE_PER_PAGE);
 
                     // Type of questions disposition on page
@@ -2154,6 +2089,30 @@ class Exercise
                 ]
             );
 
+
+            $group = [
+                $form->createElement(
+                    'checkbox',
+                    'hide_expected_answer',
+                    null,
+                    get_lang('HideExpectedAnswer')
+                ),
+                $form->createElement(
+                    'checkbox',
+                    'hide_total_score',
+                    null,
+                    get_lang('HideTotalScore')
+                ),
+                $form->createElement(
+                    'checkbox',
+                    'hide_question_score',
+                    null,
+                    get_lang('HideQuestionScore')
+                )
+            ];
+            $form->addGroup($group, null, get_lang('ResultsConfigurationPage'));
+        
+
             $displayMatrix = 'none';
             $displayRandom = 'none';
             $selectionType = $this->getQuestionSelectionType();
@@ -2201,13 +2160,6 @@ class Exercise
             $form->addElement('label', null, $cat_form);
             $form->addElement('html', '</div>');
 
-            // Category name.
-            $radio_display_cat_name = [
-                $form->createElement('radio', 'display_category_name', null, get_lang('Yes'), '1'),
-                $form->createElement('radio', 'display_category_name', null, get_lang('No'), '0'),
-            ];
-            $form->addGroup($radio_display_cat_name, null, get_lang('QuestionDisplayCategoryName'));
-
             // Random answers.
             $radios_random_answers = [
                 $form->createElement('radio', 'randomAnswers', null, get_lang('Yes'), '1'),
@@ -2215,6 +2167,13 @@ class Exercise
             ];
             $form->addGroup($radios_random_answers, null, get_lang('RandomAnswers'));
 
+            // Category name.
+            $radio_display_cat_name = [
+                $form->createElement('radio', 'display_category_name', null, get_lang('Yes'), '1'),
+                $form->createElement('radio', 'display_category_name', null, get_lang('No'), '0'),
+            ];
+            $form->addGroup($radio_display_cat_name, null, get_lang('QuestionDisplayCategoryName'));
+
             // Hide question title.
             $group = [
                 $form->createElement('radio', 'hide_question_title', null, get_lang('Yes'), '1'),
@@ -2298,11 +2257,19 @@ class Exercise
                 null,
                 get_lang('PropagateNegativeResults')
             );
-            $form->addCheckBox(
+
+
+            $options = [
+                '' => get_lang('SelectAnOption'),
+                1 => get_lang('SaveTheCorrectAnswersForTheNextAttempt'),
+                2 => get_lang('SaveAllAnswers'),
+            ];
+            $form->addSelect(
                 'save_correct_answers',
-                null,
-                get_lang('SaveTheCorrectAnswersForTheNextAttempt')
-            );
+                get_lang('SaveAnswers'),
+                $options
+            );       
+
             $form->addElement('html', '<div class="clear">&nbsp;</div>');
             $form->addElement('checkbox', 'review_answers', null, get_lang('ReviewAnswers'));
             $form->addElement('html', '<div id="divtimecontrol"  style="display:'.$display.';">');
@@ -2439,24 +2406,19 @@ class Exercise
             $form->addRule('end_time', get_lang('InvalidDate'), 'datetime');
 
             if ($this->id > 0) {
-                //if ($this->random > $this->selectNbrQuestions()) {
-                //    $defaults['randomQuestions'] = $this->selectNbrQuestions();
-                //} else {
                 $defaults['randomQuestions'] = $this->random;
-                //}
-
                 $defaults['randomAnswers'] = $this->getRandomAnswers();
                 $defaults['exerciseType'] = $this->selectType();
                 $defaults['exerciseTitle'] = $this->get_formated_title();
                 $defaults['exerciseDescription'] = $this->selectDescription();
                 $defaults['exerciseAttempts'] = $this->selectAttempts();
-                $defaults['exerciseFeedbackType'] = $this->selectFeedbackType();
+                $defaults['exerciseFeedbackType'] = $this->getFeedbackType();
                 $defaults['results_disabled'] = $this->selectResultsDisabled();
                 $defaults['propagate_neg'] = $this->selectPropagateNeg();
-                $defaults['save_correct_answers'] = $this->selectSaveCorrectAnswers();
+                $defaults['save_correct_answers'] = $this->getSaveCorrectAnswers();
                 $defaults['review_answers'] = $this->review_answers;
                 $defaults['randomByCat'] = $this->getRandomByCategory();
-                $defaults['text_when_finished'] = $this->selectTextWhenFinished();
+                $defaults['text_when_finished'] = $this->getTextWhenFinished();
                 $defaults['display_category_name'] = $this->selectDisplayCategoryName();
                 $defaults['pass_percentage'] = $this->selectPassPercentage();
                 $defaults['question_selection_type'] = $this->getQuestionSelectionType();
@@ -2512,6 +2474,8 @@ class Exercise
         if (api_get_setting('search_enabled') === 'true') {
             $defaults['index_document'] = 'checked="checked"';
         }
+
+        $this->setPageResultConfigurationDefaults($defaults);
         $form->setDefaults($defaults);
 
         // Freeze some elements.
@@ -2533,6 +2497,71 @@ class Exercise
         }
     }
 
+    /**
+     * @param $form
+     */
+    public function setResultFeedbackGroup(FormValidator $form)
+    {
+        // Feedback type.
+        $feedback = [];
+        $feedback[] = $form->createElement(
+            'radio',
+            'exerciseFeedbackType',
+            null,
+            get_lang('ExerciseAtTheEndOfTheTest'),
+            EXERCISE_FEEDBACK_TYPE_END,
+            [
+                'id' => 'exerciseType_'.EXERCISE_FEEDBACK_TYPE_END,
+                'onclick' => 'check_feedback()',
+            ]
+        );
+
+        if (api_get_setting('enable_quiz_scenario') === 'true') {
+            // Can't convert a question from one feedback to another
+            // if there is more than 1 question already added
+            if ($this->selectNbrQuestions() == 0) {
+                $feedback[] = $form->createElement(
+                    'radio',
+                    'exerciseFeedbackType',
+                    null,
+                    get_lang('DirectFeedback'),
+                    EXERCISE_FEEDBACK_TYPE_DIRECT,
+                    [
+                        'id' => 'exerciseType_'.EXERCISE_FEEDBACK_TYPE_DIRECT,
+                        'onclick' => 'check_direct_feedback()',
+                    ]
+                );
+            }
+        }
+
+        $feedback[] = $form->createElement(
+            'radio',
+            'exerciseFeedbackType',
+            null,
+            get_lang('ExerciseDirectPopUp'),
+            EXERCISE_FEEDBACK_TYPE_POPUP,
+            ['id' => 'exerciseType_'.EXERCISE_FEEDBACK_TYPE_POPUP, 'onclick' => 'check_direct_feedback()']
+        );
+
+        $feedback[] = $form->createElement(
+            'radio',
+            'exerciseFeedbackType',
+            null,
+            get_lang('NoFeedback'),
+            EXERCISE_FEEDBACK_TYPE_EXAM,
+            ['id' => 'exerciseType_'.EXERCISE_FEEDBACK_TYPE_EXAM]
+        );
+
+        $form->addGroup(
+            $feedback,
+            null,
+            [
+                get_lang('FeedbackType'),
+                get_lang('FeedbackDisplayOptions'),
+            ]
+        );
+    }
+
     /**
      * function which process the creation of exercises.
      *
@@ -2576,6 +2605,7 @@ class Exercise
         $this->setShowPreviousButton($form->getSubmitValue('show_previous_button'));
         $this->setNotifications($form->getSubmitValue('notifications'));
         $this->setExerciseCategoryId($form->getSubmitValue('exercise_category_id'));
+        $this->setPageResultConfiguration($form->getSubmitValues());
 
         $this->start_time = null;
         if ($form->getSubmitValue('activate_start_date_check') == 1) {
@@ -3082,7 +3112,9 @@ class Exercise
         $html = $label = '';
         $hotspot_get = isset($_POST['hotspot']) ? Security::remove_XSS($_POST['hotspot']) : null;
 
-        if ($this->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT && $this->type == ONE_PER_PAGE) {
+        if (in_array($this->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP]) &&
+            $this->type == ONE_PER_PAGE
+        ) {
             $urlTitle = get_lang('ContinueTest');
             if ($questionNum == count($this->questionList)) {
                 $urlTitle = get_lang('EndTest');
@@ -3090,7 +3122,7 @@ class Exercise
 
             $html .= Display::url(
                 $urlTitle,
-                'exercise_submit_modal.php?'.http_build_query([
+                api_get_path(WEB_CODE_PATH).'exercise/exercise_submit_modal.php?'.http_build_query([
                     'learnpath_id' => $safe_lp_id,
                     'learnpath_item_id' => $safe_lp_item_id,
                     'learnpath_item_view_id' => $safe_lp_item_view_id,
@@ -3104,7 +3136,7 @@ class Exercise
                 ]),
                 [
                     'class' => 'ajax btn btn-default',
-                    'data-title' => $urlTitle,
+                    'data-title' => Security::remove_XSS(get_lang('Comment')),
                     'data-size' => 'md',
                 ]
             );
@@ -3158,7 +3190,6 @@ class Exercise
                                         $num++;
                                     }
                                     $prev_question = $num;
-                                    //$question_id = $beforeId;
                                 }
                             }
 
@@ -3338,7 +3369,7 @@ class Exercise
         global $learnpath_id, $learnpath_item_id;
         require_once api_get_path(LIBRARY_PATH).'geometry.lib.php';
         $em = Database::getManager();
-        $feedback_type = $this->selectFeedbackType();
+        $feedback_type = $this->getFeedbackType();
         $results_disabled = $this->selectResultsDisabled();
 
         if ($debug) {
@@ -4354,10 +4385,12 @@ class Exercise
                                     case MATCHING:
                                     case MATCHING_DRAGGABLE:
                                         echo '<tr>';
-                                        if (!in_array($this->results_disabled, [
-                                            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-                                            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-                                            ])
+                                        if (!in_array(
+                                            $this->results_disabled,
+                                            [
+                                                RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
+                                            ]
+                                        )
                                         ) {
                                             echo '<td>'.$s_answer_label.'</td>';
                                             echo '<td>'.$user_answer.'</td>';
@@ -4367,31 +4400,35 @@ class Exercise
                                         }
 
                                         if ($this->showExpectedChoice()) {
-                                            echo '<td>';
-                                            if (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) {
-                                                if (isset($real_list[$i_answer_correct_answer]) &&
-                                                    $showTotalScoreAndUserChoicesInLastAttempt == true
-                                                ) {
-                                                    echo Display::span(
-                                                        $real_list[$i_answer_correct_answer]
-                                                    );
+                                            if ($this->showExpectedChoiceColumn()) {
+                                                echo '<td>';
+                                                if (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) {
+                                                    if (isset($real_list[$i_answer_correct_answer]) &&
+                                                        $showTotalScoreAndUserChoicesInLastAttempt == true
+                                                    ) {
+                                                        echo Display::span(
+                                                            $real_list[$i_answer_correct_answer]
+                                                        );
+                                                    }
                                                 }
+                                                echo '</td>';
                                             }
-                                            echo '</td>';
                                             echo '<td>'.$status.'</td>';
                                         } else {
-                                            echo '<td>';
                                             if (in_array($answerType, [MATCHING, MATCHING_DRAGGABLE])) {
                                                 if (isset($real_list[$i_answer_correct_answer]) &&
                                                     $showTotalScoreAndUserChoicesInLastAttempt === true
                                                 ) {
-                                                    echo Display::span(
-                                                        $real_list[$i_answer_correct_answer],
-                                                        ['style' => 'color: #008000; font-weight: bold;']
-                                                    );
+                                                    if ($this->showExpectedChoiceColumn()) {
+                                                        echo '<td>';
+                                                        echo Display::span(
+                                                            $real_list[$i_answer_correct_answer],
+                                                            ['style' => 'color: #008000; font-weight: bold;']
+                                                        );
+                                                        echo '</td>';
+                                                    }
                                                 }
                                             }
-                                            echo '</td>';
                                         }
                                         echo '</tr>';
                                         break;
@@ -4699,6 +4736,7 @@ class Exercise
                             );
                         } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
                             ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
+                                $this,
                                 $feedback_type,
                                 $studentChoice,
                                 $studentChoiceDegree,
@@ -4725,6 +4763,7 @@ class Exercise
                             );
                         } elseif ($answerType == FILL_IN_BLANKS) {
                             ExerciseShowFunctions::display_fill_in_blanks_answer(
+                                $this,
                                 $feedback_type,
                                 $answer,
                                 0,
@@ -4806,8 +4845,12 @@ class Exercise
                             $coords = explode('/', $user_answer);
                             $user_array = '';
                             foreach ($coords as $coord) {
-                                list($x, $y) = explode(';', $coord);
-                                $user_array .= round($x).';'.round($y).'/';
+                                if (!empty($coord)) {
+                                    $parts = explode(';', $coord);
+                                    if (!empty($parts)) {
+                                        $user_array .= round($parts[0]).';'.round($parts[1]).'/';
+                                    }
+                                }
                             }
                             $user_array = substr($user_array, 0, -1);
 
@@ -5091,6 +5134,7 @@ class Exercise
                         case MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY:
                             if ($answerId == 1) {
                                 ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
+                                    $this,
                                     $feedback_type,
                                     $studentChoice,
                                     $studentChoiceDegree,
@@ -5102,6 +5146,7 @@ class Exercise
                                 );
                             } else {
                                 ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
+                                    $this,
                                     $feedback_type,
                                     $studentChoice,
                                     $studentChoiceDegree,
@@ -5115,6 +5160,7 @@ class Exercise
                             break;
                         case FILL_IN_BLANKS:
                             ExerciseShowFunctions::display_fill_in_blanks_answer(
+                                $this,
                                 $feedback_type,
                                 $answer,
                                 $exeId,
@@ -7190,7 +7236,10 @@ class Exercise
                 if ($currentQuestion != $i) {
                     continue;
                 } else {
-                    if ($this->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                    if (!in_array(
+                        $this->getFeedbackType(),
+                        [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP]
+                    )) {
                         // if the user has already answered this question
                         if (isset($exerciseResult[$questionId])) {
                             echo Display::return_message(
@@ -7799,12 +7848,13 @@ class Exercise
     /**
      * Get the correct answers in all attempts.
      *
-     * @param int $learnPathId
-     * @param int $learnPathItemId
+     * @param int  $learnPathId
+     * @param int  $learnPathItemId
+     * @param bool $onlyCorrect
      *
      * @return array
      */
-    public function getCorrectAnswersInAllAttempts($learnPathId = 0, $learnPathItemId = 0)
+    public function getAnswersInAllAttempts($learnPathId = 0, $learnPathItemId = 0, $onlyCorrect = true)
     {
         $attempts = Event::getExerciseResultsByUser(
             api_get_user_id(),
@@ -7813,43 +7863,63 @@ class Exercise
             api_get_session_id(),
             $learnPathId,
             $learnPathItemId,
-            'asc'
+            'DESC'
         );
 
-        $corrects = [];
+        $list = [];
         foreach ($attempts as $attempt) {
             foreach ($attempt['question_list'] as $answers) {
                 foreach ($answers as $answer) {
                     $objAnswer = new Answer($answer['question_id']);
-
-                    switch ($objAnswer->getQuestionType()) {
-                        case FILL_IN_BLANKS:
-                            $isCorrect = FillBlanks::isCorrect($answer['answer']);
-                            break;
-                        case MATCHING:
-                        case DRAGGABLE:
-                        case MATCHING_DRAGGABLE:
-                            $isCorrect = Matching::isCorrect(
-                                $answer['position'],
-                                $answer['answer'],
-                                $answer['question_id']
-                            );
-                            break;
-                        case ORAL_EXPRESSION:
-                            $isCorrect = false;
-                            break;
-                        default:
-                            $isCorrect = $objAnswer->isCorrectByAutoId($answer['answer']);
-                    }
-
-                    if ($isCorrect) {
-                        $corrects[$answer['question_id']][] = $answer;
+                    if ($onlyCorrect) {
+                        switch ($objAnswer->getQuestionType()) {
+                            case FILL_IN_BLANKS:
+                                $isCorrect = FillBlanks::isCorrect($answer['answer']);
+                                break;
+                            case MATCHING:
+                            case DRAGGABLE:
+                            case MATCHING_DRAGGABLE:
+                                $isCorrect = Matching::isCorrect(
+                                    $answer['position'],
+                                    $answer['answer'],
+                                    $answer['question_id']
+                                );
+                                break;
+                            case ORAL_EXPRESSION:
+                                $isCorrect = false;
+                                break;
+                            default:
+                                $isCorrect = $objAnswer->isCorrectByAutoId($answer['answer']);
+                        }
+                        if ($isCorrect) {
+                            $list[$answer['question_id']][] = $answer;
+                        }
+                    } else {
+                        $list[$answer['question_id']][] = $answer;
                     }
                 }
             }
+
+            if ($onlyCorrect === false) {
+                // Only take latest attempt
+                break;
+            }
         }
 
-        return $corrects;
+        return $list;
+    }
+
+    /**
+     * Get the correct answers in all attempts.
+     *
+     * @param int $learnPathId
+     * @param int $learnPathItemId
+     *
+     * @return array
+     */
+    public function getCorrectAnswersInAllAttempts($learnPathId = 0, $learnPathItemId = 0)
+    {
+        return $this->getAnswersInAllAttempts($learnPathId , $learnPathItemId);
     }
 
     /**
@@ -7881,6 +7951,76 @@ class Exercise
         $this->exerciseCategoryId = (int) $value;
     }
 
+    /**
+     * @param array $values
+     *
+     * @throws \Doctrine\DBAL\DBALException
+     */
+    public function setPageResultConfiguration($values)
+    {
+        $pageConfig = api_get_configuration_value('allow_quiz_results_page_config');
+        if ($pageConfig) {
+            $params = [
+                'hide_expected_answer' => isset($values['hide_expected_answer']) ? $values['hide_expected_answer'] : '',
+                'hide_question_score' => isset($values['hide_question_score']) ? $values['hide_question_score'] : '',
+                'hide_total_score' => isset($values['hide_total_score']) ? $values['hide_total_score'] : ''
+            ];
+            $type = Type::getType('array');
+            $platform = Database::getManager()->getConnection()->getDatabasePlatform();
+            $this->pageResultConfiguration = $type->convertToDatabaseValue($params, $platform);
+        }
+    }
+
+    /**
+     * @param array $defaults
+     */
+    public function setPageResultConfigurationDefaults(&$defaults)
+    {
+        $configuration = $this->getPageResultConfiguration();
+        if (!empty($configuration) && !empty($defaults)) {
+            $defaults = array_merge($defaults, $configuration);
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function getPageResultConfiguration()
+    {
+        $pageConfig = api_get_configuration_value('allow_quiz_results_page_config');
+        if ($pageConfig) {
+            /*$params = [
+                'hide_expected_answer' => isset($values['hide_expected_answer']) ? $values['hide_expected_answer'] : '',
+                'hide_question_score' => isset($values['hide_question_score']) ? $values['hide_question_score'] : '',
+                'hide_total_score' => isset($values['hide_total_score']) ? $values['hide_total_score'] : ''
+            ];*/
+            $type = Type::getType('array');
+            $platform = Database::getManager()->getConnection()->getDatabasePlatform();
+            $result = $type->convertToPHPValue($this->pageResultConfiguration, $platform);
+
+            return $result;
+        }
+
+        return [];
+    }
+
+    /**
+     * @param string $attribute
+     *
+     * @return mixed|null
+     */
+    public function getPageConfigurationAttribute($attribute)
+    {
+        $result = $this->getPageResultConfiguration();
+
+        if (!empty($result)) {
+            $value = isset($result[$attribute]) ? $result[$attribute] : null;
+            return $value;
+        }
+
+        return null;
+    }
+
     /**
      * @param bool $showPreviousButton
      *
@@ -7917,6 +8057,26 @@ class Exercise
         return api_get_configuration_value('show_exercise_expected_choice');
     }
 
+    /**
+     * @return bool
+     */
+    public function showExpectedChoiceColumn()
+    {
+        if (!in_array($this->results_disabled, [
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER
+        ])
+        ) {
+            $hide = (int) $this->getPageConfigurationAttribute('hide_expected_answer');
+            if ($hide === 1) {
+                return false;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
     /**
      * @param string $class
      * @param string $scoreLabel
@@ -7927,6 +8087,11 @@ class Exercise
      */
     public function getQuestionRibbon($class, $scoreLabel, $result, $array)
     {
+        $hide = (int) $this->getPageConfigurationAttribute('hide_question_score');
+        if ($hide === 1) {
+            return '';
+        }
+
         if ($this->showExpectedChoice()) {
             $html = null;
             $hideLabel = api_get_configuration_value('exercise_hide_label');
@@ -8072,6 +8237,8 @@ class Exercise
         $courseId = $courseInfo['real_id'];
 
         $sessionId = (int) $sessionId;
+        $exerciseId = (int) $exerciseId;
+
         $result = $this->read($exerciseId);
 
         if (empty($result)) {
@@ -8081,7 +8248,7 @@ class Exercise
         $statusToFilter = empty($sessionId) ? STUDENT : 0;
 
         $studentList = CourseManager::get_user_list_from_course_code(
-            api_get_course_id(),
+            $courseInfo['code'],
             $sessionId,
             null,
             null,
@@ -8164,18 +8331,27 @@ class Exercise
         $em = Database::getManager();
 
         $links = AbstractLink::getGradebookLinksFromItem(
-            $this->selectId(),
+            $this->id,
             LINK_EXERCISE,
-            api_get_course_id(),
-            api_get_session_id()
+            $courseInfo['code'],
+            $sessionId
         );
 
+        if (empty($links)) {
+            $links = AbstractLink::getGradebookLinksFromItem(
+                $this->iId,
+                LINK_EXERCISE,
+                $courseInfo['code'],
+                $sessionId
+            );
+        }
+
         if (!empty($links)) {
             $repo = $em->getRepository('ChamiloCoreBundle:GradebookLink');
 
             foreach ($links as $link) {
                 $linkId = $link['id'];
-                /** @var \Chamilo\CoreBundle\Entity\GradebookLink $exerciseLink */
+                /** @var GradebookLink $exerciseLink */
                 $exerciseLink = $repo->find($linkId);
                 if ($exerciseLink) {
                     $exerciseLink
@@ -9640,7 +9816,7 @@ class Exercise
             ['id' => 'result_disabled_2', 'onclick' => 'check_results_disabled()']
         );
 
-        if ($this->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+        if (in_array($this->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
             $group = $form->addGroup(
                 $resultDisabledGroup,
                 null,

+ 3 - 4
main/exercise/exercise_admin.php

@@ -185,7 +185,6 @@ if ($form->validate()) {
     Display::display_header($nameTools, get_lang('Exercise'));
 
     echo '<div class="actions">';
-
     if ($objExercise->id != 0) {
         echo '<a href="admin.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id.'">'.
             Display::return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM).'</a>';
@@ -199,7 +198,7 @@ if ($form->validate()) {
             }
             $lp_id = (int) $lp_id;
             echo "<a href=\"../lp/lp_controller.php?".api_get_cidreq()."&gradebook=&action=add_item&type=step&lp_id=".$lp_id."#resource_tab-2\">".
-                Display::return_icon('back.png', get_lang("BackTo").' '.get_lang("LearningPaths"), '', ICON_SIZE_MEDIUM)."</a>";
+                Display::return_icon('back.png', get_lang("BackTo").' '.get_lang('LearningPaths'), '', ICON_SIZE_MEDIUM)."</a>";
         } else {
             echo '<a href="exercise.php?'.api_get_cidreq().'">'.
                 Display::return_icon('back.png', get_lang('BackToExercisesList'), '', ICON_SIZE_MEDIUM).
@@ -208,11 +207,11 @@ if ($form->validate()) {
     }
     echo '</div>';
 
-    if ($objExercise->feedback_type == 1) {
+    if (in_array($objExercise->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
         echo Display::return_message(get_lang('DirectFeedbackCantModifyTypeQuestion'));
     }
 
-    if (api_get_setting('search_enabled') == 'true' &&
+    if (api_get_setting('search_enabled') === 'true' &&
         !extension_loaded('xapian')
     ) {
         echo Display::return_message(get_lang('SearchXapianModuleNotInstalled'), 'error');

+ 4 - 6
main/exercise/exercise_result.php

@@ -100,7 +100,7 @@ if (api_is_course_admin() && !in_array($origin, ['learnpath', 'embeddable'])) {
     echo '</div>';
 }
 
-$feedback_type = $objExercise->feedback_type;
+$feedback_type = $objExercise->getFeedbackType();
 $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exe_id);
 
 if (!empty($exercise_stat_info['data_tracking'])) {
@@ -222,7 +222,7 @@ if (!in_array($origin, ['learnpath', 'embeddable'])) {
         Session::erase('duration_time');
     }
     Display::display_footer();
-} elseif ($origin == 'embeddable') {
+} elseif ($origin === 'embeddable') {
     if (api_is_allowed_to_session_edit()) {
         Session::erase('objExercise');
         Session::erase('exe_id');
@@ -232,14 +232,12 @@ if (!in_array($origin, ['learnpath', 'embeddable'])) {
     }
 
     Session::write('attempt_remaining', $remainingMessage);
-
     showEmbeddableFinishButton();
-
     Display::display_reduced_footer();
 } else {
     $lp_mode = Session::read('lp_mode');
-    $url = '../lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.$learnpath_id.'&lp_item_id='.$learnpath_item_id.'&exeId='.$exercise_stat_info['exe_id'].'&fb_type='.$objExercise->feedback_type.'#atoc_'.$learnpath_item_id;
-    $href = $lp_mode == 'fullscreen' ? ' window.opener.location.href="'.$url.'" ' : ' top.location.href="'.$url.'"';
+    $url = '../lp/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.$learnpath_id.'&lp_item_id='.$learnpath_item_id.'&exeId='.$exercise_stat_info['exe_id'].'&fb_type='.$objExercise->getFeedbackType().'#atoc_'.$learnpath_item_id;
+    $href = $lp_mode === 'fullscreen' ? ' window.opener.location.href="'.$url.'" ' : ' top.location.href="'.$url.'"';
 
     if (api_is_allowed_to_session_edit()) {
         Session::erase('objExercise');

+ 2 - 2
main/exercise/exercise_show.php

@@ -127,7 +127,7 @@ if (empty($objExercise)) {
     $objExercise = new Exercise();
     $objExercise->read($exercise_id);
 }
-$feedback_type = $objExercise->feedback_type;
+$feedback_type = $objExercise->getFeedbackType();
 
 // Only users can see their own results
 if (!$is_allowedToEdit) {
@@ -358,7 +358,7 @@ if (!empty($track_exercise_info['data_tracking'])) {
 }
 
 // Display the text when finished message if we are on a LP #4227
-$end_of_message = $objExercise->selectTextWhenFinished();
+$end_of_message = $objExercise->getTextWhenFinished();
 if (!empty($end_of_message) && ($origin === 'learnpath')) {
     echo Display::return_message($end_of_message, 'normal', false);
     echo "<div class='clear'>&nbsp;</div>";

+ 20 - 10
main/exercise/exercise_submit.php

@@ -109,7 +109,6 @@ $logInfo = [
 ];
 Event::registerLog($logInfo);
 
-// Error message
 $error = '';
 $exercise_attempt_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
@@ -667,7 +666,7 @@ if ($formSent && isset($_POST)) {
                 // stores the user answer into the array
                 $exerciseResult[$key] = $choice[$key];
                 //saving each question
-                if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                if (!in_array($objExercise->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
                     $nro_question = $current_question; // - 1;
                     $questionId = $key;
                     // gets the student choice for this question
@@ -1395,7 +1394,7 @@ if (!empty($error)) {
                 $i++;
                 continue;
             } else {
-                if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                if (!in_array($objExercise->getFeedbackType(), [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
                     // if the user has already answered this question
                     if (isset($exerciseResult[$questionId])) {
                         // construction of the Question object
@@ -1414,11 +1413,23 @@ if (!empty($error)) {
         $user_choice = null;
         if (isset($attempt_list[$questionId])) {
             $user_choice = $attempt_list[$questionId];
-        } elseif ($objExercise->saveCorrectAnswers) {
-            $correctAnswers = $objExercise->getCorrectAnswersInAllAttempts(
-                $learnpath_id,
-                $learnpath_item_id
-            );
+        } elseif ($objExercise->getSaveCorrectAnswers()) {
+            $correctAnswers = [];
+            switch ($objExercise->getSaveCorrectAnswers()) {
+                case 1:
+                    $correctAnswers = $objExercise->getCorrectAnswersInAllAttempts(
+                        $learnpath_id,
+                        $learnpath_item_id
+                    );
+                    break;
+                case 2:
+                    $correctAnswers = $objExercise->getAnswersInAllAttempts(
+                        $learnpath_id,
+                        $learnpath_item_id,
+                        false
+                    );
+                    break;
+            }
 
             if (isset($correctAnswers[$questionId])) {
                 $user_choice = $correctAnswers[$questionId];
@@ -1426,8 +1437,7 @@ if (!empty($error)) {
         }
 
         $remind_highlight = '';
-
-        //Hides questions when reviewing a ALL_ON_ONE_PAGE exercise see #4542 no_remind_highlight class hide with jquery
+        // Hides questions when reviewing a ALL_ON_ONE_PAGE exercise see #4542 no_remind_highlight class hide with jquery
         if ($objExercise->type == ALL_ON_ONE_PAGE &&
             isset($_GET['reminder']) && $_GET['reminder'] == 2
         ) {

+ 80 - 101
main/exercise/exercise_submit_modal.php

@@ -9,13 +9,10 @@ use ChamiloSession as Session;
  * @author Julio Montoya <gugli100@gmail.com>
  */
 require_once __DIR__.'/../inc/global.inc.php';
-api_protect_course_script(false);
 
-require_once api_get_path(LIBRARY_PATH).'geometry.lib.php';
-
-//Display::display_reduced_header();
+api_protect_course_script();
 
-echo '<div id="delineation-container">';
+require_once api_get_path(LIBRARY_PATH).'geometry.lib.php';
 
 $message = null;
 $dbg_local = 0;
@@ -34,23 +31,30 @@ $origin = api_get_origin();
 // if origin is learnpath
 $learnpath_id = 0;
 if (isset($_REQUEST['learnpath_id'])) {
-    $learnpath_id = intval($_REQUEST['learnpath_id']);
+    $learnpath_id = (int) $_REQUEST['learnpath_id'];
 }
 
 $learnpath_item_id = 0;
 if (isset($_REQUEST['learnpath_item_id'])) {
-    $learnpath_item_id = intval($_REQUEST['learnpath_item_id']);
+    $learnpath_item_id = (int) $_REQUEST['learnpath_item_id'];
+}
+
+/** @var Exercise $objExercise */
+$objExercise = Session::read('objExercise');
+
+if (empty($objExercise)) {
+    api_not_allowed();
 }
 
 $_SESSION['hotspot_coord'] = [];
-$newquestionList = Session::read('newquestionList', []);
+$newQuestionList = Session::read('newquestionList', []);
 $questionList = Session::read('questionList');
-$exerciseId = intval($_GET['exerciseId']);
-$exerciseType = intval($_GET['exerciseType']);
-$questionNum = intval($_GET['num']);
-$nbrQuestions = isset($_GET['nbrQuestions']) ? intval($_GET['nbrQuestions']) : null;
+$exerciseId = (int) $_GET['exerciseId'];
+$exerciseType = (int) $_GET['exerciseType'];
+$questionNum = (int) $_GET['num'];
+$nbrQuestions = isset($_GET['nbrQuestions']) ? (int) $_GET['nbrQuestions'] : null;
 
-//clean extra session variables
+// Clean extra session variables
 Session::erase('objExerciseExtra'.$exerciseId);
 Session::erase('exerciseResultExtra'.$exerciseId);
 Session::erase('questionListExtra'.$exerciseId);
@@ -69,13 +73,13 @@ if (isset($_GET['hotspot'])) {
     }
 }
 
-$choice_value = '';
 $user_array = substr($user_array, 0, -1);
-
+$choice_value = '';
 if (isset($_GET['choice'])) {
-    $choice_value = intval($_GET['choice']);
+    $choice_value = (int) $_GET['choice'];
 }
 
+echo '<div id="delineation-container">';
 // Getting the options by js
 if (empty($choice_value)) {
     echo "<script>
@@ -116,9 +120,9 @@ if (empty($choice_value)) {
 }
 
 $choice = [];
-$questionid = $questionList[$questionNum];
+$questionId = $questionList[$questionNum];
 // $choice_value => value of the user selection
-$choice[$questionid] = isset($choice_value) ? $choice_value : null;
+$choice[$questionId] = isset($choice_value) ? $choice_value : null;
 
 // initializing
 if (!is_array($exerciseResult)) {
@@ -127,7 +131,7 @@ if (!is_array($exerciseResult)) {
 
 // if the user has answered at least one question
 if (is_array($choice)) {
-    if ($exerciseType == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+    if (in_array($exerciseType, [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
         // $exerciseResult receives the content of the form.
         // Each choice of the student is stored into the array $choice
         $exerciseResult = $choice;
@@ -147,8 +151,8 @@ Session::write('exerciseResult', $exerciseResult);
 Session::write('exerciseResultCoordinates', $exerciseResultCoordinates);
 
 // creates a temporary Question object
-if (in_array($questionid, $questionList)) {
-    $objQuestionTmp = Question:: read($questionid);
+if (in_array($questionId, $questionList)) {
+    $objQuestionTmp = Question:: read($questionId);
     $questionName = $objQuestionTmp->selectTitle();
     $questionDescription = $objQuestionTmp->selectDescription();
     $questionWeighting = $objQuestionTmp->selectWeighting();
@@ -156,9 +160,9 @@ if (in_array($questionid, $questionList)) {
     $quesId = $objQuestionTmp->selectId(); //added by priya saini
 }
 
-$objAnswerTmp = new Answer($questionid);
+$objAnswerTmp = new Answer($questionId);
 $nbrAnswers = $objAnswerTmp->selectNbrAnswers();
-$choice = $exerciseResult[$questionid];
+$choice = $exerciseResult[$questionId];
 $destination = [];
 $comment = '';
 $next = 1;
@@ -181,27 +185,24 @@ if (!empty($choice_value)) {
         $answerWeighting = $objAnswerTmp->selectWeighting($answerId);
         $numAnswer = $objAnswerTmp->selectAutoId($answerId);
 
-        //delineation
+        // Delineation
         $delineation_cord = $objAnswerTmp->selectHotspotCoordinates(1);
         $answer_delineation_destination = $objAnswerTmp->selectDestination(1);
-        if ($dbg_local > 0) {
-            error_log(__LINE__.' answerId: '.$answerId.'('.$answerType.') - user delineation_cord: '.$delineation_cord.' - $answer_delineation_destination: '.$answer_delineation_destination, 0);
-        }
 
         switch ($answerType) {
             // for unique answer
             case UNIQUE_ANSWER:
-                $studentChoice = ($choice_value == $numAnswer) ? 1 : 0;
+                $studentChoice = $choice_value == $numAnswer ? 1 : 0;
                 if ($studentChoice) {
                     $questionScore += $answerWeighting;
                     $totalScore += $answerWeighting;
-                    $newquestionList[] = $questionid;
+                    $newQuestionList[] = $questionId;
                 }
                 break;
             case HOT_SPOT_DELINEATION:
                 $studentChoice = $choice[$answerId];
                 if ($studentChoice) {
-                    $newquestionList[] = $questionid;
+                    $newQuestionList[] = $questionId;
                 }
                 if ($answerId === 1) {
                     $questionScore += $answerWeighting;
@@ -219,12 +220,9 @@ if (!empty($choice_value)) {
             }
         } elseif ($answerType == HOT_SPOT_DELINEATION) {
             if ($next) {
-                if ($dbg_local > 0) {
-                    error_log(__LINE__.' - next', 0);
-                }
                 $hot_spot_load = true; //apparently the script is called twice
                 $user_answer = $user_array;
-                $_SESSION['exerciseResultCoordinates'][$questionid] = $user_answer; //needed for exercise_result.php
+                $_SESSION['exerciseResultCoordinates'][$questionId] = $user_answer; //needed for exercise_result.php
 
                 // we compare only the delineation not the other points
                 $answer_question = $_SESSION['hotspot_coord'][1];
@@ -255,12 +253,8 @@ if (!empty($choice_value)) {
                     $excess = $poly_results['s2Only'];
                 }
 
-                //$overlap = round(polygons_overlap($poly_answer,$poly_user)); //this is an area in pixels
-                if ($dbg_local > 0) {
-                    error_log(__LINE__.' - Polygons results are '.print_r($poly_results, 1), 0);
-                }
                 if ($overlap < 1) {
-                    //shortcut to avoid complicated calculations
+                    // shortcut to avoid complicated calculations
                     $final_overlap = 0;
                     $final_missing = 100;
                     $final_excess = 100;
@@ -293,15 +287,15 @@ if (!empty($choice_value)) {
                 if ($answerId === 1) {
                     //setting colors
                     if ($final_overlap >= $threadhold1) {
-                        $overlap_color = true; //echo 'a';
+                        $overlap_color = true;
                     }
 
                     if ($final_excess <= $threadhold2) {
-                        $excess_color = true; //echo 'b';
+                        $excess_color = true;
                     }
 
                     if ($final_missing <= $threadhold3) {
-                        $missing_color = true; //echo 'c';
+                        $missing_color = true;
                     }
 
                     $try_hotspot = null;
@@ -328,17 +322,11 @@ if (!empty($choice_value)) {
                     $select_question_hotspot = $destination_items[3];
                     $url_hotspot = $destination_items[4];
                 } elseif ($answerId > 1) {
-                    if ($objAnswerTmp->selectHotspotType($answerId) == 'noerror') {
-                        if ($dbg_local > 0) {
-                            error_log(__LINE__.' - answerId is of type noerror', 0);
-                        }
-                        //type no error shouldn't be treated
+                    if ($objAnswerTmp->selectHotspotType($answerId) === 'noerror') {
+                        // Type no error shouldn't be treated
                         $next = 1;
                         continue;
                     }
-                    if ($dbg_local > 0) {
-                        error_log(__LINE__.' - answerId is >1 so we\'re probably in OAR', 0);
-                    }
                     //check the intersection between the oar and the user
                     //echo 'user';	print_r($x_user_list);		print_r($y_user_list);
                     //echo 'official';print_r($x_list);print_r($y_list);
@@ -347,14 +335,14 @@ if (!empty($choice_value)) {
                     //$delineation_cord=$objAnswerTmp->selectHotspotCoordinates($answerId);
                     $delineation_cord = $objAnswerTmp->selectHotspotCoordinates($answerId); //getting the oars coordinates
                     $poly_answer = convert_coordinates($delineation_cord, '|');
+                    // getting max coordinates
                     $max_coord = poly_get_max(
                         $poly_user,
                         $poly_answer
-                    ); //getting max coordinates
+                    );
                     $test = false;
-                    // if ($answerId == 2 ){$test = true;} for test oars
-
-                    if (empty($_GET['hotspot'])) { //no user response
+                    if (empty($_GET['hotspot'])) {
+                        // no user response
                         $overlap = false;
                     } else {
                         // poly_compile really works tested with gnuplot
@@ -402,29 +390,22 @@ if (!empty($choice_value)) {
                         $url_hotspot = $destination_items[4];
                     }
                 }
-            } else {
-                // the first delineation feedback
-                if ($dbg_local > 0) {
-                    error_log(__LINE__.' first', 0);
-                }
             }
         }
     }
 
+    $overlap_color = 'red';
     if ($overlap_color) {
         $overlap_color = 'green';
-    } else {
-        $overlap_color = 'red';
     }
+
+    $missing_color = 'red';
     if ($missing_color) {
         $missing_color = 'green';
-    } else {
-        $missing_color = 'red';
     }
+    $excess_color = 'red';
     if ($excess_color) {
         $excess_color = 'green';
-    } else {
-        $excess_color = 'red';
     }
 
     if (!is_numeric($final_overlap)) {
@@ -466,52 +447,50 @@ if (!empty($choice_value)) {
     </tr>
     </table>';
 }
-Session::write('newquestionList', $newquestionList);
+Session::write('newquestionList', $newQuestionList);
 $links = '';
-if (isset($choice_value) && $choice_value == -1) {
-    if ($answerType != HOT_SPOT_DELINEATION) {
-        $links .= '<a href="#" onclick="tb_remove();">'.get_lang('ChooseAnAnswer').'</a><br />';
+if ($objExercise->getFeedbackType() === EXERCISE_FEEDBACK_TYPE_DIRECT) {
+    if (isset($choice_value) && $choice_value == -1) {
+        if ($answerType != HOT_SPOT_DELINEATION) {
+            $links .= '<a href="#" onclick="tb_remove();">'.get_lang('ChooseAnAnswer').'</a><br />';
+        }
     }
 }
 
-$destinationid = null;
-
+$destinationId = null;
 if ($answerType != HOT_SPOT_DELINEATION) {
     if (!empty($destination)) {
         $item_list = explode('@@', $destination);
         $try = $item_list[0];
         $lp = $item_list[1];
-        $destinationid = $item_list[2];
+        $destinationId = $item_list[2];
         $url = $item_list[3];
     }
     $table_resume = '';
 } else {
     $try = $try_hotspot;
     $lp = $lp_hotspot;
-    $destinationid = $select_question_hotspot;
+    $destinationId = $select_question_hotspot;
     $url = $url_hotspot;
+    $exerciseResult[$questionId] = 0;
     if ($organs_at_risk_hit == 0 && $wrong_results == false) {
         // no error = no oar and no wrong result for delineation
-        //show if no error
-        //echo 'no error';
+        // show if no error
         $comment = $answerComment = $objAnswerTmp->selectComment($nbrAnswers);
         $answerDestination = $objAnswerTmp->selectDestination($nbrAnswers);
-
-        //we send the error
+        // we send the error
         $destination_items = explode('@@', $answerDestination);
         $try = $destination_items[1];
         $lp = $destination_items[2];
-        $destinationid = $destination_items[3];
+        $destinationId = $destination_items[3];
         $url = $destination_items[4];
-        $exerciseResult[$questionid] = 1;
-    } else {
-        $exerciseResult[$questionid] = 0;
+        $exerciseResult[$questionId] = 1;
     }
 }
 
 // the link to retry the question
 if (isset($try) && $try == 1) {
-    $num_value_array = array_keys($questionList, $questionid);
+    $num_value_array = array_keys($questionList, $questionId);
     $links .= Display:: return_icon(
         'reload.gif',
         '',
@@ -530,6 +509,7 @@ if (!empty($lp)) {
         ['style' => 'padding-left:0px;padding-right:5px;']
     ).'<a target="_blank" href="'.$lp_url.'">'.get_lang('SeeTheory').'</a><br />';
 }
+
 $links .= '<br />';
 
 // the link to an external website or link
@@ -541,8 +521,13 @@ if (!empty($url)) {
     ).'<a target="_blank" href="'.$url.'">'.get_lang('VisitUrl').'</a><br /><br />';
 }
 
+if ($objExercise->getFeedbackType() === EXERCISE_FEEDBACK_TYPE_POPUP) {
+    $nextQuestion = $questionNum + 1;
+    $destinationId = isset($questionList[$nextQuestion]) ? $questionList[$nextQuestion] : -1;
+}
+
 // the link to finish the test
-if ($destinationid == -1) {
+if ($destinationId == -1) {
     $links .= Display:: return_icon(
         'finish.gif',
         '',
@@ -550,17 +535,18 @@ if ($destinationid == -1) {
     ).'<a onclick="SendEx(-1);" href="#">'.get_lang('EndActivity').'</a><br /><br />';
 } else {
     // the link to other question
-    if (in_array($destinationid, $questionList)) {
-        $objQuestionTmp = Question :: read($destinationid);
+    if (in_array($destinationId, $questionList)) {
+        $objQuestionTmp = Question::read($destinationId);
         $questionName = $objQuestionTmp->selectTitle();
-        $num_value_array = (array_keys($questionList, $destinationid));
-        $links .= Display:: return_icon(
+        $num_value_array = array_keys($questionList, $destinationId);
+        $icon = Display::return_icon(
                 'quiz.png',
                 '',
                 ['style' => 'padding-left:0px;padding-right:5px;']
         );
         $links .= '<a onclick="SendEx('.$num_value_array[0].');" href="#">'.
-            get_lang('GoToQuestion').' '.$num_value_array[0].'</a><br /><br />';
+                get_lang('Question').' '.$num_value_array[0].'</a>&nbsp;';
+        $links .= $icon;
     }
 }
 
@@ -568,25 +554,20 @@ echo '<script>
 function SendEx(num) {
     if (num == -1) {
         window.location.href = "exercise_result.php?take_session=1&exerciseId='.$exerciseId.'&num="+num+"&exerciseType='.$exerciseType.'&origin='.$origin.'&learnpath_item_id='.$learnpath_item_id.'&learnpath_id='.$learnpath_id.'";
-        //tb_remove();
     } else {
         num -= 1;
         window.location.href = "exercise_submit.php?tryagain=1&exerciseId='.$exerciseId.'&num="+num+"&exerciseType='.$exerciseType.'&origin='.$origin.'&learnpath_item_id='.$learnpath_item_id.'&learnpath_id='.$learnpath_id.'";
-        //tb_remove();
     }
     
     return false;
 }
 </script>';
 
-if ($links != '') {
-    echo '<h1><div style="color:#333;">'.get_lang('Feedback').'</div></h1>';
+if (!empty($links)) {
+    //echo '<h1><div style="color:#333;">'.get_lang('Feedback').'</div></h1>';
     if ($answerType == HOT_SPOT_DELINEATION) {
         if ($organs_at_risk_hit > 0) {
-            //$message='<p>'.get_lang('YourDelineation').'</p>';
-            //$message.=$table_resume;
             $message .= '<br />'.get_lang('ResultIs').' <b>'.get_lang('Unacceptable').'</b><br />';
-            //if ($wrong_results) { }
             $message .= '<p style="color:#DC0A0A;"><b>'.get_lang('OARHit').'</b></p>';
             $message .= '<p>'.$comment.'</p>';
         } else {
@@ -595,16 +576,17 @@ if ($links != '') {
             $message .= '<br />'.get_lang('ResultIs').' <b>'.$result_comment.'</b><br />';
             $message .= '<p>'.$comment.'</p>';
         }
+        echo '<br />';
         echo $message;
     } else {
         echo '<p>'.$comment.'</p>';
     }
-    echo '<h3>'.$links.'</h3>';
+    echo '<div style="padding-left: 450px"><h5>'.$links.'</h5></div>';
     echo '</div>';
 
     Session::write('hot_spot_result', $message);
-    $_SESSION['hotspot_delineation_result'][$exerciseId][$questionid] = [$message, $exerciseResult[$questionid]];
-    //reseting the exerciseResult variable
+    $_SESSION['hotspot_delineation_result'][$exerciseId][$questionId] = [$message, $exerciseResult[$questionId]];
+    // Resetting the exerciseResult variable
     Session::write('exerciseResult', $exerciseResult);
 
     //save this variables just in case the exercise loads an LP with other exercise
@@ -615,10 +597,7 @@ if ($links != '') {
     $questionNum++;
     echo '<script>
             window.location.href = "exercise_submit.php?exerciseId='.$exerciseId.'&num='.$questionNum.'&exerciseType='.$exerciseType.'&'.api_get_cidreq().'";
-            //tb_remove();
         </script>';
 }
 
 echo '</div>';
-
-//Display::display_footer();

+ 4 - 6
main/exercise/global_multiple_answer.class.php

@@ -266,13 +266,11 @@ class GlobalMultipleAnswer extends Question
         $header = parent::return_header($exercise, $counter, $score);
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
-        if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-        ])
-        ) {
+        if (!in_array($exercise->results_disabled, [RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER])) {
             $header .= '<th>'.get_lang('Choice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
         }
 
         $header .= '<th>'.get_lang('Answer').'</th>';

+ 24 - 29
main/exercise/hotspot_admin.inc.php

@@ -159,9 +159,9 @@ if ($submitAnswers || $buttonBack) {
         }
 
         $questionWeighting = $nbrGoodAnswers = 0;
-        $select_question = $_POST['select_question'];
+        $select_question = isset($_POST['select_question']) ? $_POST['select_question'] : null;
         $try = isset($_POST['try']) ? $_POST['try'] : [];
-        $url = $_POST['url'];
+        $url = isset($_POST['url']) ? $_POST['url'] : '';
         $destination = [];
 
         $threadhold1 = $_POST['threadhold1'];
@@ -169,10 +169,6 @@ if ($submitAnswers || $buttonBack) {
         $threadhold3 = $_POST['threadhold3'];
 
         for ($i = 1; $i <= $nbrAnswers; $i++) {
-            if ($debug > 0) {
-                echo str_repeat('&nbsp;', 4).'$answerType is HOT_SPOT'."<br />\n";
-            }
-
             $reponse[$i] = trim($reponse[$i]);
             $comment[$i] = trim($comment[$i]);
             $weighting[$i] = $weighting[$i];
@@ -180,19 +176,19 @@ if ($submitAnswers || $buttonBack) {
             if (empty($threadhold1[$i])) {
                 $threadhold1_str = 0;
             } else {
-                $threadhold1_str = intval($threadhold1[$i]);
+                $threadhold1_str = (int) $threadhold1[$i];
             }
 
             if (empty($threadhold2[$i])) {
                 $threadhold2_str = 0;
             } else {
-                $threadhold2_str = intval($threadhold2[$i]);
+                $threadhold2_str = (int) $threadhold2[$i];
             }
 
             if (empty($threadhold3[$i])) {
                 $threadhold3_str = 0;
             } else {
-                $threadhold3_str = intval($threadhold3[$i]);
+                $threadhold3_str = (int) $threadhold3[$i];
             }
 
             $threadhold_total = $threadhold1_str.';'.$threadhold2_str.';'.$threadhold3_str;
@@ -209,9 +205,8 @@ if ($submitAnswers || $buttonBack) {
                 $lp_str = $lp[$i];
             }
 
-            if ($url[$i] == '') {
-                $url_str = '';
-            } else {
+            $url_str = '';
+            if (isset($url[$i]) && !empty($url[$i])) {
                 $url_str = $url[$i];
             }
 
@@ -245,14 +240,14 @@ if ($submitAnswers || $buttonBack) {
                 $objAnswer->cancel();
                 break;
             }
-        }  // end for()
+        }
 
-        //now the noerror section
-        $selectQuestionNoError = Security::remove_XSS($_POST['select_question_noerror']);
-        $lp_noerror = Security::remove_XSS($_POST['lp_noerror']);
+        // now the noerror section
+        $selectQuestionNoError = isset($_POST['select_question_noerror']) ? Security::remove_XSS($_POST['select_question_noerror']) : null;
+        $lp_noerror = isset($_POST['lp_noerror']) ? Security::remove_XSS($_POST['lp_noerror']) : '';
         $try_noerror = isset($_POST['try_noerror']) ? Security::remove_XSS($_POST['try_noerror']) : null;
-        $url_noerror = Security::remove_XSS($_POST['url_noerror']);
-        $comment_noerror = Security::remove_XSS($_POST['comment_noerror']);
+        $url_noerror = isset($_POST['url_noerror']) ? Security::remove_XSS($_POST['url_noerror']) : null;
+        $comment_noerror = isset($_POST['comment_noerror']) ? Security::remove_XSS($_POST['comment_noerror']) : null;
         $threadhold_total = '0;0;0';
 
         if ($try_noerror == 'on') {
@@ -385,7 +380,7 @@ if (isset($modifyAnswers)) {
         for ($i = 1; $i <= $nbrAnswers; $i++) {
             $reponse[$i] = $objAnswer->selectAnswer($i);
 
-            if ($objExercise->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+            if ($objExercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
                 $comment[$i] = $objAnswer->selectComment($i);
             }
 
@@ -436,7 +431,7 @@ if (isset($modifyAnswers)) {
     $_SESSION['tmp_answers'] = [];
     $_SESSION['tmp_answers']['answer'] = $reponse;
 
-    if ($objExercise->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+    if ($objExercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
         $_SESSION['tmp_answers']['comment'] = $comment;
     }
 
@@ -474,7 +469,7 @@ if (isset($modifyAnswers)) {
                 $nbrAnswers--;
                 // Remove the last answer
                 $tmp = array_pop($_SESSION['tmp_answers']['answer']);
-                if ($objExercise->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+                if ($objExercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
                     $tmp = array_pop($_SESSION['tmp_answers']['comment']);
                 }
                 $tmp = array_pop($_SESSION['tmp_answers']['weighting']);
@@ -494,7 +489,7 @@ if (isset($modifyAnswers)) {
 
             // Add a new answer
             $_SESSION['tmp_answers']['answer'][] = '';
-            if ($objExercise->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+            if ($objExercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
                 $_SESSION['tmp_answers']['comment'][] = '';
             }
             $_SESSION['tmp_answers']['weighting'][] = '1';
@@ -615,7 +610,7 @@ if (isset($modifyAnswers)) {
                     <th width="5">&nbsp;</th>
                     <th><?php echo get_lang('HotspotDescription'); ?> *</th>
                     <?php
-                    if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                    if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
                         echo '<th>'.get_lang('Comment').'</th>';
                         if ($answerType == HOT_SPOT_DELINEATION) {
                             echo '<th >'.get_lang('Scenario').'</th>';
@@ -736,7 +731,7 @@ if (isset($modifyAnswers)) {
                                 <input type="hidden" name="hotspot_coordinates[<?php echo $i; ?>]" value="<?php
                                 echo empty($hotspot_coordinates[$i]) ? '0;0|0|0' : $hotspot_coordinates[$i]; ?>"/>
                             </td>
-                            <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                            <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
                                     ?>
                                 <td>
                                     <div class="checkbox">
@@ -795,7 +790,7 @@ if (isset($modifyAnswers)) {
                                               name="comment[<?php echo $i; ?>]"
                                               style="width: 100%"><?php echo Security::remove_XSS($comment[$i]); ?></textarea>
                                 </td>
-                                <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                                <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
                     ?>
                                     <td>
                                         <table>
@@ -850,7 +845,7 @@ if (isset($modifyAnswers)) {
                                 <tr>
                                     <th width="5">&nbsp;<?php /* echo get_lang('Hotspot'); */ ?></th>
                                     <th><?php echo get_lang('OAR'); ?>*</th>
-                                    <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                                    <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
                         ?>
                                         <th colspan="2"><?php echo get_lang('Comment'); ?></th>
                                         <th><?php if ($answerType == HOT_SPOT_DELINEATION) {
@@ -883,7 +878,7 @@ if (isset($modifyAnswers)) {
                                 <input type="hidden" name="hotspot_coordinates[<?php echo $i; ?>]" value="<?php
                                 echo empty($hotspot_coordinates[$i]) ? '0;0|0|0' : $hotspot_coordinates[$i]; ?>"/>
                             </td>
-                            <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                            <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
                                     ?>
                                 <td>
                                     <div class="checkbox">
@@ -1029,7 +1024,7 @@ if (isset($modifyAnswers)) {
         ?>
                     <tr>
                         <th colspan="2"><?php echo get_lang('IfNoError'); ?></th>
-                        <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                        <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
             ?>
                             <th colspan="2"><?php echo get_lang('Feedback'); ?></th>
                             <th><?php echo get_lang('Scenario'); ?></th>
@@ -1049,7 +1044,7 @@ if (isset($modifyAnswers)) {
                             <textarea class="form-control" wrap="virtual" rows="3" cols="25"
                                       name="comment_noerror"><?php echo Security::remove_XSS($comment_noerror); ?></textarea>
                         </td>
-                        <?php if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+                        <?php if ($objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
             ?>
                             <td>
                                 <div class="checkbox">

+ 6 - 2
main/exercise/matching.class.php

@@ -292,13 +292,17 @@ class Matching extends Question
         ])
         ) {
             $header .= '<th>'.get_lang('Choice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            //if ($exercise->showExpectedChoiceColumn()) {
+                //$header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            //}
         }
 
         if ($exercise->showExpectedChoice()) {
             $header .= '<th>'.get_lang('Status').'</th>';
         } else {
-            $header .= '<th>'.get_lang('CorrespondsTo').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('CorrespondsTo').'</th>';
+            }
         }
         $header .= '</tr>';
 

+ 2 - 5
main/exercise/multiple_answer.class.php

@@ -235,11 +235,8 @@ class MultipleAnswer extends Question
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
         $header .= '<th>'.get_lang('Choice').'</th>';
-        if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-        ])
-        ) {
+
+        if ($exercise->showExpectedChoiceColumn()) {
             $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
         }
 

+ 4 - 3
main/exercise/multiple_answer_combination.class.php

@@ -233,12 +233,13 @@ class MultipleAnswerCombination extends Question
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
         if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER
         ])
         ) {
             $header .= '<th>'.get_lang('Choice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
         }
 
         $header .= '<th>'.get_lang('Answer').'</th>';

+ 7 - 6
main/exercise/multiple_answer_true_false.class.php

@@ -52,7 +52,7 @@ class MultipleAnswerTrueFalse extends Question
         $html .= '<th>'.get_lang('Answer').'</th>';
 
         // show column comment when feedback is enable
-        if ($obj_ex->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+        if ($obj_ex->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
             $html .= '<th>'.get_lang('Comment').'</th>';
         }
 
@@ -146,7 +146,7 @@ class MultipleAnswerTrueFalse extends Question
             );
 
             // show comment when feedback is enable
-            if ($obj_ex->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
+            if ($obj_ex->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) {
                 $form->addElement(
                     'html_editor',
                     'comment['.$i.']',
@@ -314,12 +314,13 @@ class MultipleAnswerTrueFalse extends Question
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
         if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER
         ])
         ) {
             $header .= '<th>'.get_lang('Choice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
         }
 
         $header .= '<th>'.get_lang('Answer').'</th>';
@@ -327,7 +328,7 @@ class MultipleAnswerTrueFalse extends Question
         if ($exercise->showExpectedChoice()) {
             $header .= '<th>'.get_lang('Status').'</th>';
         }
-        if ($exercise->feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM ||
+        if ($exercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM ||
             in_array(
                 $exercise->results_disabled,
                 [

+ 2 - 2
main/exercise/overview.php

@@ -286,7 +286,7 @@ if (!empty($attempts)) {
             ]
         ) || (
             $objExercise->results_disabled == RESULT_DISABLE_SHOW_SCORE_ONLY &&
-            $objExercise->feedback_type == EXERCISE_FEEDBACK_TYPE_END
+            $objExercise->getFeedbackType() == EXERCISE_FEEDBACK_TYPE_END
         )
         ) {
             if ($blockShowAnswers &&
@@ -355,7 +355,7 @@ if (!empty($attempts)) {
             $header_names = [get_lang('Attempt'), get_lang('StartDate'), get_lang('IP')];
             break;
         case RESULT_DISABLE_SHOW_SCORE_ONLY:
-            if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_END) {
+            if ($objExercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_END) {
                 $header_names = [get_lang('Attempt'), get_lang('StartDate'), get_lang('IP'), get_lang('Score')];
             } else {
                 $header_names = [

+ 6 - 6
main/exercise/question.class.php

@@ -1816,17 +1816,17 @@ abstract class Question
      */
     public static function displayTypeMenu($objExercise)
     {
-        $feedback_type = $objExercise->feedback_type;
+        $feedbackType = $objExercise->getFeedbackType();
         $exerciseId = $objExercise->id;
 
         // 1. by default we show all the question types
         $question_type_custom_list = self::get_question_type_list();
 
-        if (!isset($feedback_type)) {
-            $feedback_type = 0;
+        if (!isset($feedbackType)) {
+            $feedbackType = 0;
         }
 
-        if ($feedback_type == 1) {
+        if (in_array($feedbackType, [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
             //2. but if it is a feedback DIRECT we only show the UNIQUE_ANSWER type that is currently available
             $question_type_custom_list = [
                 UNIQUE_ANSWER => self::$questionTypes[UNIQUE_ANSWER],
@@ -1875,7 +1875,7 @@ abstract class Question
                 ICON_SIZE_BIG
             );
         } else {
-            if ($feedback_type == 1) {
+            if (in_array($feedbackType, [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP])) {
                 echo $url = "<a href=\"question_pool.php?".api_get_cidreq()."&type=1&fromExercise=$exerciseId\">";
             } else {
                 echo $url = '<a href="question_pool.php?'.api_get_cidreq().'&fromExercise='.$exerciseId.'">';
@@ -2403,7 +2403,7 @@ abstract class Question
     {
         return
             in_array($this->type, $this->questionTypeWithFeedback) &&
-            $exercise->feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM;
+            $exercise->getFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM;
     }
 
     /**

+ 1 - 2
main/exercise/question_list_admin.inc.php

@@ -43,7 +43,6 @@ $ajax_url = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?'.api_get_cidreq().'&
         <?php echo get_lang('AreYouSureToDelete'); ?>
     </p>
 </div>
-
 <script>
     $(function () {
         $("#dialog:ui-dialog").dialog("destroy");
@@ -148,7 +147,7 @@ $ajax_url = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?'.api_get_cidreq().'&
 </script>
 <?php
 
-//we filter the type of questions we can add
+// Filter the type of questions we can add
 Question::displayTypeMenu($objExercise);
 
 echo '<div id="message"></div>';

+ 4 - 1
main/exercise/question_pool.php

@@ -478,7 +478,10 @@ $new_question_list = [];
 $new_question_list['-1'] = get_lang('All');
 if (!empty($_course)) {
     foreach ($question_list as $key => $item) {
-        if ($objExercise->feedback_type == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+        if (in_array(
+            $objExercise->getFeedbackType(),
+            [EXERCISE_FEEDBACK_TYPE_DIRECT, EXERCISE_FEEDBACK_TYPE_POPUP]
+        )) {
             if (!in_array($key, [HOT_SPOT_DELINEATION, UNIQUE_ANSWER])) {
                 continue;
             }

+ 74 - 57
main/exercise/unique_answer.class.php

@@ -58,12 +58,18 @@ class UniqueAnswer extends Question
          */
 
         $feedback_title = '';
-        if ($obj_ex->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
-            //Scenario
-            $comment_title = '<th width="20%">'.get_lang('Comment').'</th>';
-            $feedback_title = '<th width="20%">'.get_lang('Scenario').'</th>';
-        } else {
-            $comment_title = '<th width="40%">'.get_lang('Comment').'</th>';
+        switch ($obj_ex->getFeedbackType()) {
+            case EXERCISE_FEEDBACK_TYPE_DIRECT:
+                // Scenario
+                $comment_title = '<th width="20%">'.get_lang('Comment').'</th>';
+                $feedback_title = '<th width="20%">'.get_lang('Scenario').'</th>';
+                break;
+            case EXERCISE_FEEDBACK_TYPE_POPUP:
+                $comment_title = '<th width="20%">'.get_lang('Comment').'</th>';
+                break;
+            default:
+                $comment_title = '<th width="40%">'.get_lang('Comment').'</th>';
+                break;
         }
 
         $html = '<table class="table table-striped table-hover">
@@ -218,52 +224,14 @@ class UniqueAnswer extends Question
                 'required'
             );
 
-            if ($obj_ex->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
-                $form->addHtmlEditor(
-                    'comment['.$i.']',
-                    null,
-                    null,
-                    false,
-                    $editor_config
-                );
-                // Direct feedback
-                //Adding extra feedback fields
-                $group = [];
-                $group['try'.$i] = $form->createElement(
-                    'checkbox',
-                    'try'.$i,
-                    null,
-                    get_lang('TryAgain')
-                );
-                $group['lp'.$i] = $form->createElement(
-                    'select',
-                    'lp'.$i,
-                    get_lang('SeeTheory').': ',
-                    $select_lp_id
-                );
-                $group['destination'.$i] = $form->createElement(
-                    'select',
-                    'destination'.$i,
-                    get_lang('GoToQuestion').': ',
-                    $select_question
-                );
-                $group['url'.$i] = $form->createElement(
-                    'text',
-                    'url'.$i,
-                    get_lang('Other').': ',
-                    [
-                        'class' => 'col-md-2',
-                        'placeholder' => get_lang('Other'),
-                    ]
-                );
-                $form->addGroup($group, 'scenario');
-
-                $renderer->setElementTemplate(
-                    '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}',
-                    'scenario'
-                );
-            } else {
-                $form->addHtmlEditor('comment['.$i.']', null, null, false, $editor_config);
+            switch ($obj_ex->getFeedbackType()) {
+                case EXERCISE_FEEDBACK_TYPE_DIRECT:
+                    $this->setDirectOptions($i, $form, $renderer, $select_lp_id, $select_question);
+                    break;
+                case EXERCISE_FEEDBACK_TYPE_POPUP:
+                default:
+                    $form->addHtmlEditor('comment['.$i.']', null, null, false, $editor_config);
+                    break;
             }
             $form->addText('weighting['.$i.']', null, null, ['value' => '0']);
             $form->addHtml('</tr>');
@@ -314,6 +282,59 @@ class UniqueAnswer extends Question
         $form->setConstants(['nb_answers' => $nb_answers]);
     }
 
+    public function setDirectOptions($i, FormValidator $form, $renderer, $select_lp_id, $select_question)
+    {
+        $editor_config = [
+            'ToolbarSet' => 'TestProposedAnswer',
+            'Width' => '100%',
+            'Height' => '125',
+        ];
+
+        $form->addHtmlEditor(
+            'comment['.$i.']',
+            null,
+            null,
+            false,
+            $editor_config
+        );
+        // Direct feedback
+        //Adding extra feedback fields
+        $group = [];
+        $group['try'.$i] = $form->createElement(
+            'checkbox',
+            'try'.$i,
+            null,
+            get_lang('TryAgain')
+        );
+        $group['lp'.$i] = $form->createElement(
+            'select',
+            'lp'.$i,
+            get_lang('SeeTheory').': ',
+            $select_lp_id
+        );
+        $group['destination'.$i] = $form->createElement(
+            'select',
+            'destination'.$i,
+            get_lang('GoToQuestion').': ',
+            $select_question
+        );
+        $group['url'.$i] = $form->createElement(
+            'text',
+            'url'.$i,
+            get_lang('Other').': ',
+            [
+                'class' => 'col-md-2',
+                'placeholder' => get_lang('Other'),
+            ]
+        );
+        $form->addGroup($group, 'scenario');
+
+        $renderer->setElementTemplate(
+            '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}',
+            'scenario'
+        );
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -414,11 +435,7 @@ class UniqueAnswer extends Question
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
         $header .= '<th>'.get_lang('Choice').'</th>';
-        if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-        ])
-        ) {
+        if ($exercise->showExpectedChoiceColumn()) {
             $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
         }
 

+ 5 - 4
main/exercise/unique_answer_no_option.class.php

@@ -54,7 +54,7 @@ class UniqueAnswerNoOption extends Question
          */
 
         $feedback_title = '';
-        if ($obj_ex->selectFeedbackType() == 1) {
+        if ($obj_ex->getFeedbackType() == 1) {
             $editor_config['Width'] = '250';
             $editor_config['Height'] = '110';
             $comment_title = '<th width="50%" >'.get_lang('Comment').'</th>';
@@ -405,12 +405,13 @@ class UniqueAnswerNoOption extends Question
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
         if (!in_array($exercise->results_disabled, [
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            //RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER
         ])
         ) {
             $header .= '<th>'.get_lang('Choice').'</th>';
-            $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            if ($exercise->showExpectedChoiceColumn()) {
+                $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
+            }
         }
         $header .= '<th>'.get_lang('Answer').'</th>';
         if ($exercise->showExpectedChoice()) {

+ 7 - 10
main/gradebook/gradebook_flatview.php

@@ -45,19 +45,17 @@ if ($showlink == '0' && $showeval == '0') {
 $cat = Category::load($categoryId);
 $userId = isset($_GET['userid']) ? (int) $_GET['userid'] : 0;
 
+$alleval = null;
 if ($showeval) {
     $alleval = $cat[0]->get_evaluations($userId, true);
-} else {
-    $alleval = null;
 }
 
+$alllinks = null;
 if ($showlink) {
     $alllinks = $cat[0]->get_links($userId, true);
-} else {
-    $alllinks = null;
 }
 
-if (isset($export_flatview_form) && !$file_type == 'pdf') {
+if (isset($export_flatview_form) && !$file_type === 'pdf') {
     Display::addFlash(
         Display::return_message(
             $export_flatview_form->toHtml(),
@@ -76,7 +74,7 @@ $simple_search_form = new UserForm(
     null,
     'simple_search_form',
     null,
-    api_get_self().'?selectcat='.$category_id
+    api_get_self().'?selectcat='.$category_id.'&'.api_get_cidreq()
 );
 $values = $simple_search_form->exportValues();
 
@@ -91,10 +89,9 @@ if ($simple_search_form->validate() && empty($keyword)) {
 if (!empty($keyword)) {
     $users = GradebookUtils::find_students($keyword);
 } else {
+    $users = null;
     if (isset($alleval) && isset($alllinks)) {
         $users = GradebookUtils::get_all_users($alleval, $alllinks);
-    } else {
-        $users = null;
     }
 }
 $offset = isset($_GET['offset']) ? $_GET['offset'] : '0';
@@ -176,7 +173,7 @@ if (isset($_GET['exportpdf'])) {
 
     if ($export_pdf_form->validate()) {
         $params = $export_pdf_form->exportValues();
-        Display::set_header(null, false, false);
+        Display::set_header();
         $params['join_firstname_lastname'] = true;
         $params['show_official_code'] = true;
         $params['export_pdf'] = true;
@@ -214,7 +211,7 @@ if (isset($_GET['print'])) {
 }
 
 if (!empty($_GET['export_report']) &&
-    $_GET['export_report'] == 'export_report'
+    $_GET['export_report'] === 'export_report'
 ) {
     if (api_is_platform_admin() || api_is_course_admin() || api_is_session_general_coach() || $isDrhOfCourse) {
         $user_id = null;

+ 13 - 3
main/gradebook/index.php

@@ -39,11 +39,21 @@ switch ($action) {
         if (!empty($itemId)) {
             $link = LinkFactory::create(LINK_EXERCISE);
             $links = $link::load($itemId);
+
+            $exercise = new Exercise(api_get_course_int_id());
             /** @var ExerciseLink $link */
             foreach ($links as $link) {
-                $exercise = new Exercise(api_get_course_int_id());
-                $exercise->read($link->get_ref_id());
-                $exercise->generateStats($link->get_ref_id(), api_get_course_info(), api_get_session_id());
+                $exerciseId = $link->get_ref_id();
+                $data = $link->get_exercise_data();
+                if (empty($data)) {
+                    continue;
+                }
+
+                $exerciseId = $data['id'];
+                $result = $exercise->read($exerciseId);
+                if ($result) {
+                    $exercise->generateStats($exerciseId, api_get_course_info(), api_get_session_id());
+                }
             }
             Display::addFlash(Display::return_message(get_lang('Updated')));
         }

+ 0 - 1
main/gradebook/lib/be/category.class.php

@@ -2525,7 +2525,6 @@ class Category implements GradebookItem
         Session::write('gradebook_dest', $url);
     }
 
-
     /**
      * @return int
      */

+ 47 - 41
main/gradebook/lib/be/exerciselink.class.php

@@ -240,7 +240,7 @@ class ExerciseLink extends AbstractLink
         $courseId = $this->getCourseId();
         $exerciseData = $this->get_exercise_data();
 
-        $exerciseId = isset($exerciseData['id']) ? $exerciseData['id'] : 0;
+        $exerciseId = isset($exerciseData['id']) ? (int) $exerciseData['id'] : 0;
         $stud_id = (int) $stud_id;
 
         if (empty($exerciseId)) {
@@ -262,7 +262,7 @@ class ExerciseLink extends AbstractLink
         }
 
         $exercise = new Exercise($courseId);
-        $exercise->read($exerciseData['id']);
+        $exercise->read($exerciseId);
 
         if (!$this->is_hp) {
             if ($exercise->exercise_was_added_in_lp == false) {
@@ -303,7 +303,7 @@ class ExerciseLink extends AbstractLink
                     ON (hp.exe_name = doc.path AND doc.c_id = hp.c_id)
                     WHERE
                         hp.c_id = $courseId AND                        
-                        doc.id = ".$exerciseId;
+                        doc.id = $exerciseId";
 
             if (!empty($stud_id)) {
                 $sql .= " AND hp.exe_user_id = $stud_id ";
@@ -315,7 +315,12 @@ class ExerciseLink extends AbstractLink
         if (isset($stud_id) && empty($type)) {
             // for 1 student
             if ($data = Database::fetch_array($scores)) {
-                $result = [$data['score'], $data['max_score']];
+                $attempts = Database::query($sql);
+                $counter = 0;
+                while ($attempt = Database::fetch_array($attempts)) {
+                    $counter++;
+                }
+                $result = [$data['score'], $data['max_score'], $data['exe_date'], $counter];
                 if ($cacheAvailable) {
                     $cacheDriver->save($key, $result);
                 }
@@ -357,11 +362,11 @@ class ExerciseLink extends AbstractLink
                     if ($data['max_score'] != 0) {
                         $students[$data['exe_user_id']] = $data['score'];
                         $student_count++;
-                        if ($data['score'] > $bestResult) {
-                            $bestResult = $data['score'];
+                        if ($data['exe_result'] > $bestResult) {
+                            $bestResult = $data['exe_result'];
                         }
                         $sum += $data['score'] / $data['max_score'];
-                        $sumResult += $data['score'];
+                        $sumResult += $data['exe_result'];
                         $weight = $data['max_score'];
                     }
                 }
@@ -500,9 +505,9 @@ class ExerciseLink extends AbstractLink
     {
         if ($this->is_hp == 1) {
             return 'HotPotatoes';
-        } else {
-            return get_lang('Quiz');
         }
+
+        return get_lang('Quiz');
     }
 
     public function needs_name_and_description()
@@ -550,58 +555,45 @@ class ExerciseLink extends AbstractLink
     {
         switch ($type) {
             case 'best':
-
                 break;
         }
     }
 
-    /**
-     * Lazy load function to get the database table of the exercise.
-     */
-    private function get_exercise_table()
-    {
-        $this->exercise_table = Database::get_course_table(TABLE_QUIZ_TEST);
-
-        return $this->exercise_table;
-    }
-
     /**
      * Lazy load function to get the database contents of this exercise.
      */
-    private function get_exercise_data()
+    public function get_exercise_data()
     {
         $tableItemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
         if ($this->is_hp == 1) {
             $table = Database::get_course_table(TABLE_DOCUMENT);
         } else {
-            $table = $this->get_exercise_table();
+            $table = Database::get_course_table(TABLE_QUIZ_TEST);
         }
 
         $exerciseId = $this->get_ref_id();
 
-        if ($table == '') {
-            return false;
-        } elseif (empty($this->exercise_data)) {
+        if (empty($this->exercise_data)) {
             if ($this->is_hp == 1) {
                 $sql = "SELECT * FROM $table ex
-                        INNER JOIN $tableItemProperty ip
-                        ON (ip.ref = ex.id AND ip.c_id = ex.c_id)
-                        WHERE
-                            ip.c_id = $this->course_id AND
-                            ex.c_id = $this->course_id AND
-                            ip.ref = $exerciseId AND
-                            ip.tool = '".TOOL_DOCUMENT."' AND
-                            ex.path LIKE '%htm%' AND
-                            ex.path LIKE '%HotPotatoes_files%' AND
-                            ip.visibility = 1";
+                    INNER JOIN $tableItemProperty ip
+                    ON (ip.ref = ex.id AND ip.c_id = ex.c_id)
+                    WHERE
+                        ip.c_id = $this->course_id AND
+                        ex.c_id = $this->course_id AND
+                        ip.ref = $exerciseId AND
+                        ip.tool = '".TOOL_DOCUMENT."' AND
+                        ex.path LIKE '%htm%' AND
+                        ex.path LIKE '%HotPotatoes_files%' AND
+                        ip.visibility = 1";
                 $result = Database::query($sql);
                 $this->exercise_data = Database::fetch_array($result);
             } else {
                 // Try with iid
                 $sql = 'SELECT * FROM '.$table.'
-                        WHERE
-                            c_id = '.$this->course_id.' AND
-                            iid = '.$exerciseId;
+                    WHERE
+                        c_id = '.$this->course_id.' AND
+                        iid = '.$exerciseId;
                 $result = Database::query($sql);
                 $rows = Database::num_rows($result);
 
@@ -610,15 +602,29 @@ class ExerciseLink extends AbstractLink
                 } else {
                     // Try wit id
                     $sql = 'SELECT * FROM '.$table.'
-                            WHERE
-                                c_id = '.$this->course_id.' AND
-                                id = '.$exerciseId;
+                        WHERE
+                            c_id = '.$this->course_id.' AND
+                            id = '.$exerciseId;
                     $result = Database::query($sql);
                     $this->exercise_data = Database::fetch_array($result);
                 }
             }
         }
 
+        if (empty($this->exercise_data)) {
+            return false;
+        }
+
         return $this->exercise_data;
     }
+
+    /**
+     * Lazy load function to get the database table of the exercise.
+     */
+    private function get_exercise_table()
+    {
+        $this->exercise_table = Database::get_course_table(TABLE_QUIZ_TEST);
+
+        return $this->exercise_table;
+    }
 }

+ 16 - 12
main/gradebook/lib/be/studentpublicationlink.class.php

@@ -34,17 +34,18 @@ class StudentPublicationLink extends AbstractLink
         // with the same title as the evaluation name
 
         $eval = $this->get_evaluation();
-        $stud_id = intval($stud_id);
+        $stud_id = (int) $stud_id;
         $itemProperty = $this->get_itemprop_table();
         $workTable = $this->get_studpub_table();
         $courseId = $this->course_id;
 
         $sql = "SELECT pub.url
-                FROM $itemProperty prop INNER JOIN $workTable pub
+                FROM $itemProperty prop 
+                INNER JOIN $workTable pub
                 ON (prop.c_id = pub.c_id AND prop.ref = pub.id)
                 WHERE
-                    prop.c_id = ".$courseId." AND
-                    pub.c_id = ".$courseId." AND
+                    prop.c_id = $courseId AND
+                    pub.c_id = $courseId AND
                     prop.tool = 'work' AND 
                     prop.insert_user_id = $stud_id AND                     
                     pub.title = '".Database::escape_string($eval->get_name())."' AND 
@@ -82,7 +83,8 @@ class StudentPublicationLink extends AbstractLink
             return [];
         }
         $em = Database::getManager();
-        $session = $em->find('ChamiloCoreBundle:Session', api_get_session_id());
+        $sessionId = $this->get_session_id();
+        $session = $em->find('ChamiloCoreBundle:Session', $sessionId);
         /*
         if (empty($session_id)) {
             $session_condition = api_get_session_condition(0, true);
@@ -128,7 +130,7 @@ class StudentPublicationLink extends AbstractLink
         $id = $data['id'];
 
         $em = Database::getManager();
-        $session = $em->find('ChamiloCoreBundle:Session', api_get_session_id());
+        $session = $em->find('ChamiloCoreBundle:Session', $this->get_session_id());
         $results = $em
             ->getRepository('ChamiloCourseBundle:CStudentPublication')
             ->findBy([
@@ -155,7 +157,7 @@ class StudentPublicationLink extends AbstractLink
             return [];
         }
         $id = $data['id'];
-        $session = $em->find('ChamiloCoreBundle:Session', api_get_session_id());
+        $session = api_get_session_entity($this->get_session_id());
 
         $assignment = $em
             ->getRepository('ChamiloCourseBundle:CStudentPublication')
@@ -225,7 +227,7 @@ class StudentPublicationLink extends AbstractLink
         // for 1 student
         if (!empty($stud_id)) {
             if (!count($scores)) {
-                return '';
+                return [null, null];
             }
 
             $data = $scores[0];
@@ -233,6 +235,8 @@ class StudentPublicationLink extends AbstractLink
             return [
                 $data->getQualification(),
                 $assignment->getQualification(),
+                api_get_local_time($assignment->getDateOfQualification()),
+                1,
             ];
         }
 
@@ -261,7 +265,7 @@ class StudentPublicationLink extends AbstractLink
         }
 
         if ($rescount == 0) {
-            return null;
+            return [null, null];
         }
 
         switch ($type) {
@@ -302,8 +306,8 @@ class StudentPublicationLink extends AbstractLink
 
     public function get_link()
     {
-        $session_id = api_get_session_id();
-        $url = api_get_path(WEB_PATH).'main/work/work.php?'.api_get_cidreq_params($this->get_course_code(), $session_id).'&id='.$this->exercise_data['id'].'&gradebook=view';
+        $sessionId = $this->get_session_id();
+        $url = api_get_path(WEB_PATH).'main/work/work.php?'.api_get_cidreq_params($this->get_course_code(), $sessionId).'&id='.$this->exercise_data['id'].'&gradebook=view';
 
         return $url;
     }
@@ -329,7 +333,7 @@ class StudentPublicationLink extends AbstractLink
         $sql = 'SELECT count(id) FROM '.$this->get_studpub_table().'
                 WHERE 
                     c_id = "'.$this->course_id.'" AND 
-                    id = '.$id.'';
+                    id = '.$id;
         $result = Database::query($sql);
         $number = Database::fetch_row($result);
 

+ 0 - 135
main/gradebook/lib/fe/exportgradebook.php

@@ -90,141 +90,6 @@ a:active {text-decoration: none; font-weight : bold;  color : black;}
     return $printdata;
 }
 
-/**
- * This function get a content html for export inside a pdf file.
- *
- * @param   array   table headers
- * @param   array   table body
- * @param   array   pdf headers
- * @param   array   pdf footers
- */
-function export_pdf_attendance($headers_table, $data_table, $headers_pdf, $footers_pdf, $title_pdf)
-{
-    $mpdf = new mPDF('UTF-8', 'A4-L', '', '', 15, 10, 35, 20, 4, 2, 'L');
-    $mpdf->useOnlyCoreFonts = true;
-    $mpdf->mirrorMargins = 0;
-
-    // Use different Odd/Even headers and footers and mirror margins
-    if (is_array($headers_pdf)) {
-        // preparing headers pdf
-        $header = '
-            <table width="100%"  cellspacing="1" cellpadding="1" border="0" class="strong">
-            <tr>
-                <td ROWSPAN="3" style="text-align: left;" class="title">
-                    <img src="'.api_get_path(WEB_CSS_PATH).api_get_setting('stylesheets').'/images/header-logo.png">
-                </td>
-                <td  colspan="3">
-                    <h1>'.$title_pdf.'</h1>
-                </td>
-            <tr>
-                <td></td>
-                <td><strong>'.$headers_pdf[0][0].'</strong> </td><td> <strong>'.$headers_pdf[0][1].'</strong></td>
-                <td><strong>'.$headers_pdf[1][0].'</strong> </td><td> <strong>'.$headers_pdf[1][1].'</strong></td>
-
-            </tr>
-            <tr>
-                <td></td>
-                <td><strong>'.$headers_pdf[2][0].'</strong> </td><td> <strong>'.$headers_pdf[2][1].'</strong></td>
-                <td><strong>'.$headers_pdf[3][0].' </strong></td><td> <strong>'.$headers_pdf[3][1].'</strong></td>
-            </tr>
-            <tr>
-                <td></td><td></td>
-                <td><strong>'.$headers_pdf[4][0].'</strong></td><td> <strong>'.$headers_pdf[4][1].'</strong></td>
-                <td><strong>'.$headers_pdf[5][0].'</strong> </td><td> <strong>'.$headers_pdf[5][1].'</strong></td>
-            </tr>
-        </table>';
-    }
-
-    // preparing footer pdf
-    $footer = '<table width="100%" cellspacing="2" cellpadding="10" border="0">';
-    if (is_array($footers_pdf)) {
-        $footer .= '<tr>';
-        foreach ($footers_pdf as $foot_pdf) {
-            $footer .= '<td width="33%" style="text-align: center;">'.$foot_pdf.'</td>';
-        }
-        $footer .= '</tr>';
-    }
-    $footer .= '</table>';
-    $footer .= '<div align="right" style="font-weight: bold;">{PAGENO}/{nb}</div>';
-
-    // preparing content pdf
-    $css_file = api_get_path(SYS_CSS_PATH).'themes/'.api_get_setting('stylesheets').'/print.css';
-
-    if (file_exists($css_file)) {
-        $css = @file_get_contents($css_file);
-    } else {
-        $css = '';
-    }
-
-    if (count($data_table) > 30) {
-        $items_per_page = (count($data_table) / 2);
-    } else {
-        $items_per_page = count($data_table);
-    }
-
-    $count_pages = ceil(count($data_table) / $items_per_page);
-    $content_table = '';
-    for ($x = 0; $x < $count_pages; $x++) {
-        $content_table .= '<table width="100%" border="1" style="border-collapse:collapse">';
-        // header table
-        $content_table .= '<tr>';
-        $i = 0;
-        if (is_array($headers_table)) {
-            foreach ($headers_table as $head_table) {
-                if (!empty($head_table[0])) {
-                    $width = (!empty($head_table[1]) ? $head_table[1].'%' : '');
-                    $content_table .= '<th width="'.$width.'">'.$head_table[0].'</th>';
-                    $i++;
-                }
-            }
-        }
-        $content_table .= '</tr>';
-        // body table
-        if (is_array($data_table) && count($data_table) > 0) {
-            $offset = $x * $items_per_page;
-            $data_table = array_slice($data_table, $offset, count($data_table));
-            $i = 1;
-            $item = $offset + 1;
-            foreach ($data_table as $data) {
-                $content_table .= '<tr>';
-                $content_table .= '<td>'.($item < 10 ? '0'.$item : $item).'</td>';
-                foreach ($data as $key => $content) {
-                    if (isset($content)) {
-                        $key == 1 ? $align = 'align="left"' : $align = 'align="center"';
-                        $content_table .= '<td '.$align.' style="padding:4px;" >'.$content.'</td>';
-                    }
-                }
-                $content_table .= '</tr>';
-                $i++;
-                $item++;
-                if ($i > $items_per_page) {
-                    break;
-                }
-            }
-        } else {
-            $content_table .= '<tr colspan="'.$i.'"><td>'.get_lang('Empty').'</td></tr>';
-        }
-        $content_table .= '</table>';
-        if ($x < ($count_pages - 1)) {
-            $content_table .= '<pagebreak />';
-        }
-    }
-    $html = $content_table;
-
-    // set attributes for pdf
-    $mpdf->SetHTMLHeader($header);
-    $mpdf->SetHTMLFooter($footer);
-    if (!empty($css)) {
-        $mpdf->WriteHTML($css, 1);
-        $mpdf->WriteHTML($html, 2);
-    } else {
-        $mpdf->WriteHTML($html);
-    }
-    $mpdf->Output(api_replace_dangerous_char($title_pdf.'.pdf'), 'D');
-
-    exit;
-}
-
 /**
  * This function get a content html for export inside a pdf file.
  *

+ 11 - 10
main/gradebook/lib/fe/gradebooktable.class.php

@@ -483,7 +483,6 @@ class GradebookTable extends SortableTable
                     }
 
                     // Students get the results and certificates columns
-
                     $value_data = isset($data[4]) ? $data[4] : null;
                     $best = isset($data['best']) ? $data['best'] : null;
                     $average = isset($data['average']) ? $data['average'] : null;
@@ -497,15 +496,17 @@ class GradebookTable extends SortableTable
                     $totalUserResult[0] += $totalResult[0] / ($totalResult[1] ?: 1) * $data[3];
                     $totalUserResult[1] += $data[3];
 
-                    $totalBest = [
-                        $scoredisplay->format_score($totalBest[0] + $data['best_score'][0]),
-                        $scoredisplay->format_score($totalBest[1] + $data['best_score'][1]),
-                    ];
-
-                    $totalAverage = [
-                        $data['average_score'][0],
-                        $data['average_score'][1],
-                    ];
+                    if (empty($model)) {
+                        $totalBest = [
+                            $scoredisplay->format_score($totalBest[0] + $data['best_score'][0]),
+                            $scoredisplay->format_score($totalBest[1] + $data['best_score'][1]),
+                        ];
+
+                        $totalAverage = [
+                            $data['average_score'][0],
+                            $data['average_score'][1],
+                        ];
+                    }
 
                     // Student result
                     if (empty($model)) {

+ 2 - 2
main/gradebook/lib/flatview_data_generator.class.php

@@ -460,8 +460,6 @@ class FlatViewDataGenerator
 
                     if (api_get_setting('gradebook_detailed_admin_view') === 'true') {
                         $links = $sub_cat->get_links();
-                        $evaluations = $sub_cat->get_evaluations();
-
                         /** @var ExerciseLink $link */
                         $linkScoreList = [];
                         foreach ($links as $link) {
@@ -472,7 +470,9 @@ class FlatViewDataGenerator
                             );
                         }
 
+                        $evaluations = $sub_cat->get_evaluations();
                         $evalScoreList = [];
+                        /** @var Evaluation $evaluation */
                         foreach ($evaluations as $evaluation) {
                             $evalScore = $evaluation->calc_score($user_id);
                             $evalScoreList[] = $scoreDisplay->display_score(

+ 0 - 2
main/inc/lib/template.lib.php

@@ -1501,8 +1501,6 @@ class Template
                 $this->assign('footer_extra_content', $extra_footer);
             }
         }
-
-        // Tutor name
     }
 
     /**