Browse Source

Minor - Flint fixes + remove var_dump

Angel Fernando Quiroz Campos 5 years ago
parent
commit
cf32a6aa47
1 changed files with 1347 additions and 1347 deletions
  1. 1347 1347
      main/exercise/exercise.class.php

+ 1347 - 1347
main/exercise/exercise.class.php

@@ -7853,7 +7853,6 @@ class Exercise
 
     /**
      * @param int $value
-     *
      */
     public function setExerciseCategoryId($value)
     {
@@ -8170,1519 +8169,1520 @@ class Exercise
     }
 
     /**
-     * Gets the question list ordered by the question_order setting (drag and drop).
+     * @param int $categoryId
+     * @param int $page
+     * @param int $from
+     * @param int $limit
      *
-     * @return array
+     * @throws \Doctrine\ORM\Query\QueryException
+     *
+     * @return string
      */
-    private function getQuestionOrderedList()
+    public static function exerciseGrid($categoryId, $page, $from, $limit)
     {
-        $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
-        $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
+        $TBL_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
+        $TBL_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
+        $TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
+        $TBL_EXERCISES = Database::get_course_table(TABLE_QUIZ_TEST);
+        $TBL_TRACK_EXERCISES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
-        // Getting question_order to verify that the question
-        // list is correct and all question_order's were set
-        $sql = "SELECT DISTINCT count(e.question_order) as count
-                FROM $TBL_EXERCICE_QUESTION e
-                INNER JOIN $TBL_QUESTIONS q
-                ON (e.question_id = q.id AND e.c_id = q.c_id)
-                WHERE
-                  e.c_id = {$this->course_id} AND
-                  e.exercice_id	= ".$this->id;
+        $categoryId = (int) $categoryId;
+        $page = (int) $page;
+        $from = (int) $from;
+        $limit = (int) $limit;
 
-        $result = Database::query($sql);
-        $row = Database::fetch_array($result);
-        $count_question_orders = $row['count'];
+        $autoLaunchAvailable = false;
+        if (api_get_course_setting('enable_exercise_auto_launch') == 1 &&
+            api_get_configuration_value('allow_exercise_auto_launch')
+        ) {
+            $autoLaunchAvailable = true;
+        }
 
-        // Getting question list from the order (question list drag n drop interface).
-        $sql = "SELECT DISTINCT e.question_id, e.question_order
-                FROM $TBL_EXERCICE_QUESTION e
-                INNER JOIN $TBL_QUESTIONS q
-                ON (e.question_id = q.id AND e.c_id = q.c_id)
-                WHERE
-                    e.c_id = {$this->course_id} AND
-                    e.exercice_id = '".$this->id."'
-                ORDER BY question_order";
-        $result = Database::query($sql);
+        $is_allowedToEdit = api_is_allowed_to_edit(null, true);
+        $courseInfo = api_get_course_info();
+        $sessionId = api_get_session_id();
+        $courseId = $courseInfo['real_id'];
+        $tableRows = [];
+        $uploadPath = DIR_HOTPOTATOES; //defined in main_api
+        $exercisePath = api_get_self();
+        $origin = api_get_origin();
+        $userInfo = api_get_user_info();
+        $charset = 'utf-8';
+        $token = Security::get_token();
+        $userId = api_get_user_id();
+        $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
+            $userId,
+            $courseInfo
+        );
+        $documentPath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
 
-        // Fills the array with the question ID for this exercise
-        // the key of the array is the question position
-        $temp_question_list = [];
-        $counter = 1;
-        $questionList = [];
-        while ($new_object = Database::fetch_object($result)) {
-            // Correct order.
-            $questionList[$new_object->question_order] = $new_object->question_id;
-            // Just in case we save the order in other array
-            $temp_question_list[$counter] = $new_object->question_id;
-            $counter++;
-        }
+        $limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
 
-        if (!empty($temp_question_list)) {
-            /* If both array don't match it means that question_order was not correctly set
-               for all questions using the default mysql order */
-            if (count($temp_question_list) != $count_question_orders) {
-                $questionList = $temp_question_list;
-            }
-        }
+        $learnpath_id = isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : null;
+        $learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? (int) $_REQUEST['learnpath_item_id'] : null;
 
-        return $questionList;
-    }
+        // Condition for the session
+        $condition_session = api_get_session_condition($sessionId, true, true);
+        $content = '';
 
-    /**
-     * Select N values from the questions per category array.
-     *
-     * @param array $categoriesAddedInExercise
-     * @param array $question_list
-     * @param array $questions_by_category     per category
-     * @param bool  $flatResult
-     * @param bool  $randomizeQuestions
-     *
-     * @return array
-     */
-    private function pickQuestionsPerCategory(
-        $categoriesAddedInExercise,
-        $question_list,
-        &$questions_by_category,
-        $flatResult = true,
-        $randomizeQuestions = false
-    ) {
-        $addAll = true;
-        $categoryCountArray = [];
+        $categoryCondition = '';
+        if (!empty($categoryId)) {
+            $categoryCondition = " AND exercise_category_id = $categoryId ";
+        }
 
-        // Getting how many questions will be selected per category.
-        if (!empty($categoriesAddedInExercise)) {
-            $addAll = false;
-            // Parsing question according the category rel exercise settings
-            foreach ($categoriesAddedInExercise as $category_info) {
-                $category_id = $category_info['category_id'];
-                if (isset($questions_by_category[$category_id])) {
-                    // How many question will be picked from this category.
-                    $count = $category_info['count_questions'];
-                    // -1 means all questions
-                    $categoryCountArray[$category_id] = $count;
-                    if ($count == -1) {
-                        $categoryCountArray[$category_id] = 999;
-                    }
-                }
-            }
+        // Only for administrators
+        if ($is_allowedToEdit) {
+            $total_sql = "SELECT count(iid) as count 
+                          FROM $TBL_EXERCISES
+                          WHERE 
+                                c_id = $courseId AND 
+                                active<>'-1' 
+                                $condition_session 
+                                $categoryCondition
+                                ";
+            $sql = "SELECT * FROM $TBL_EXERCISES
+                    WHERE c_id = $courseId AND active<>'-1' $condition_session $categoryCondition
+                    ORDER BY title
+                    LIMIT ".$from.",".$limit;
+        } else {
+            // Only for students
+            $total_sql = "SELECT count(iid) as count 
+                          FROM $TBL_EXERCISES
+                          WHERE c_id = $courseId AND active = '1' $condition_session $categoryCondition";
+            $sql = "SELECT * FROM $TBL_EXERCISES
+                    WHERE c_id = $courseId AND
+                          active='1' $condition_session
+                          $categoryCondition
+                    ORDER BY title LIMIT ".$from.",".$limit;
         }
+        $result = Database::query($sql);
+        $result_total = Database::query($total_sql);
 
-        if (!empty($questions_by_category)) {
-            $temp_question_list = [];
-            foreach ($questions_by_category as $category_id => &$categoryQuestionList) {
-                if (isset($categoryCountArray) && !empty($categoryCountArray)) {
-                    $numberOfQuestions = 0;
-                    if (isset($categoryCountArray[$category_id])) {
-                        $numberOfQuestions = $categoryCountArray[$category_id];
-                    }
-                }
+        $total_exercises = 0;
+        if (Database :: num_rows($result_total)) {
+            $result_total = Database::fetch_array($result_total);
+            $total_exercises = $result_total['count'];
+        }
 
-                if ($addAll) {
-                    $numberOfQuestions = 999;
-                }
+        //get HotPotatoes files (active and inactive)
+        if ($is_allowedToEdit) {
+            $sql = "SELECT * FROM $TBL_DOCUMENT
+                    WHERE
+                        c_id = $courseId AND
+                        path LIKE '".Database::escape_string($uploadPath.'/%/%')."'";
+            $res = Database::query($sql);
+            $hp_count = Database :: num_rows($res);
+        } else {
+            $sql = "SELECT * FROM $TBL_DOCUMENT d 
+                    INNER JOIN $TBL_ITEM_PROPERTY ip
+                    ON (d.id = ip.ref AND d.c_id = ip.c_id) 
+                    WHERE                
+                        ip.tool = '".TOOL_DOCUMENT."' AND
+                        d.path LIKE '".Database::escape_string($uploadPath.'/%/%')."' AND
+                        ip.visibility ='1' AND
+                        d.c_id = $courseId AND
+                        ip.c_id  = $courseId";
+            $res = Database::query($sql);
+            $hp_count = Database::num_rows($res);
+        }
 
-                if (!empty($numberOfQuestions)) {
-                    $elements = TestCategory::getNElementsFromArray(
-                        $categoryQuestionList,
-                        $numberOfQuestions,
-                        $randomizeQuestions
-                    );
+        $total = $total_exercises + $hp_count;
 
-                    if (!empty($elements)) {
-                        $temp_question_list[$category_id] = $elements;
-                        $categoryQuestionList = $elements;
-                    }
-                }
+        if ($total > $limit) {
+            $content .= '<div style="float:right;height:20px;">';
+            // Show pages navigation link for previous page
+            if ($page) {
+                $content .= "<a href=\"".api_get_self()."?".api_get_cidreq()."&page=".($page - 1)."\">".
+                    Display::return_icon('action_prev.png', get_lang('PreviousPage')).'</a>';
+            } elseif ($total_exercises + $hp_count > $limit) {
+                $content .= Display::return_icon('action_prev_na.png', get_lang('PreviousPage'));
             }
 
-            if (!empty($temp_question_list)) {
-                if ($flatResult) {
-                    $temp_question_list = array_flatten($temp_question_list);
-                }
-                $question_list = $temp_question_list;
+            // Show pages navigation link for previous page
+            if ($total_exercises > $from + $limit || $hp_count > $from + $limit) {
+                $content .= ' '."<a href=\"".api_get_self()."?".api_get_cidreq()."&page=".($page + 1)."\">".
+                    Display::return_icon('action_next.png', get_lang('NextPage')).'</a>';
+            } elseif ($page) {
+                $content .= ' '.Display::return_icon('action_next_na.png', get_lang('NextPage'));
             }
+            $content .= '</div>';
         }
 
-        return $question_list;
-    }
-
-    /**
-     * Changes the exercise id.
-     *
-     * @param int $id - exercise id
-     */
-    private function updateId($id)
-    {
-        $this->id = $id;
-    }
+        $exerciseList = [];
+        $list_ordered = null;
+        while ($row = Database::fetch_array($result, 'ASSOC')) {
+            $exerciseList[$row['iid']] = $row;
+        }
 
-    /**
-     * Sends a notification when a user ends an examn.
-     *
-     * @param array  $question_list_answers
-     * @param string $origin
-     * @param array  $user_info
-     * @param string $url_email
-     * @param array  $teachers
-     */
-    private function sendNotificationForOpenQuestions(
-        $question_list_answers,
-        $origin,
-        $user_info,
-        $url_email,
-        $teachers
-    ) {
-        // Email configuration settings
-        $courseCode = api_get_course_id();
-        $courseInfo = api_get_course_info($courseCode);
-        $sessionId = api_get_session_id();
-        $sessionData = '';
-        if (!empty($sessionId)) {
-            $sessionInfo = api_get_session_info($sessionId);
-            if (!empty($sessionInfo)) {
-                $sessionData = '<tr>'
-                    .'<td><em>'.get_lang('SessionName').'</em></td>'
-                    .'<td>&nbsp;<b>'.$sessionInfo['name'].'</b></td>'
-                    .'</tr>';
-            }
-        }
-
-        $msg = get_lang('OpenQuestionsAttempted').'<br /><br />'
-            .get_lang('AttemptDetails').' : <br /><br />'
-            .'<table>'
-            .'<tr>'
-            .'<td><em>'.get_lang('CourseName').'</em></td>'
-            .'<td>&nbsp;<b>#course#</b></td>'
-            .'</tr>'
-            .$sessionData
-            .'<tr>'
-            .'<td>'.get_lang('TestAttempted').'</td>'
-            .'<td>&nbsp;#exercise#</td>'
-            .'</tr>'
-            .'<tr>'
-            .'<td>'.get_lang('StudentName').'</td>'
-            .'<td>&nbsp;#firstName# #lastName#</td>'
-            .'</tr>'
-            .'<tr>'
-            .'<td>'.get_lang('StudentEmail').'</td>'
-            .'<td>&nbsp;#mail#</td>'
-            .'</tr>'
-            .'</table>';
-
-        $open_question_list = null;
-        foreach ($question_list_answers as $item) {
-            $question = $item['question'];
-            $answer = $item['answer'];
-            $answer_type = $item['answer_type'];
-
-            if (!empty($question) && !empty($answer) && $answer_type == FREE_ANSWER) {
-                $open_question_list .=
-                    '<tr>'
-                    .'<td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Question').'</td>'
-                    .'<td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>'
-                    .'</tr>'
-                    .'<tr>'
-                    .'<td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Answer').'</td>'
-                    .'<td valign="top" bgcolor="#F3F3F3">'.$answer.'</td>'
-                    .'</tr>';
-            }
-        }
-
-        if (!empty($open_question_list)) {
-            $msg .= '<p><br />'.get_lang('OpenQuestionsAttemptedAre').' :</p>'.
-                '<table width="730" height="136" border="0" cellpadding="3" cellspacing="3">';
-            $msg .= $open_question_list;
-            $msg .= '</table><br />';
-
-            $msg = str_replace('#exercise#', $this->exercise, $msg);
-            $msg = str_replace('#firstName#', $user_info['firstname'], $msg);
-            $msg = str_replace('#lastName#', $user_info['lastname'], $msg);
-            $msg = str_replace('#mail#', $user_info['email'], $msg);
-            $msg = str_replace(
-                '#course#',
-                Display::url($courseInfo['title'], $courseInfo['course_public_url'].'?id_session='.$sessionId),
-                $msg
-            );
-
-            if ($origin != 'learnpath') {
-                $msg .= '<br /><a href="#url#">'.get_lang('ClickToCommentAndGiveFeedback').'</a>';
-            }
-            $msg = str_replace('#url#', $url_email, $msg);
-            $subject = get_lang('OpenQuestionsAttempted');
-
-            if (!empty($teachers)) {
-                foreach ($teachers as $user_id => $teacher_data) {
-                    MessageManager::send_message_simple(
-                        $user_id,
-                        $subject,
-                        $msg
-                    );
-                }
-            }
-        }
-    }
-
-    /**
-     * Send notification for oral questions.
-     *
-     * @param array  $question_list_answers
-     * @param string $origin
-     * @param int    $exe_id
-     * @param array  $user_info
-     * @param string $url_email
-     * @param array  $teachers
-     */
-    private function sendNotificationForOralQuestions(
-        $question_list_answers,
-        $origin,
-        $exe_id,
-        $user_info,
-        $url_email,
-        $teachers
-    ) {
-        // Email configuration settings
-        $courseCode = api_get_course_id();
-        $courseInfo = api_get_course_info($courseCode);
-        $oral_question_list = null;
-        foreach ($question_list_answers as $item) {
-            $question = $item['question'];
-            $file = $item['generated_oral_file'];
-            $answer = $item['answer'];
-            if ($answer == 0) {
-                $answer = '';
-            }
-            $answer_type = $item['answer_type'];
-            if (!empty($question) && (!empty($answer) || !empty($file)) && $answer_type == ORAL_EXPRESSION) {
-                if (!empty($file)) {
-                    $file = Display::url($file, $file);
+        if (!empty($exerciseList) &&
+            api_get_setting('exercise_invisible_in_session') === 'true'
+        ) {
+            if (!empty($sessionId)) {
+                $changeDefaultVisibility = true;
+                if (api_get_setting('configure_exercise_visibility_in_course') === 'true') {
+                    $changeDefaultVisibility = false;
+                    if (api_get_course_setting('exercise_invisible_in_session') == 1) {
+                        $changeDefaultVisibility = true;
+                    }
                 }
-                $oral_question_list .= '<br />
-                    <table width="730" height="136" border="0" cellpadding="3" cellspacing="3">
-                    <tr>
-                        <td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Question').'</td>
-                        <td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>
-                    </tr>
-                    <tr>
-                        <td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Answer').'</td>
-                        <td valign="top" bgcolor="#F3F3F3">'.$answer.$file.'</td>
-                    </tr></table>';
-            }
-        }
-
-        if (!empty($oral_question_list)) {
-            $msg = get_lang('OralQuestionsAttempted').'<br /><br />
-                    '.get_lang('AttemptDetails').' : <br /><br />
-                    <table>
-                        <tr>
-                            <td><em>'.get_lang('CourseName').'</em></td>
-                            <td>&nbsp;<b>#course#</b></td>
-                        </tr>
-                        <tr>
-                            <td>'.get_lang('TestAttempted').'</td>
-                            <td>&nbsp;#exercise#</td>
-                        </tr>
-                        <tr>
-                            <td>'.get_lang('StudentName').'</td>
-                            <td>&nbsp;#firstName# #lastName#</td>
-                        </tr>
-                        <tr>
-                            <td>'.get_lang('StudentEmail').'</td>
-                            <td>&nbsp;#mail#</td>
-                        </tr>
-                    </table>';
-            $msg .= '<br />'.sprintf(get_lang('OralQuestionsAttemptedAreX'), $oral_question_list).'<br />';
-            $msg1 = str_replace("#exercise#", $this->exercise, $msg);
-            $msg = str_replace("#firstName#", $user_info['firstname'], $msg1);
-            $msg1 = str_replace("#lastName#", $user_info['lastname'], $msg);
-            $msg = str_replace("#mail#", $user_info['email'], $msg1);
-            $msg = str_replace("#course#", $courseInfo['name'], $msg1);
 
-            if (!in_array($origin, ['learnpath', 'embeddable'])) {
-                $msg .= '<br /><a href="#url#">'.get_lang('ClickToCommentAndGiveFeedback').'</a>';
-            }
-            $msg1 = str_replace("#url#", $url_email, $msg);
-            $mail_content = $msg1;
-            $subject = get_lang('OralQuestionsAttempted');
+                if ($changeDefaultVisibility) {
+                    // Check exercise
+                    foreach ($exerciseList as $exercise) {
+                        if ($exercise['session_id'] == 0) {
+                            $visibilityInfo = api_get_item_property_info(
+                                $courseId,
+                                TOOL_QUIZ,
+                                $exercise['iid'],
+                                $sessionId
+                            );
 
-            if (!empty($teachers)) {
-                foreach ($teachers as $user_id => $teacher_data) {
-                    MessageManager::send_message_simple(
-                        $user_id,
-                        $subject,
-                        $mail_content
-                    );
+                            if (empty($visibilityInfo)) {
+                                // Create a record for this
+                                api_item_property_update(
+                                    $courseInfo,
+                                    TOOL_QUIZ,
+                                    $exercise['iid'],
+                                    'invisible',
+                                    api_get_user_id(),
+                                    0,
+                                    null,
+                                    '',
+                                    '',
+                                    $sessionId
+                                );
+                            }
+                        }
+                    }
                 }
             }
         }
-    }
 
-    /**
-     * Returns an array with the media list.
-     *
-     * @param array question list
-     *
-     * @example there's 1 question with iid 5 that belongs to the media question with iid = 100
-     * <code>
-     * array (size=2)
-     *  999 =>
-     *    array (size=3)
-     *      0 => int 7
-     *      1 => int 6
-     *      2 => int 3254
-     *  100 =>
-     *   array (size=1)
-     *      0 => int 5
-     *  </code>
-     */
-    private function setMediaList($questionList)
-    {
-        $mediaList = [];
-        /*
-         * Media feature is not activated in 1.11.x
-        if (!empty($questionList)) {
-            foreach ($questionList as $questionId) {
-                $objQuestionTmp = Question::read($questionId, $this->course_id);
-                // If a media question exists
-                if (isset($objQuestionTmp->parent_id) && $objQuestionTmp->parent_id != 0) {
-                    $mediaList[$objQuestionTmp->parent_id][] = $objQuestionTmp->id;
-                } else {
-                    // Always the last item
-                    $mediaList[999][] = $objQuestionTmp->id;
+        if (isset($list_ordered) && !empty($list_ordered)) {
+            $new_question_list = [];
+            foreach ($list_ordered as $exercise_id) {
+                if (isset($exerciseList[$exercise_id])) {
+                    $new_question_list[] = $exerciseList[$exercise_id];
                 }
             }
-        }*/
-
-        $this->mediaList = $mediaList;
-    }
-
-    /**
-     * @param FormValidator $form
-     *
-     * @return HTML_QuickForm_group
-     */
-    private function setResultDisabledGroup(FormValidator $form)
-    {
-        $resultDisabledGroup = [];
-
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('ShowScoreAndRightAnswer'),
-            '0',
-            ['id' => 'result_disabled_0']
-        );
-
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('DoNotShowScoreNorRightAnswer'),
-            '1',
-            ['id' => 'result_disabled_1', 'onclick' => 'check_results_disabled()']
-        );
-
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('OnlyShowScore'),
-            '2',
-            ['id' => 'result_disabled_2', 'onclick' => 'check_results_disabled()']
-        );
+            $exerciseList = $new_question_list;
+        }
 
-        if ($this->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
-            $group = $form->addGroup(
-                $resultDisabledGroup,
-                null,
-                get_lang('ShowResultsToStudents')
-            );
+        if (!empty($exerciseList)) {
+            if ($origin !== 'learnpath') {
+                //avoid sending empty parameters
+                $mylpid = empty($learnpath_id) ? '' : '&learnpath_id='.$learnpath_id;
+                $mylpitemid = empty($learnpath_item_id) ? '' : '&learnpath_item_id='.$learnpath_item_id;
+                foreach ($exerciseList as $row) {
+                    $my_exercise_id = $row['id'];
+                    $exercise = new Exercise();
+                    $exercise->read($my_exercise_id, false);
 
-            return $group;
-        }
+                    if (empty($exercise->id)) {
+                        continue;
+                    }
 
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('ShowScoreEveryAttemptShowAnswersLastAttempt'),
-            '4',
-            ['id' => 'result_disabled_4']
-        );
+                    $locked = $exercise->is_gradebook_locked;
+                    // Validation when belongs to a session
+                    $session_img = api_get_session_image($row['session_id'], $userInfo['status']);
 
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('DontShowScoreOnlyWhenUserFinishesAllAttemptsButShowFeedbackEachAttempt'),
-            '5',
-            ['id' => 'result_disabled_5', 'onclick' => 'check_results_disabled()']
-        );
+                    $time_limits = false;
+                    if (!empty($row['start_time']) || !empty($row['end_time'])) {
+                        $time_limits = true;
+                    }
 
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('ExerciseRankingMode'),
-            RESULT_DISABLE_RANKING,
-            ['id' => 'result_disabled_6']
-        );
+                    $is_actived_time = false;
+                    if ($time_limits) {
+                        // check if start time
+                        $start_time = false;
+                        if (!empty($row['start_time'])) {
+                            $start_time = api_strtotime($row['start_time'], 'UTC');
+                        }
+                        $end_time = false;
+                        if (!empty($row['end_time'])) {
+                            $end_time = api_strtotime($row['end_time'], 'UTC');
+                        }
+                        $now = time();
 
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('ExerciseShowOnlyGlobalScoreAndCorrectAnswers'),
-            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
-            ['id' => 'result_disabled_7']
-        );
+                        //If both "clocks" are enable
+                        if ($start_time && $end_time) {
+                            if ($now > $start_time && $end_time > $now) {
+                                $is_actived_time = true;
+                            }
+                        } else {
+                            //we check the start and end
+                            if ($start_time) {
+                                if ($now > $start_time) {
+                                    $is_actived_time = true;
+                                }
+                            }
+                            if ($end_time) {
+                                if ($end_time > $now) {
+                                    $is_actived_time = true;
+                                }
+                            }
+                        }
+                    }
 
-        $resultDisabledGroup[] = $form->createElement(
-            'radio',
-            'results_disabled',
-            null,
-            get_lang('ExerciseAutoEvaluationAndRankingMode'),
-            RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-            ['id' => 'result_disabled_8']
-        );
+                    // Blocking empty start times see BT#2800
+                    global $_custom;
+                    if (isset($_custom['exercises_hidden_when_no_start_date']) &&
+                        $_custom['exercises_hidden_when_no_start_date']
+                    ) {
+                        if (empty($row['start_time'])) {
+                            $time_limits = true;
+                            $is_actived_time = false;
+                        }
+                    }
 
-        $group = $form->addGroup(
-            $resultDisabledGroup,
-            null,
-            get_lang('ShowResultsToStudents')
-        );
+                    $cut_title = $exercise->getCutTitle();
+                    $alt_title = '';
+                    if ($cut_title != $row['title']) {
+                        $alt_title = ' title = "'.$exercise->getUnformattedTitle().'" ';
+                    }
 
-        return $group;
-    }
+                    // Teacher only
+                    if ($is_allowedToEdit) {
+                        $lp_blocked = null;
+                        if ($exercise->exercise_was_added_in_lp == true) {
+                            $lp_blocked = Display::div(
+                                get_lang('AddedToLPCannotBeAccessed'),
+                                ['class' => 'lp_content_type_label']
+                            );
+                        }
 
-    /**
-     * @param int $categoryId
-     * @param int $page
-     * @param int $from
-     * @param int $limit
-     *
-     * @return string
-     * @throws \Doctrine\ORM\Query\QueryException
-     */
-    public static function exerciseGrid($categoryId, $page, $from, $limit)
-    {
-        $TBL_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
-        $TBL_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
-        $TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
-        $TBL_EXERCISES = Database::get_course_table(TABLE_QUIZ_TEST);
-        $TBL_TRACK_EXERCISES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
+                        $visibility = api_get_item_visibility(
+                            $courseInfo,
+                            TOOL_QUIZ,
+                            $my_exercise_id,
+                            0
+                        );
 
-        $categoryId = (int) $categoryId;
-        $page = (int) $page;
-        $from = (int) $from;
-        $limit = (int) $limit;
+                        if (!empty($sessionId)) {
+                            $setting = api_get_configuration_value('show_hidden_exercise_added_to_lp');
+                            if ($setting) {
+                                if ($exercise->exercise_was_added_in_lp == false) {
+                                    if ($visibility == 0) {
+                                        continue;
+                                    }
+                                }
+                            } else {
+                                if ($visibility == 0) {
+                                    continue;
+                                }
+                            }
 
-        $autoLaunchAvailable = false;
-        if (api_get_course_setting('enable_exercise_auto_launch') == 1 &&
-            api_get_configuration_value('allow_exercise_auto_launch')
-        ) {
-            $autoLaunchAvailable = true;
-        }
+                            $visibility = api_get_item_visibility(
+                                $courseInfo,
+                                TOOL_QUIZ,
+                                $my_exercise_id,
+                                $sessionId
+                            );
+                        }
 
-        $is_allowedToEdit = api_is_allowed_to_edit(null, true);
-        $courseInfo = api_get_course_info();
-        $sessionId = api_get_session_id();
-        $courseId = $courseInfo['real_id'];
-        $tableRows = [];
-        $uploadPath = DIR_HOTPOTATOES; //defined in main_api
-        $exercisePath = api_get_self();
-        $origin = api_get_origin();
-        $userInfo = api_get_user_info();
-        $charset = 'utf-8';
-        $token = Security::get_token();
-        $userId = api_get_user_id();
-        $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
-            $userId,
-            $courseInfo
-        );
-        $documentPath = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/document';
+                        if ($row['active'] == 0 || $visibility == 0) {
+                            $title = Display::tag('font', $cut_title, ['style' => 'color:grey']);
+                        } else {
+                            $title = $cut_title;
+                        }
 
-        $limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
+                        $count_exercise_not_validated = (int) Event::count_exercise_result_not_validated(
+                            $my_exercise_id,
+                            $courseId,
+                            $sessionId
+                        );
 
-        $learnpath_id = isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : null;
-        $learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? (int) $_REQUEST['learnpath_item_id'] : null;
+                        $move = Display::return_icon(
+                            'all_directions.png',
+                            get_lang('Move'),
+                            ['class' => 'moved', 'style' => 'margin-bottom:-0.5em;']
+                        );
+                        $move = null;
+                        $class_tip = '';
 
-        // Condition for the session
-        $condition_session = api_get_session_condition($sessionId, true, true);
-        $content = '';
+                        if (!empty($count_exercise_not_validated)) {
+                            $results_text = $count_exercise_not_validated == 1 ? get_lang('ResultNotRevised') : get_lang('ResultsNotRevised');
+                            $title .= '<span class="exercise_tooltip" style="display: none;">'.$count_exercise_not_validated.' '.$results_text.' </span>';
+                            $class_tip = 'link_tooltip';
+                        }
 
-        $categoryCondition = '';
-        if (!empty($categoryId)) {
-            $categoryCondition = " AND exercise_category_id = $categoryId ";
-        }
+                        $url = $move.'<a '.$alt_title.' class="'.$class_tip.'" id="tooltip_'.$row['id'].'" href="overview.php?'.api_get_cidreq().$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">
+                             '.Display::return_icon('quiz.png', $row['title']).'
+                             '.$title.' </a>'.PHP_EOL;
 
-        // Only for administrators
-        if ($is_allowedToEdit) {
-            $total_sql = "SELECT count(iid) as count 
-                          FROM $TBL_EXERCISES
-                          WHERE 
-                                c_id = $courseId AND 
-                                active<>'-1' 
-                                $condition_session 
-                                $categoryCondition
-                                ";
-            $sql = "SELECT * FROM $TBL_EXERCISES
-                    WHERE c_id = $courseId AND active<>'-1' $condition_session $categoryCondition
-                    ORDER BY title
-                    LIMIT ".$from.",".$limit;
-        } else {
-            // Only for students
-            $total_sql = "SELECT count(iid) as count 
-                          FROM $TBL_EXERCISES
-                          WHERE c_id = $courseId AND active = '1' $condition_session $categoryCondition";
-            $sql = "SELECT * FROM $TBL_EXERCISES
-                    WHERE c_id = $courseId AND
-                          active='1' $condition_session
-                          $categoryCondition
-                    ORDER BY title LIMIT ".$from.",".$limit;
-        }
-        $result = Database::query($sql);
-        $result_total = Database::query($total_sql);
+                        if (ExerciseLib::isQuizEmbeddable($row)) {
+                            $embeddableIcon = Display::return_icon('om_integration.png', get_lang('ThisQuizCanBeEmbeddable'));
+                            $url .= Display::div($embeddableIcon, ['class' => 'pull-right']);
+                        }
 
-        $total_exercises = 0;
-        if (Database :: num_rows($result_total)) {
-            $result_total = Database::fetch_array($result_total);
-            $total_exercises = $result_total['count'];
-        }
+                        $item = Display::tag('td', $url.' '.$session_img.$lp_blocked);
 
-        //get HotPotatoes files (active and inactive)
-        if ($is_allowedToEdit) {
-            $sql = "SELECT * FROM $TBL_DOCUMENT
-                    WHERE
-                        c_id = $courseId AND
-                        path LIKE '".Database::escape_string($uploadPath.'/%/%')."'";
-            $res = Database::query($sql);
-            $hp_count = Database :: num_rows($res);
-        } else {
-            $sql = "SELECT * FROM $TBL_DOCUMENT d 
-                    INNER JOIN $TBL_ITEM_PROPERTY ip
-                    ON (d.id = ip.ref AND d.c_id = ip.c_id) 
-                    WHERE                
-                        ip.tool = '".TOOL_DOCUMENT."' AND
-                        d.path LIKE '".Database::escape_string($uploadPath.'/%/%')."' AND
-                        ip.visibility ='1' AND
-                        d.c_id = $courseId AND
-                        ip.c_id  = $courseId";
-            $res = Database::query($sql);
-            $hp_count = Database::num_rows($res);
-        }
+                        // Count number exercise - teacher
+                        $sql = "SELECT count(*) count FROM $TBL_EXERCISE_QUESTION
+                        WHERE c_id = $courseId AND exercice_id = $my_exercise_id";
+                        $sqlresult = Database::query($sql);
+                        $rowi = (int) Database::result($sqlresult, 0, 0);
 
-        $total = $total_exercises + $hp_count;
+                        if ($sessionId == $row['session_id']) {
+                            // Questions list
+                            $actions = Display::url(
+                                Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL),
+                                'admin.php?'.api_get_cidreq().'&exerciseId='.$row['id']
+                            );
 
-        if ($total > $limit) {
-            $content .= '<div style="float:right;height:20px;">';
-            // Show pages navigation link for previous page
-            if ($page) {
-                $content .= "<a href=\"".api_get_self()."?".api_get_cidreq()."&page=".($page - 1)."\">".
-                    Display::return_icon('action_prev.png', get_lang('PreviousPage')).'</a>';
-            } elseif ($total_exercises + $hp_count > $limit) {
-                $content .= Display::return_icon('action_prev_na.png', get_lang('PreviousPage'));
-            }
+                            // Test settings
+                            $settings = Display::url(
+                                Display::return_icon('settings.png', get_lang('Configure'), '', ICON_SIZE_SMALL),
+                                'exercise_admin.php?'.api_get_cidreq().'&exerciseId='.$row['id']
+                            );
 
-            // Show pages navigation link for previous page
-            if ($total_exercises > $from + $limit || $hp_count > $from + $limit) {
-                $content .= ' '."<a href=\"".api_get_self()."?".api_get_cidreq()."&page=".($page + 1)."\">".
-                    Display::return_icon('action_next.png', get_lang('NextPage')).'</a>';
-            } elseif ($page) {
-                $content .= ' '.Display::return_icon('action_next_na.png', get_lang('NextPage'));
-            }
-            $content .= '</div>';
-        }
+                            if ($limitTeacherAccess && !api_is_platform_admin()) {
+                                $settings = '';
+                            }
+                            $actions .= $settings;
 
-        $exerciseList = [];
-        $list_ordered = null;
-        while ($row = Database::fetch_array($result, 'ASSOC')) {
-            $exerciseList[$row['iid']] = $row;
-        }
+                            // Exercise results
+                            $resultsLink = '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
+                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+
+                            if ($limitTeacherAccess) {
+                                if (api_is_platform_admin()) {
+                                    $actions .= $resultsLink;
+                                }
+                            } else {
+                                // Exercise results
+                                $actions .= $resultsLink;
+                            }
 
-        if (!empty($exerciseList) &&
-            api_get_setting('exercise_invisible_in_session') === 'true'
-        ) {
-            if (!empty($sessionId)) {
-                $changeDefaultVisibility = true;
-                if (api_get_setting('configure_exercise_visibility_in_course') === 'true') {
-                    $changeDefaultVisibility = false;
-                    if (api_get_course_setting('exercise_invisible_in_session') == 1) {
-                        $changeDefaultVisibility = true;
-                    }
-                }
+                            // Auto launch
+                            if ($autoLaunchAvailable) {
+                                $autoLaunch = $exercise->getAutoLaunch();
+                                if (empty($autoLaunch)) {
+                                    $actions .= Display::url(
+                                        Display::return_icon(
+                                            'launch_na.png',
+                                            get_lang('Enable'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=enable_launch&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
+                                } else {
+                                    $actions .= Display::url(
+                                        Display::return_icon(
+                                            'launch.png',
+                                            get_lang('Disable'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=disable_launch&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
+                                }
+                            }
 
-                if ($changeDefaultVisibility) {
-                    // Check exercise
-                    foreach ($exerciseList as $exercise) {
-                        if ($exercise['session_id'] == 0) {
-                            $visibilityInfo = api_get_item_property_info(
-                                $courseId,
-                                TOOL_QUIZ,
-                                $exercise['iid'],
-                                $sessionId
+                            // Export
+                            $actions .= Display::url(
+                                Display::return_icon('cd.png', get_lang('CopyExercise')),
+                                '',
+                                [
+                                    'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
+                                    'href' => 'exercise.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id'],
+                                ]
                             );
 
-                            if (empty($visibilityInfo)) {
-                                // Create a record for this
-                                api_item_property_update(
-                                    $courseInfo,
-                                    TOOL_QUIZ,
-                                    $exercise['iid'],
-                                    'invisible',
-                                    api_get_user_id(),
-                                    0,
-                                    null,
+                            // Clean exercise
+                            if ($locked == false) {
+                                $clean = Display::url(
+                                    Display::return_icon(
+                                        'clean.png',
+                                        get_lang('CleanStudentResults'),
+                                        '',
+                                        ICON_SIZE_SMALL
+                                    ),
                                     '',
+                                    [
+                                        'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteResults'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
+                                        'href' => 'exercise.php?'.api_get_cidreq().'&choice=clean_results&sec_token='.$token.'&exerciseId='.$row['id'],
+                                    ]
+                                );
+                            } else {
+                                $clean = Display::return_icon(
+                                    'clean_na.png',
+                                    get_lang('ResourceLockedByGradebook'),
                                     '',
-                                    $sessionId
+                                    ICON_SIZE_SMALL
                                 );
                             }
-                        }
-                    }
-                }
-            }
-        }
-
-        if (isset($list_ordered) && !empty($list_ordered)) {
-            $new_question_list = [];
-            foreach ($list_ordered as $exercise_id) {
-                if (isset($exerciseList[$exercise_id])) {
-                    $new_question_list[] = $exerciseList[$exercise_id];
-                }
-            }
-            $exerciseList = $new_question_list;
-        }
-
-        if (!empty($exerciseList)) {
-            if ($origin !== 'learnpath') {
-                //avoid sending empty parameters
-                $mylpid = empty($learnpath_id) ? '' : '&learnpath_id='.$learnpath_id;
-                $mylpitemid = empty($learnpath_item_id) ? '' : '&learnpath_item_id='.$learnpath_item_id;
-                foreach ($exerciseList as $row) {
-                    $my_exercise_id = $row['id'];
-                    $exercise = new Exercise();
-                    $exercise->read($my_exercise_id, false);
 
-                    if (empty($exercise->id)) {
-                        continue;
-                    }
+                            if ($limitTeacherAccess && !api_is_platform_admin()) {
+                                $clean = '';
+                            }
+                            $actions .= $clean;
+                            // Visible / invisible
+                            // Check if this exercise was added in a LP
+                            if ($exercise->exercise_was_added_in_lp == true) {
+                                $visibility = Display::return_icon(
+                                    'invisible.png',
+                                    get_lang('AddedToLPCannotBeAccessed'),
+                                    '',
+                                    ICON_SIZE_SMALL
+                                );
+                            } else {
+                                if ($row['active'] == 0 || $visibility == 0) {
+                                    $visibility = Display::url(
+                                        Display::return_icon(
+                                            'invisible.png',
+                                            get_lang('Activate'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=enable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
+                                } else {
+                                    // else if not active
+                                    $visibility = Display::url(
+                                        Display::return_icon(
+                                            'visible.png',
+                                            get_lang('Deactivate'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=disable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
+                                }
+                            }
 
-                    $locked = $exercise->is_gradebook_locked;
-                    // Validation when belongs to a session
-                    $session_img = api_get_session_image($row['session_id'], $userInfo['status']);
+                            if ($limitTeacherAccess && !api_is_platform_admin()) {
+                                $visibility = '';
+                            }
 
-                    $time_limits = false;
-                    if (!empty($row['start_time']) || !empty($row['end_time'])) {
-                        $time_limits = true;
-                    }
+                            $actions .= $visibility;
 
-                    $is_actived_time = false;
-                    if ($time_limits) {
-                        // check if start time
-                        $start_time = false;
-                        if (!empty($row['start_time'])) {
-                            $start_time = api_strtotime($row['start_time'], 'UTC');
-                        }
-                        $end_time = false;
-                        if (!empty($row['end_time'])) {
-                            $end_time = api_strtotime($row['end_time'], 'UTC');
-                        }
-                        $now = time();
+                            // Export qti ...
+                            $export = Display::url(
+                                Display::return_icon(
+                                    'export_qti2.png',
+                                    'IMS/QTI',
+                                    '',
+                                    ICON_SIZE_SMALL
+                                ),
+                                'exercise.php?choice=exportqti2&exerciseId='.$row['id'].'&'.api_get_cidreq()
+                            );
 
-                        //If both "clocks" are enable
-                        if ($start_time && $end_time) {
-                            if ($now > $start_time && $end_time > $now) {
-                                $is_actived_time = true;
+                            if ($limitTeacherAccess && !api_is_platform_admin()) {
+                                $export = '';
                             }
+
+                            $actions .= $export;
                         } else {
-                            //we check the start and end
-                            if ($start_time) {
-                                if ($now > $start_time) {
-                                    $is_actived_time = true;
+                            // not session
+                            $actions = Display::return_icon(
+                                'edit_na.png',
+                                get_lang('ExerciseEditionNotAvailableInSession')
+                            );
+
+                            // Check if this exercise was added in a LP
+                            if ($exercise->exercise_was_added_in_lp == true) {
+                                $visibility = Display::return_icon(
+                                    'invisible.png',
+                                    get_lang('AddedToLPCannotBeAccessed'),
+                                    '',
+                                    ICON_SIZE_SMALL
+                                );
+                            } else {
+                                if ($row['active'] == 0 || $visibility == 0) {
+                                    $visibility = Display::url(
+                                        Display::return_icon(
+                                            'invisible.png',
+                                            get_lang('Activate'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=enable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
+                                } else {
+                                    // else if not active
+                                    $visibility = Display::url(
+                                        Display::return_icon(
+                                            'visible.png',
+                                            get_lang('Deactivate'),
+                                            '',
+                                            ICON_SIZE_SMALL
+                                        ),
+                                        'exercise.php?'.api_get_cidreq().'&choice=disable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
+                                    );
                                 }
                             }
-                            if ($end_time) {
-                                if ($end_time > $now) {
-                                    $is_actived_time = true;
-                                }
+
+                            if ($limitTeacherAccess && !api_is_platform_admin()) {
+                                $visibility = '';
+                            }
+
+                            $actions .= $visibility;
+
+                            $actions .= '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
+                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+                            $actions .= Display::url(
+                                Display::return_icon('cd.gif', get_lang('CopyExercise')),
+                                '',
+                                [
+                                    'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
+                                    'href' => 'exercise.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id'],
+                                ]
+                            );
+                        }
+
+                        // Delete
+                        $delete = '';
+                        if ($sessionId == $row['session_id']) {
+                            if ($locked == false) {
+                                $delete = Display::url(
+                                    Display::return_icon(
+                                        'delete.png',
+                                        get_lang('Delete'),
+                                        '',
+                                        ICON_SIZE_SMALL
+                                    ),
+                                    '',
+                                    [
+                                        'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteJS'), ENT_QUOTES, $charset))." ".addslashes($exercise->getUnformattedTitle())."?"."')) return false;",
+                                        'href' => 'exercise.php?'.api_get_cidreq().'&choice=delete&sec_token='.$token.'&exerciseId='.$row['id'],
+                                    ]
+                                );
+                            } else {
+                                $delete = Display::return_icon(
+                                    'delete_na.png',
+                                    get_lang('ResourceLockedByGradebook'),
+                                    '',
+                                    ICON_SIZE_SMALL
+                                );
                             }
                         }
-                    }
 
-                    // Blocking empty start times see BT#2800
-                    global $_custom;
-                    if (isset($_custom['exercises_hidden_when_no_start_date']) &&
-                        $_custom['exercises_hidden_when_no_start_date']
-                    ) {
-                        if (empty($row['start_time'])) {
-                            $time_limits = true;
-                            $is_actived_time = false;
+                        if ($limitTeacherAccess && !api_is_platform_admin()) {
+                            $delete = '';
                         }
-                    }
 
-                    $cut_title = $exercise->getCutTitle();
-                    $alt_title = '';
-                    if ($cut_title != $row['title']) {
-                        $alt_title = ' title = "'.$exercise->getUnformattedTitle().'" ';
-                    }
+                        $actions .= $delete;
 
-                    // Teacher only
-                    if ($is_allowedToEdit) {
-                        $lp_blocked = null;
-                        if ($exercise->exercise_was_added_in_lp == true) {
-                            $lp_blocked = Display::div(
-                                get_lang('AddedToLPCannotBeAccessed'),
-                                ['class' => 'lp_content_type_label']
-                            );
+                        // Number of questions
+                        $random_label = null;
+                        if ($row['random'] > 0 || $row['random'] == -1) {
+                            // if random == -1 means use random questions with all questions
+                            $random_number_of_question = $row['random'];
+                            if ($random_number_of_question == -1) {
+                                $random_number_of_question = $rowi;
+                            }
+                            if ($row['random_by_category'] > 0) {
+                                $nbQuestionsTotal = TestCategory::getNumberOfQuestionRandomByCategory(
+                                    $my_exercise_id,
+                                    $random_number_of_question
+                                );
+                                $number_of_questions = $nbQuestionsTotal.' ';
+                                $number_of_questions .= ($nbQuestionsTotal > 1) ? get_lang('QuestionsLowerCase') : get_lang('QuestionLowerCase');
+                                $number_of_questions .= ' - ';
+                                $number_of_questions .= min(
+                                        TestCategory::getNumberMaxQuestionByCat($my_exercise_id), $random_number_of_question
+                                    ).' '.get_lang('QuestionByCategory');
+                            } else {
+                                $random_label = ' ('.get_lang('Random').') ';
+                                $number_of_questions = $random_number_of_question.' '.$random_label.' / '.$rowi;
+                                // Bug if we set a random value bigger than the real number of questions
+                                if ($random_number_of_question > $rowi) {
+                                    $number_of_questions = $rowi.' '.$random_label;
+                                }
+                            }
+                        } else {
+                            $number_of_questions = $rowi;
                         }
-
+                        $item .= Display::tag('td', $number_of_questions);
+                    } else {
+                        // Student only.
                         $visibility = api_get_item_visibility(
                             $courseInfo,
                             TOOL_QUIZ,
                             $my_exercise_id,
-                            0
+                            $sessionId
                         );
 
-                        if (!empty($sessionId)) {
-                            $setting = api_get_configuration_value('show_hidden_exercise_added_to_lp');
-                            if ($setting) {
-                                if ($exercise->exercise_was_added_in_lp == false) {
-                                    if ($visibility == 0) {
-                                        continue;
+                        if ($visibility == 0) {
+                            continue;
+                        }
+
+                        $url = '<a '.$alt_title.'  href="overview.php?'.api_get_cidreq().$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">'.
+                            $cut_title.'</a>';
+
+                        // Link of the exercise.
+                        $item = Display::tag('td', $url.' '.$session_img);
+
+                        // This query might be improved later on by ordering by the new "tms" field rather than by exe_id
+                        // Don't remove this marker: note-query-exe-results
+                        $sql = "SELECT * FROM $TBL_TRACK_EXERCISES
+                                WHERE
+                                    exe_exo_id = ".$row['id']." AND
+                                    exe_user_id = $userId AND
+                                    c_id = ".api_get_course_int_id()." AND
+                                    status <> 'incomplete' AND
+                                    orig_lp_id = 0 AND
+                                    orig_lp_item_id = 0 AND
+                                    session_id =  '".api_get_session_id()."'
+                                ORDER BY exe_id DESC";
+
+                        $qryres = Database::query($sql);
+                        $num = Database :: num_rows($qryres);
+
+                        // Hide the results.
+                        $my_result_disabled = $row['results_disabled'];
+
+                        // Time limits are on
+                        if ($time_limits) {
+                            // Exam is ready to be taken
+                            if ($is_actived_time) {
+                                // Show results
+                                if (
+                                in_array(
+                                    $my_result_disabled,
+                                    [
+                                        RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
+                                        RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+                                        RESULT_DISABLE_SHOW_SCORE_ONLY,
+                                        RESULT_DISABLE_RANKING,
+                                    ]
+                                )
+                                ) {
+                                    // More than one attempt
+                                    if ($num > 0) {
+                                        $row_track = Database :: fetch_array($qryres);
+                                        $attempt_text = get_lang('LatestAttempt').' : ';
+                                        $attempt_text .= ExerciseLib::show_score(
+                                            $row_track['exe_result'],
+                                            $row_track['exe_weighting']
+                                        );
+                                    } else {
+                                        //No attempts
+                                        $attempt_text = get_lang('NotAttempted');
                                     }
+                                } else {
+                                    $attempt_text = '-';
                                 }
                             } else {
-                                if ($visibility == 0) {
-                                    continue;
+                                // Quiz not ready due to time limits
+                                //@todo use the is_visible function
+                                if (!empty($row['start_time']) && !empty($row['end_time'])) {
+                                    $today = time();
+                                    $start_time = api_strtotime($row['start_time'], 'UTC');
+                                    $end_time = api_strtotime($row['end_time'], 'UTC');
+                                    if ($today < $start_time) {
+                                        $attempt_text = sprintf(
+                                            get_lang('ExerciseWillBeActivatedFromXToY'),
+                                            api_convert_and_format_date($row['start_time']),
+                                            api_convert_and_format_date($row['end_time'])
+                                        );
+                                    } else {
+                                        if ($today > $end_time) {
+                                            $attempt_text = sprintf(
+                                                get_lang('ExerciseWasActivatedFromXToY'),
+                                                api_convert_and_format_date($row['start_time']),
+                                                api_convert_and_format_date($row['end_time'])
+                                            );
+                                        }
+                                    }
+                                } else {
+                                    //$attempt_text = get_lang('ExamNotAvailableAtThisTime');
+                                    if (!empty($row['start_time'])) {
+                                        $attempt_text = sprintf(
+                                            get_lang('ExerciseAvailableFromX'),
+                                            api_convert_and_format_date($row['start_time'])
+                                        );
+                                    }
+                                    if (!empty($row['end_time'])) {
+                                        $attempt_text = sprintf(
+                                            get_lang('ExerciseAvailableUntilX'),
+                                            api_convert_and_format_date($row['end_time'])
+                                        );
+                                    }
                                 }
                             }
-
-                            $visibility = api_get_item_visibility(
-                                $courseInfo,
-                                TOOL_QUIZ,
-                                $my_exercise_id,
-                                $sessionId
-                            );
+                        } else {
+                            // Normal behaviour.
+                            // Show results.
+                            if (
+                            in_array(
+                                $my_result_disabled,
+                                [
+                                    RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
+                                    RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+                                    RESULT_DISABLE_SHOW_SCORE_ONLY,
+                                    RESULT_DISABLE_RANKING,
+                                ]
+                            )
+                            ) {
+                                if ($num > 0) {
+                                    $row_track = Database :: fetch_array($qryres);
+                                    $attempt_text = get_lang('LatestAttempt').' : ';
+                                    $attempt_text .= ExerciseLib::show_score(
+                                        $row_track['exe_result'],
+                                        $row_track['exe_weighting']
+                                    );
+                                } else {
+                                    $attempt_text = get_lang('NotAttempted');
+                                }
+                            } else {
+                                $attempt_text = '-';
+                            }
                         }
 
-                        if ($row['active'] == 0 || $visibility == 0) {
-                            $title = Display::tag('font', $cut_title, ['style' => 'color:grey']);
+                        $class_tip = '';
+                        if (empty($num)) {
+                            $num = '';
                         } else {
-                            $title = $cut_title;
+                            $class_tip = 'link_tooltip';
+                            //@todo use sprintf and show the results validated by the teacher
+                            if ($num == 1) {
+                                $num = $num.' '.get_lang('Result');
+                            } else {
+                                $num = $num.' '.get_lang('Results');
+                            }
+                            $num = '<span class="tooltip" style="display: none;">'.$num.'</span>';
                         }
 
-                        $count_exercise_not_validated = (int) Event::count_exercise_result_not_validated(
-                            $my_exercise_id,
-                            $courseId,
-                            $sessionId
-                        );
+                        $item .= Display::tag('td', $attempt_text);
+                    }
 
-                        $move = Display::return_icon(
-                            'all_directions.png',
-                            get_lang('Move'),
-                            ['class' => 'moved', 'style' => 'margin-bottom:-0.5em;']
-                        );
-                        $move = null;
-                        $class_tip = '';
+                    if ($is_allowedToEdit) {
+                        $additionalActions = ExerciseLib::getAdditionalTeacherActions($row['id']);
 
-                        if (!empty($count_exercise_not_validated)) {
-                            $results_text = $count_exercise_not_validated == 1 ? get_lang('ResultNotRevised') : get_lang('ResultsNotRevised');
-                            $title .= '<span class="exercise_tooltip" style="display: none;">'.$count_exercise_not_validated.' '.$results_text.' </span>';
-                            $class_tip = 'link_tooltip';
+                        if (!empty($additionalActions)) {
+                            $actions .= $additionalActions.PHP_EOL;
                         }
 
-                        $url = $move.'<a '.$alt_title.' class="'.$class_tip.'" id="tooltip_'.$row['id'].'" href="overview.php?'.api_get_cidreq().$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">
-                             '.Display::return_icon('quiz.png', $row['title']).'
-                             '.$title.' </a>'.PHP_EOL;
-
-                        if (ExerciseLib::isQuizEmbeddable($row)) {
-                            $embeddableIcon = Display::return_icon('om_integration.png', get_lang('ThisQuizCanBeEmbeddable'));
-                            $url .= Display::div($embeddableIcon, ['class' => 'pull-right']);
+                        $item .= Display::tag('td', $actions, ['class' => 'td_actions']);
+                    } else {
+                        if ($isDrhOfCourse) {
+                            $actions = '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
+                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+                            $item .= Display::tag('td', $actions, ['class' => 'td_actions']);
                         }
+                    }
 
-                        $item = Display::tag('td', $url.' '.$session_img.$lp_blocked);
+                    $tableRows[] = Display::tag(
+                        'tr',
+                        $item,
+                        [
+                            'id' => 'exercise_list_'.$my_exercise_id,
+                        ]
+                    );
+                }
+            }
+        }
 
-                        // Count number exercise - teacher
-                        $sql = "SELECT count(*) count FROM $TBL_EXERCISE_QUESTION
-                        WHERE c_id = $courseId AND exercice_id = $my_exercise_id";
-                        $sqlresult = Database::query($sql);
-                        $rowi = (int) Database::result($sqlresult, 0, 0);
+        // end exercise list
+        // Hotpotatoes results
+        $hotpotatoes_exist = false;
 
-                        if ($sessionId == $row['session_id']) {
-                            // Questions list
-                            $actions = Display::url(
-                                Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL),
-                                'admin.php?'.api_get_cidreq().'&exerciseId='.$row['id']
-                            );
+        if ($is_allowedToEdit) {
+            $sql = "SELECT d.iid, d.path as path, d.comment as comment
+                    FROM $TBL_DOCUMENT d
+                    WHERE
+                        d.c_id = $courseId AND
+                        (d.path LIKE '%htm%') AND
+                        d.path  LIKE '".Database :: escape_string($uploadPath.'/%/%')."'
+                    LIMIT ".$from.",".$limit; // only .htm or .html files listed
+        } else {
+            $sql = "SELECT d.iid, d.path as path, d.comment as comment
+                    FROM $TBL_DOCUMENT d
+                    WHERE
+                        d.c_id = $courseId AND
+                        (d.path LIKE '%htm%') AND
+                        d.path  LIKE '".Database :: escape_string($uploadPath.'/%/%')."'
+                    LIMIT ".$from.",".$limit;
+        }
 
-                            // Test settings
-                            $settings = Display::url(
-                                Display::return_icon('settings.png', get_lang('Configure'), '', ICON_SIZE_SMALL),
-                                'exercise_admin.php?'.api_get_cidreq().'&exerciseId='.$row['id']
-                            );
+        $result = Database::query($sql);
+        $attribute = [];
+        while ($row = Database :: fetch_array($result, 'ASSOC')) {
+            $attribute['id'][] = $row['iid'];
+            $attribute['path'][] = $row['path'];
+            $attribute['comment'][] = $row['comment'];
+        }
 
-                            if ($limitTeacherAccess && !api_is_platform_admin()) {
-                                $settings = '';
-                            }
-                            $actions .= $settings;
+        $nbrActiveTests = 0;
+        if (isset($attribute['path']) && is_array($attribute['path'])) {
+            $hotpotatoes_exist = true;
+            foreach ($attribute['path'] as $key => $path) {
+                $item = '';
+                $title = GetQuizName($path, $documentPath);
+                if ($title == '') {
+                    $title = basename($path);
+                }
 
-                            // Exercise results
-                            $resultsLink = '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
-                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+                // prof only
+                if ($is_allowedToEdit) {
+                    $visibility = api_get_item_visibility(
+                        ['real_id' => $courseId],
+                        TOOL_DOCUMENT,
+                        $attribute['id'][$key],
+                        0
+                    );
 
-                            if ($limitTeacherAccess) {
-                                if (api_is_platform_admin()) {
-                                    $actions .= $resultsLink;
-                                }
-                            } else {
-                                // Exercise results
-                                $actions .= $resultsLink;
-                            }
+                    if (!empty($sessionId)) {
+                        if (0 == $visibility) {
+                            continue;
+                        }
 
-                            // Auto launch
-                            if ($autoLaunchAvailable) {
-                                $autoLaunch = $exercise->getAutoLaunch();
-                                if (empty($autoLaunch)) {
-                                    $actions .= Display::url(
-                                        Display::return_icon(
-                                            'launch_na.png',
-                                            get_lang('Enable'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=enable_launch&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                } else {
-                                    $actions .= Display::url(
-                                        Display::return_icon(
-                                            'launch.png',
-                                            get_lang('Disable'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=disable_launch&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                }
-                            }
+                        $visibility = api_get_item_visibility(
+                            ['real_id' => $courseId],
+                            TOOL_DOCUMENT,
+                            $attribute['id'][$key],
+                            $sessionId
+                        );
+                    }
 
-                            // Export
-                            $actions .= Display::url(
-                                Display::return_icon('cd.png', get_lang('CopyExercise')),
-                                '',
-                                [
-                                    'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
-                                    'href' => 'exercise.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id'],
-                                ]
-                            );
+                    $item = Display::tag(
+                        'td',
+                        implode(PHP_EOL, [
+                            Display::return_icon('hotpotatoes_s.png', "HotPotatoes"),
+                            Display::url(
+                                $title,
+                                'showinframes.php?'.api_get_cidreq().'&'.http_build_query([
+                                    'file' => $path,
+                                    'uid' => $userId,
+                                ]),
+                                ['class' => $visibility == 0 ? 'text-muted' : null]
+                            ),
+                        ])
+                    );
 
-                            // Clean exercise
-                            if ($locked == false) {
-                                $clean = Display::url(
-                                    Display::return_icon(
-                                        'clean.png',
-                                        get_lang('CleanStudentResults'),
-                                        '',
-                                        ICON_SIZE_SMALL
-                                    ),
-                                    '',
-                                    [
-                                        'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteResults'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
-                                        'href' => 'exercise.php?'.api_get_cidreq().'&choice=clean_results&sec_token='.$token.'&exerciseId='.$row['id'],
-                                    ]
-                                );
-                            } else {
-                                $clean = Display::return_icon(
-                                    'clean_na.png',
-                                    get_lang('ResourceLockedByGradebook'),
-                                    '',
-                                    ICON_SIZE_SMALL
-                                );
-                            }
+                    $item .= Display::tag('td', '-');
 
-                            if ($limitTeacherAccess && !api_is_platform_admin()) {
-                                $clean = '';
-                            }
-                            $actions .= $clean;
-                            // Visible / invisible
-                            // Check if this exercise was added in a LP
-                            if ($exercise->exercise_was_added_in_lp == true) {
-                                $visibility = Display::return_icon(
-                                    'invisible.png',
-                                    get_lang('AddedToLPCannotBeAccessed'),
-                                    '',
-                                    ICON_SIZE_SMALL
-                                );
-                            } else {
-                                if ($row['active'] == 0 || $visibility == 0) {
-                                    $visibility = Display::url(
-                                        Display::return_icon(
-                                            'invisible.png',
-                                            get_lang('Activate'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=enable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                } else {
-                                    // else if not active
-                                    $visibility = Display::url(
-                                        Display::return_icon(
-                                            'visible.png',
-                                            get_lang('Deactivate'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=disable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                }
-                            }
+                    $actions = Display::url(
+                        Display::return_icon(
+                            'edit.png',
+                            get_lang('Edit'),
+                            '',
+                            ICON_SIZE_SMALL
+                        ),
+                        'adminhp.php?'.api_get_cidreq().'&hotpotatoesName='.$path
+                    );
+
+                    $actions .= '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'">'.
+                        Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+
+                    // if active
+                    if ($visibility != 0) {
+                        $nbrActiveTests = $nbrActiveTests + 1;
+                        $actions .= '      <a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=disable&page='.$page.'&file='.$path.'">'.
+                            Display::return_icon('visible.png', get_lang('Deactivate'), '', ICON_SIZE_SMALL).'</a>';
+                    } else { // else if not active
+                        $actions .= '    <a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=enable&page='.$page.'&file='.$path.'">'.
+                            Display::return_icon('invisible.png', get_lang('Activate'), '', ICON_SIZE_SMALL).'</a>';
+                    }
+                    $actions .= '<a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=delete&file='.$path.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('AreYouSureToDeleteJS'), ENT_QUOTES, $charset).' '.$title."?").'\')) return false;">'.
+                        Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
+                    $item .= Display::tag('td', $actions);
+                    $tableRows[] = Display::tag('tr', $item);
+                } else {
+                    $visibility = api_get_item_visibility(
+                        ['real_id' => $courseId],
+                        TOOL_DOCUMENT,
+                        $attribute['id'][$key],
+                        $sessionId
+                    );
+
+                    if (0 == $visibility) {
+                        continue;
+                    }
 
-                            if ($limitTeacherAccess && !api_is_platform_admin()) {
-                                $visibility = '';
-                            }
+                    // Student only
+                    $attempt = ExerciseLib::getLatestHotPotatoResult(
+                        $path,
+                        $userId,
+                        api_get_course_int_id(),
+                        api_get_session_id()
+                    );
 
-                            $actions .= $visibility;
+                    $nbrActiveTests = $nbrActiveTests + 1;
+                    $item .= Display::tag(
+                        'td',
+                        Display::url(
+                            $title,
+                            'showinframes.php?'.api_get_cidreq().'&'.http_build_query([
+                                'file' => $path,
+                                'cid' => api_get_course_id(),
+                                'uid' => $userId,
+                            ])
+                        )
+                    );
 
-                            // Export qti ...
-                            $export = Display::url(
-                                Display::return_icon(
-                                    'export_qti2.png',
-                                    'IMS/QTI',
-                                    '',
-                                    ICON_SIZE_SMALL
-                                ),
-                                'exercise.php?choice=exportqti2&exerciseId='.$row['id'].'&'.api_get_cidreq()
-                            );
+                    if (!empty($attempt)) {
+                        $actions = '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'&filter_by_user='.$userId.'">'.Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+                        $attemptText = get_lang('LatestAttempt').' : ';
+                        $attemptText .= ExerciseLib::show_score(
+                                $attempt['exe_result'],
+                                $attempt['exe_weighting']
+                            ).' ';
+                        $attemptText .= $actions;
+                    } else {
+                        // No attempts.
+                        $attemptText = get_lang('NotAttempted').' ';
+                    }
 
-                            if ($limitTeacherAccess && !api_is_platform_admin()) {
-                                $export = '';
-                            }
+                    $item .= Display::tag('td', $attemptText);
 
-                            $actions .= $export;
-                        } else {
-                            // not session
-                            $actions = Display::return_icon(
-                                'edit_na.png',
-                                get_lang('ExerciseEditionNotAvailableInSession')
-                            );
+                    if ($isDrhOfCourse) {
+                        $actions = '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'">'.
+                            Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
 
-                            // Check if this exercise was added in a LP
-                            if ($exercise->exercise_was_added_in_lp == true) {
-                                $visibility = Display::return_icon(
-                                    'invisible.png',
-                                    get_lang('AddedToLPCannotBeAccessed'),
-                                    '',
-                                    ICON_SIZE_SMALL
-                                );
-                            } else {
-                                if ($row['active'] == 0 || $visibility == 0) {
-                                    $visibility = Display::url(
-                                        Display::return_icon(
-                                            'invisible.png',
-                                            get_lang('Activate'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=enable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                } else {
-                                    // else if not active
-                                    $visibility = Display::url(
-                                        Display::return_icon(
-                                            'visible.png',
-                                            get_lang('Deactivate'),
-                                            '',
-                                            ICON_SIZE_SMALL
-                                        ),
-                                        'exercise.php?'.api_get_cidreq().'&choice=disable&sec_token='.$token.'&page='.$page.'&exerciseId='.$row['id']
-                                    );
-                                }
-                            }
+                        $item .= Display::tag(
+                            'td',
+                            $actions,
+                            ['class' => 'td_actions']
+                        );
+                    }
+                    $tableRows[] = Display::tag('tr', $item);
+                }
+            }
+        }
 
-                            if ($limitTeacherAccess && !api_is_platform_admin()) {
-                                $visibility = '';
-                            }
+        if (empty($tableRows)) {
+            if ($is_allowedToEdit && $origin != 'learnpath') {
+                $content .= '<div id="no-data-view">';
+                $content .= '<h3>'.get_lang('Quiz').'</h3>';
+                $content .= Display::return_icon('quiz.png', '', [], 64);
+                $content .= '<div class="controls">';
+                $content .= Display::url(
+                    '<em class="fa fa-plus"></em> '.get_lang('NewEx'),
+                    'exercise_admin.php?'.api_get_cidreq(),
+                    ['class' => 'btn btn-primary']
+                );
+                $content .= '</div>';
+                $content .= '</div>';
+            }
+        } else {
+            if ($is_allowedToEdit) {
+                $headers = [
+                    get_lang('ExerciseName'),
+                    get_lang('QuantityQuestions'),
+                    get_lang('Actions'),
+                ];
+            } else {
+                $headers = [
+                    get_lang('ExerciseName'),
+                    get_lang('Status'),
+                ];
 
-                            $actions .= $visibility;
+                if ($isDrhOfCourse) {
+                    $headers[] = get_lang('Actions');
+                }
+            }
 
-                            $actions .= '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
-                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
-                            $actions .= Display::url(
-                                Display::return_icon('cd.gif', get_lang('CopyExercise')),
-                                '',
-                                [
-                                    'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToCopy'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
-                                    'href' => 'exercise.php?'.api_get_cidreq().'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$row['id'],
-                                ]
-                            );
-                        }
+            foreach ($tableRows as $roz) {
+                echo $roz;
+            }
 
-                        // Delete
-                        $delete = '';
-                        if ($sessionId == $row['session_id']) {
-                            if ($locked == false) {
-                                $delete = Display::url(
-                                    Display::return_icon(
-                                        'delete.png',
-                                        get_lang('Delete'),
-                                        '',
-                                        ICON_SIZE_SMALL
-                                    ),
-                                    '',
-                                    [
-                                        'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteJS'), ENT_QUOTES, $charset))." ".addslashes($exercise->getUnformattedTitle())."?"."')) return false;",
-                                        'href' => 'exercise.php?'.api_get_cidreq().'&choice=delete&sec_token='.$token.'&exerciseId='.$row['id'],
-                                    ]
-                                );
-                            } else {
-                                $delete = Display::return_icon(
-                                    'delete_na.png',
-                                    get_lang('ResourceLockedByGradebook'),
-                                    '',
-                                    ICON_SIZE_SMALL
-                                );
-                            }
-                        }
+            $content .= '<div class="table-responsive">';
+            $table = new SortableTableFromArrayConfig(
+                $tableRows,
+                1,
+                20,
+                'exercises'
+            );
+            $i = 0;
+            foreach ($headers as $header) {
+                $table->set_header($i++, $header);
+            }
+            $table->set_header($i++, 'aa');
 
-                        if ($limitTeacherAccess && !api_is_platform_admin()) {
-                            $delete = '';
-                        }
+            $content .= $table->return_table();
+            $content .= '</div>';
+        }
 
-                        $actions .= $delete;
+        return $content;
+    }
 
-                        // Number of questions
-                        $random_label = null;
-                        if ($row['random'] > 0 || $row['random'] == -1) {
-                            // if random == -1 means use random questions with all questions
-                            $random_number_of_question = $row['random'];
-                            if ($random_number_of_question == -1) {
-                                $random_number_of_question = $rowi;
-                            }
-                            if ($row['random_by_category'] > 0) {
-                                $nbQuestionsTotal = TestCategory::getNumberOfQuestionRandomByCategory(
-                                    $my_exercise_id,
-                                    $random_number_of_question
-                                );
-                                $number_of_questions = $nbQuestionsTotal.' ';
-                                $number_of_questions .= ($nbQuestionsTotal > 1) ? get_lang('QuestionsLowerCase') : get_lang('QuestionLowerCase');
-                                $number_of_questions .= ' - ';
-                                $number_of_questions .= min(
-                                        TestCategory::getNumberMaxQuestionByCat($my_exercise_id), $random_number_of_question
-                                    ).' '.get_lang('QuestionByCategory');
-                            } else {
-                                $random_label = ' ('.get_lang('Random').') ';
-                                $number_of_questions = $random_number_of_question.' '.$random_label.' / '.$rowi;
-                                // Bug if we set a random value bigger than the real number of questions
-                                if ($random_number_of_question > $rowi) {
-                                    $number_of_questions = $rowi.' '.$random_label;
-                                }
-                            }
-                        } else {
-                            $number_of_questions = $rowi;
-                        }
-                        $item .= Display::tag('td', $number_of_questions);
-                    } else {
-                        // Student only.
-                        $visibility = api_get_item_visibility(
-                            $courseInfo,
-                            TOOL_QUIZ,
-                            $my_exercise_id,
-                            $sessionId
-                        );
+    /**
+     * Gets the question list ordered by the question_order setting (drag and drop).
+     *
+     * @return array
+     */
+    private function getQuestionOrderedList()
+    {
+        $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
+        $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
 
-                        if ($visibility == 0) {
-                            continue;
-                        }
+        // Getting question_order to verify that the question
+        // list is correct and all question_order's were set
+        $sql = "SELECT DISTINCT count(e.question_order) as count
+                FROM $TBL_EXERCICE_QUESTION e
+                INNER JOIN $TBL_QUESTIONS q
+                ON (e.question_id = q.id AND e.c_id = q.c_id)
+                WHERE
+                  e.c_id = {$this->course_id} AND
+                  e.exercice_id	= ".$this->id;
 
-                        $url = '<a '.$alt_title.'  href="overview.php?'.api_get_cidreq().$mylpid.$mylpitemid.'&exerciseId='.$row['id'].'">'.
-                            $cut_title.'</a>';
+        $result = Database::query($sql);
+        $row = Database::fetch_array($result);
+        $count_question_orders = $row['count'];
 
-                        // Link of the exercise.
-                        $item = Display::tag('td', $url.' '.$session_img);
+        // Getting question list from the order (question list drag n drop interface).
+        $sql = "SELECT DISTINCT e.question_id, e.question_order
+                FROM $TBL_EXERCICE_QUESTION e
+                INNER JOIN $TBL_QUESTIONS q
+                ON (e.question_id = q.id AND e.c_id = q.c_id)
+                WHERE
+                    e.c_id = {$this->course_id} AND
+                    e.exercice_id = '".$this->id."'
+                ORDER BY question_order";
+        $result = Database::query($sql);
 
-                        // This query might be improved later on by ordering by the new "tms" field rather than by exe_id
-                        // Don't remove this marker: note-query-exe-results
-                        $sql = "SELECT * FROM $TBL_TRACK_EXERCISES
-                                WHERE
-                                    exe_exo_id = ".$row['id']." AND
-                                    exe_user_id = $userId AND
-                                    c_id = ".api_get_course_int_id()." AND
-                                    status <> 'incomplete' AND
-                                    orig_lp_id = 0 AND
-                                    orig_lp_item_id = 0 AND
-                                    session_id =  '".api_get_session_id()."'
-                                ORDER BY exe_id DESC";
+        // Fills the array with the question ID for this exercise
+        // the key of the array is the question position
+        $temp_question_list = [];
+        $counter = 1;
+        $questionList = [];
+        while ($new_object = Database::fetch_object($result)) {
+            // Correct order.
+            $questionList[$new_object->question_order] = $new_object->question_id;
+            // Just in case we save the order in other array
+            $temp_question_list[$counter] = $new_object->question_id;
+            $counter++;
+        }
 
-                        $qryres = Database::query($sql);
-                        $num = Database :: num_rows($qryres);
+        if (!empty($temp_question_list)) {
+            /* If both array don't match it means that question_order was not correctly set
+               for all questions using the default mysql order */
+            if (count($temp_question_list) != $count_question_orders) {
+                $questionList = $temp_question_list;
+            }
+        }
 
-                        // Hide the results.
-                        $my_result_disabled = $row['results_disabled'];
+        return $questionList;
+    }
 
-                        // Time limits are on
-                        if ($time_limits) {
-                            // Exam is ready to be taken
-                            if ($is_actived_time) {
-                                // Show results
-                                if (
-                                in_array(
-                                    $my_result_disabled,
-                                    [
-                                        RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
-                                        RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-                                        RESULT_DISABLE_SHOW_SCORE_ONLY,
-                                        RESULT_DISABLE_RANKING,
-                                    ]
-                                )
-                                ) {
-                                    // More than one attempt
-                                    if ($num > 0) {
-                                        $row_track = Database :: fetch_array($qryres);
-                                        $attempt_text = get_lang('LatestAttempt').' : ';
-                                        $attempt_text .= ExerciseLib::show_score(
-                                            $row_track['exe_result'],
-                                            $row_track['exe_weighting']
-                                        );
-                                    } else {
-                                        //No attempts
-                                        $attempt_text = get_lang('NotAttempted');
-                                    }
-                                } else {
-                                    $attempt_text = '-';
-                                }
-                            } else {
-                                // Quiz not ready due to time limits
-                                //@todo use the is_visible function
-                                if (!empty($row['start_time']) && !empty($row['end_time'])) {
-                                    $today = time();
-                                    $start_time = api_strtotime($row['start_time'], 'UTC');
-                                    $end_time = api_strtotime($row['end_time'], 'UTC');
-                                    if ($today < $start_time) {
-                                        $attempt_text = sprintf(
-                                            get_lang('ExerciseWillBeActivatedFromXToY'),
-                                            api_convert_and_format_date($row['start_time']),
-                                            api_convert_and_format_date($row['end_time'])
-                                        );
-                                    } else {
-                                        if ($today > $end_time) {
-                                            $attempt_text = sprintf(
-                                                get_lang('ExerciseWasActivatedFromXToY'),
-                                                api_convert_and_format_date($row['start_time']),
-                                                api_convert_and_format_date($row['end_time'])
-                                            );
-                                        }
-                                    }
-                                } else {
-                                    //$attempt_text = get_lang('ExamNotAvailableAtThisTime');
-                                    if (!empty($row['start_time'])) {
-                                        $attempt_text = sprintf(
-                                            get_lang('ExerciseAvailableFromX'),
-                                            api_convert_and_format_date($row['start_time'])
-                                        );
-                                    }
-                                    if (!empty($row['end_time'])) {
-                                        $attempt_text = sprintf(
-                                            get_lang('ExerciseAvailableUntilX'),
-                                            api_convert_and_format_date($row['end_time'])
-                                        );
-                                    }
-                                }
-                            }
-                        } else {
-                            // Normal behaviour.
-                            // Show results.
-                            if (
-                            in_array(
-                                $my_result_disabled,
-                                [
-                                    RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
-                                    RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
-                                    RESULT_DISABLE_SHOW_SCORE_ONLY,
-                                    RESULT_DISABLE_RANKING,
-                                ]
-                            )
-                            ) {
-                                if ($num > 0) {
-                                    $row_track = Database :: fetch_array($qryres);
-                                    $attempt_text = get_lang('LatestAttempt').' : ';
-                                    $attempt_text .= ExerciseLib::show_score(
-                                        $row_track['exe_result'],
-                                        $row_track['exe_weighting']
-                                    );
-                                } else {
-                                    $attempt_text = get_lang('NotAttempted');
-                                }
-                            } else {
-                                $attempt_text = '-';
-                            }
-                        }
+    /**
+     * Select N values from the questions per category array.
+     *
+     * @param array $categoriesAddedInExercise
+     * @param array $question_list
+     * @param array $questions_by_category     per category
+     * @param bool  $flatResult
+     * @param bool  $randomizeQuestions
+     *
+     * @return array
+     */
+    private function pickQuestionsPerCategory(
+        $categoriesAddedInExercise,
+        $question_list,
+        &$questions_by_category,
+        $flatResult = true,
+        $randomizeQuestions = false
+    ) {
+        $addAll = true;
+        $categoryCountArray = [];
 
-                        $class_tip = '';
-                        if (empty($num)) {
-                            $num = '';
-                        } else {
-                            $class_tip = 'link_tooltip';
-                            //@todo use sprintf and show the results validated by the teacher
-                            if ($num == 1) {
-                                $num = $num.' '.get_lang('Result');
-                            } else {
-                                $num = $num.' '.get_lang('Results');
-                            }
-                            $num = '<span class="tooltip" style="display: none;">'.$num.'</span>';
-                        }
+        // Getting how many questions will be selected per category.
+        if (!empty($categoriesAddedInExercise)) {
+            $addAll = false;
+            // Parsing question according the category rel exercise settings
+            foreach ($categoriesAddedInExercise as $category_info) {
+                $category_id = $category_info['category_id'];
+                if (isset($questions_by_category[$category_id])) {
+                    // How many question will be picked from this category.
+                    $count = $category_info['count_questions'];
+                    // -1 means all questions
+                    $categoryCountArray[$category_id] = $count;
+                    if ($count == -1) {
+                        $categoryCountArray[$category_id] = 999;
+                    }
+                }
+            }
+        }
 
-                        $item .= Display::tag('td', $attempt_text);
+        if (!empty($questions_by_category)) {
+            $temp_question_list = [];
+            foreach ($questions_by_category as $category_id => &$categoryQuestionList) {
+                if (isset($categoryCountArray) && !empty($categoryCountArray)) {
+                    $numberOfQuestions = 0;
+                    if (isset($categoryCountArray[$category_id])) {
+                        $numberOfQuestions = $categoryCountArray[$category_id];
                     }
+                }
 
-                    if ($is_allowedToEdit) {
-                        $additionalActions = ExerciseLib::getAdditionalTeacherActions($row['id']);
+                if ($addAll) {
+                    $numberOfQuestions = 999;
+                }
 
-                        if (!empty($additionalActions)) {
-                            $actions .= $additionalActions.PHP_EOL;
-                        }
+                if (!empty($numberOfQuestions)) {
+                    $elements = TestCategory::getNElementsFromArray(
+                        $categoryQuestionList,
+                        $numberOfQuestions,
+                        $randomizeQuestions
+                    );
 
-                        $item .= Display::tag('td', $actions, ['class' => 'td_actions']);
-                    } else {
-                        if ($isDrhOfCourse) {
-                            $actions = '<a href="exercise_report.php?'.api_get_cidreq().'&exerciseId='.$row['id'].'">'.
-                                Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
-                            $item .= Display::tag('td', $actions, ['class' => 'td_actions']);
-                        }
+                    if (!empty($elements)) {
+                        $temp_question_list[$category_id] = $elements;
+                        $categoryQuestionList = $elements;
                     }
+                }
+            }
+
+            if (!empty($temp_question_list)) {
+                if ($flatResult) {
+                    $temp_question_list = array_flatten($temp_question_list);
+                }
+                $question_list = $temp_question_list;
+            }
+        }
+
+        return $question_list;
+    }
+
+    /**
+     * Changes the exercise id.
+     *
+     * @param int $id - exercise id
+     */
+    private function updateId($id)
+    {
+        $this->id = $id;
+    }
 
-                    $tableRows[] = Display::tag(
-                        'tr',
-                        $item,
-                        [
-                            'id' => 'exercise_list_'.$my_exercise_id,
-                        ]
-                    );
-                }
+    /**
+     * Sends a notification when a user ends an examn.
+     *
+     * @param array  $question_list_answers
+     * @param string $origin
+     * @param array  $user_info
+     * @param string $url_email
+     * @param array  $teachers
+     */
+    private function sendNotificationForOpenQuestions(
+        $question_list_answers,
+        $origin,
+        $user_info,
+        $url_email,
+        $teachers
+    ) {
+        // Email configuration settings
+        $courseCode = api_get_course_id();
+        $courseInfo = api_get_course_info($courseCode);
+        $sessionId = api_get_session_id();
+        $sessionData = '';
+        if (!empty($sessionId)) {
+            $sessionInfo = api_get_session_info($sessionId);
+            if (!empty($sessionInfo)) {
+                $sessionData = '<tr>'
+                    .'<td><em>'.get_lang('SessionName').'</em></td>'
+                    .'<td>&nbsp;<b>'.$sessionInfo['name'].'</b></td>'
+                    .'</tr>';
             }
         }
 
-        // end exercise list
-        // Hotpotatoes results
-        $hotpotatoes_exist = false;
+        $msg = get_lang('OpenQuestionsAttempted').'<br /><br />'
+            .get_lang('AttemptDetails').' : <br /><br />'
+            .'<table>'
+            .'<tr>'
+            .'<td><em>'.get_lang('CourseName').'</em></td>'
+            .'<td>&nbsp;<b>#course#</b></td>'
+            .'</tr>'
+            .$sessionData
+            .'<tr>'
+            .'<td>'.get_lang('TestAttempted').'</td>'
+            .'<td>&nbsp;#exercise#</td>'
+            .'</tr>'
+            .'<tr>'
+            .'<td>'.get_lang('StudentName').'</td>'
+            .'<td>&nbsp;#firstName# #lastName#</td>'
+            .'</tr>'
+            .'<tr>'
+            .'<td>'.get_lang('StudentEmail').'</td>'
+            .'<td>&nbsp;#mail#</td>'
+            .'</tr>'
+            .'</table>';
 
-        if ($is_allowedToEdit) {
-            $sql = "SELECT d.iid, d.path as path, d.comment as comment
-                    FROM $TBL_DOCUMENT d
-                    WHERE
-                        d.c_id = $courseId AND
-                        (d.path LIKE '%htm%') AND
-                        d.path  LIKE '".Database :: escape_string($uploadPath.'/%/%')."'
-                    LIMIT ".$from.",".$limit; // only .htm or .html files listed
-        } else {
-            $sql = "SELECT d.iid, d.path as path, d.comment as comment
-                    FROM $TBL_DOCUMENT d
-                    WHERE
-                        d.c_id = $courseId AND
-                        (d.path LIKE '%htm%') AND
-                        d.path  LIKE '".Database :: escape_string($uploadPath.'/%/%')."'
-                    LIMIT ".$from.",".$limit;
-        }
+        $open_question_list = null;
+        foreach ($question_list_answers as $item) {
+            $question = $item['question'];
+            $answer = $item['answer'];
+            $answer_type = $item['answer_type'];
 
-        $result = Database::query($sql);
-        $attribute = [];
-        while ($row = Database :: fetch_array($result, 'ASSOC')) {
-            $attribute['id'][] = $row['iid'];
-            $attribute['path'][] = $row['path'];
-            $attribute['comment'][] = $row['comment'];
+            if (!empty($question) && !empty($answer) && $answer_type == FREE_ANSWER) {
+                $open_question_list .=
+                    '<tr>'
+                    .'<td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Question').'</td>'
+                    .'<td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>'
+                    .'</tr>'
+                    .'<tr>'
+                    .'<td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Answer').'</td>'
+                    .'<td valign="top" bgcolor="#F3F3F3">'.$answer.'</td>'
+                    .'</tr>';
+            }
         }
 
-        $nbrActiveTests = 0;
-        if (isset($attribute['path']) && is_array($attribute['path'])) {
-            $hotpotatoes_exist = true;
-            foreach ($attribute['path'] as $key => $path) {
-                $item = '';
-                $title = GetQuizName($path, $documentPath);
-                if ($title == '') {
-                    $title = basename($path);
-                }
-
-                // prof only
-                if ($is_allowedToEdit) {
-                    $visibility = api_get_item_visibility(
-                        ['real_id' => $courseId],
-                        TOOL_DOCUMENT,
-                        $attribute['id'][$key],
-                        0
-                    );
+        if (!empty($open_question_list)) {
+            $msg .= '<p><br />'.get_lang('OpenQuestionsAttemptedAre').' :</p>'.
+                '<table width="730" height="136" border="0" cellpadding="3" cellspacing="3">';
+            $msg .= $open_question_list;
+            $msg .= '</table><br />';
 
-                    if (!empty($sessionId)) {
-                        if (0 == $visibility) {
-                            continue;
-                        }
+            $msg = str_replace('#exercise#', $this->exercise, $msg);
+            $msg = str_replace('#firstName#', $user_info['firstname'], $msg);
+            $msg = str_replace('#lastName#', $user_info['lastname'], $msg);
+            $msg = str_replace('#mail#', $user_info['email'], $msg);
+            $msg = str_replace(
+                '#course#',
+                Display::url($courseInfo['title'], $courseInfo['course_public_url'].'?id_session='.$sessionId),
+                $msg
+            );
 
-                        $visibility = api_get_item_visibility(
-                            ['real_id' => $courseId],
-                            TOOL_DOCUMENT,
-                            $attribute['id'][$key],
-                            $sessionId
-                        );
-                    }
+            if ($origin != 'learnpath') {
+                $msg .= '<br /><a href="#url#">'.get_lang('ClickToCommentAndGiveFeedback').'</a>';
+            }
+            $msg = str_replace('#url#', $url_email, $msg);
+            $subject = get_lang('OpenQuestionsAttempted');
 
-                    $item = Display::tag(
-                        'td',
-                        implode(PHP_EOL, [
-                            Display::return_icon('hotpotatoes_s.png', "HotPotatoes"),
-                            Display::url(
-                                $title,
-                                'showinframes.php?'.api_get_cidreq().'&'.http_build_query([
-                                    'file' => $path,
-                                    'uid' => $userId,
-                                ]),
-                                ['class' => $visibility == 0 ? 'text-muted' : null]
-                            ),
-                        ])
+            if (!empty($teachers)) {
+                foreach ($teachers as $user_id => $teacher_data) {
+                    MessageManager::send_message_simple(
+                        $user_id,
+                        $subject,
+                        $msg
                     );
+                }
+            }
+        }
+    }
 
-                    $item .= Display::tag('td', '-');
+    /**
+     * Send notification for oral questions.
+     *
+     * @param array  $question_list_answers
+     * @param string $origin
+     * @param int    $exe_id
+     * @param array  $user_info
+     * @param string $url_email
+     * @param array  $teachers
+     */
+    private function sendNotificationForOralQuestions(
+        $question_list_answers,
+        $origin,
+        $exe_id,
+        $user_info,
+        $url_email,
+        $teachers
+    ) {
+        // Email configuration settings
+        $courseCode = api_get_course_id();
+        $courseInfo = api_get_course_info($courseCode);
+        $oral_question_list = null;
+        foreach ($question_list_answers as $item) {
+            $question = $item['question'];
+            $file = $item['generated_oral_file'];
+            $answer = $item['answer'];
+            if ($answer == 0) {
+                $answer = '';
+            }
+            $answer_type = $item['answer_type'];
+            if (!empty($question) && (!empty($answer) || !empty($file)) && $answer_type == ORAL_EXPRESSION) {
+                if (!empty($file)) {
+                    $file = Display::url($file, $file);
+                }
+                $oral_question_list .= '<br />
+                    <table width="730" height="136" border="0" cellpadding="3" cellspacing="3">
+                    <tr>
+                        <td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Question').'</td>
+                        <td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>
+                    </tr>
+                    <tr>
+                        <td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Answer').'</td>
+                        <td valign="top" bgcolor="#F3F3F3">'.$answer.$file.'</td>
+                    </tr></table>';
+            }
+        }
 
-                    $actions = Display::url(
-                        Display::return_icon(
-                            'edit.png',
-                            get_lang('Edit'),
-                            '',
-                            ICON_SIZE_SMALL
-                        ),
-                        'adminhp.php?'.api_get_cidreq().'&hotpotatoesName='.$path
-                    );
+        if (!empty($oral_question_list)) {
+            $msg = get_lang('OralQuestionsAttempted').'<br /><br />
+                    '.get_lang('AttemptDetails').' : <br /><br />
+                    <table>
+                        <tr>
+                            <td><em>'.get_lang('CourseName').'</em></td>
+                            <td>&nbsp;<b>#course#</b></td>
+                        </tr>
+                        <tr>
+                            <td>'.get_lang('TestAttempted').'</td>
+                            <td>&nbsp;#exercise#</td>
+                        </tr>
+                        <tr>
+                            <td>'.get_lang('StudentName').'</td>
+                            <td>&nbsp;#firstName# #lastName#</td>
+                        </tr>
+                        <tr>
+                            <td>'.get_lang('StudentEmail').'</td>
+                            <td>&nbsp;#mail#</td>
+                        </tr>
+                    </table>';
+            $msg .= '<br />'.sprintf(get_lang('OralQuestionsAttemptedAreX'), $oral_question_list).'<br />';
+            $msg1 = str_replace("#exercise#", $this->exercise, $msg);
+            $msg = str_replace("#firstName#", $user_info['firstname'], $msg1);
+            $msg1 = str_replace("#lastName#", $user_info['lastname'], $msg);
+            $msg = str_replace("#mail#", $user_info['email'], $msg1);
+            $msg = str_replace("#course#", $courseInfo['name'], $msg1);
+
+            if (!in_array($origin, ['learnpath', 'embeddable'])) {
+                $msg .= '<br /><a href="#url#">'.get_lang('ClickToCommentAndGiveFeedback').'</a>';
+            }
+            $msg1 = str_replace("#url#", $url_email, $msg);
+            $mail_content = $msg1;
+            $subject = get_lang('OralQuestionsAttempted');
 
-                    $actions .= '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'">'.
-                        Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+            if (!empty($teachers)) {
+                foreach ($teachers as $user_id => $teacher_data) {
+                    MessageManager::send_message_simple(
+                        $user_id,
+                        $subject,
+                        $mail_content
+                    );
+                }
+            }
+        }
+    }
 
-                    // if active
-                    if ($visibility != 0) {
-                        $nbrActiveTests = $nbrActiveTests + 1;
-                        $actions .= '      <a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=disable&page='.$page.'&file='.$path.'">'.
-                            Display::return_icon('visible.png', get_lang('Deactivate'), '', ICON_SIZE_SMALL).'</a>';
-                    } else { // else if not active
-                        $actions .= '    <a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=enable&page='.$page.'&file='.$path.'">'.
-                            Display::return_icon('invisible.png', get_lang('Activate'), '', ICON_SIZE_SMALL).'</a>';
-                    }
-                    $actions .= '<a href="'.$exercisePath.'?'.api_get_cidreq().'&hpchoice=delete&file='.$path.'" onclick="javascript:if(!confirm(\''.addslashes(api_htmlentities(get_lang('AreYouSureToDeleteJS'), ENT_QUOTES, $charset).' '.$title."?").'\')) return false;">'.
-                        Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
-                    $item .= Display::tag('td', $actions);
-                    $tableRows[] = Display::tag('tr', $item);
+    /**
+     * Returns an array with the media list.
+     *
+     * @param array question list
+     *
+     * @example there's 1 question with iid 5 that belongs to the media question with iid = 100
+     * <code>
+     * array (size=2)
+     *  999 =>
+     *    array (size=3)
+     *      0 => int 7
+     *      1 => int 6
+     *      2 => int 3254
+     *  100 =>
+     *   array (size=1)
+     *      0 => int 5
+     *  </code>
+     */
+    private function setMediaList($questionList)
+    {
+        $mediaList = [];
+        /*
+         * Media feature is not activated in 1.11.x
+        if (!empty($questionList)) {
+            foreach ($questionList as $questionId) {
+                $objQuestionTmp = Question::read($questionId, $this->course_id);
+                // If a media question exists
+                if (isset($objQuestionTmp->parent_id) && $objQuestionTmp->parent_id != 0) {
+                    $mediaList[$objQuestionTmp->parent_id][] = $objQuestionTmp->id;
                 } else {
-                    $visibility = api_get_item_visibility(
-                        ['real_id' => $courseId],
-                        TOOL_DOCUMENT,
-                        $attribute['id'][$key],
-                        $sessionId
-                    );
+                    // Always the last item
+                    $mediaList[999][] = $objQuestionTmp->id;
+                }
+            }
+        }*/
 
-                    if (0 == $visibility) {
-                        continue;
-                    }
+        $this->mediaList = $mediaList;
+    }
 
-                    // Student only
-                    $attempt = ExerciseLib::getLatestHotPotatoResult(
-                        $path,
-                        $userId,
-                        api_get_course_int_id(),
-                        api_get_session_id()
-                    );
+    /**
+     * @param FormValidator $form
+     *
+     * @return HTML_QuickForm_group
+     */
+    private function setResultDisabledGroup(FormValidator $form)
+    {
+        $resultDisabledGroup = [];
 
-                    $nbrActiveTests = $nbrActiveTests + 1;
-                    $item .= Display::tag(
-                        'td',
-                        Display::url(
-                            $title,
-                            'showinframes.php?'.api_get_cidreq().'&'.http_build_query([
-                                'file' => $path,
-                                'cid' => api_get_course_id(),
-                                'uid' => $userId,
-                            ])
-                        )
-                    );
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('ShowScoreAndRightAnswer'),
+            '0',
+            ['id' => 'result_disabled_0']
+        );
 
-                    if (!empty($attempt)) {
-                        $actions = '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'&filter_by_user='.$userId.'">'.Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
-                        $attemptText = get_lang('LatestAttempt').' : ';
-                        $attemptText .= ExerciseLib::show_score(
-                                $attempt['exe_result'],
-                                $attempt['exe_weighting']
-                            ).' ';
-                        $attemptText .= $actions;
-                    } else {
-                        // No attempts.
-                        $attemptText = get_lang('NotAttempted').' ';
-                    }
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('DoNotShowScoreNorRightAnswer'),
+            '1',
+            ['id' => 'result_disabled_1', 'onclick' => 'check_results_disabled()']
+        );
 
-                    $item .= Display::tag('td', $attemptText);
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('OnlyShowScore'),
+            '2',
+            ['id' => 'result_disabled_2', 'onclick' => 'check_results_disabled()']
+        );
 
-                    if ($isDrhOfCourse) {
-                        $actions = '<a href="hotpotatoes_exercise_report.php?'.api_get_cidreq().'&path='.$path.'">'.
-                            Display::return_icon('test_results.png', get_lang('Results'), '', ICON_SIZE_SMALL).'</a>';
+        if ($this->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
+            $group = $form->addGroup(
+                $resultDisabledGroup,
+                null,
+                get_lang('ShowResultsToStudents')
+            );
 
-                        $item .= Display::tag(
-                            'td',
-                            $actions,
-                            ['class' => 'td_actions']
-                        );
-                    }
-                    $tableRows[] = Display::tag('tr', $item);
-                }
-            }
+            return $group;
         }
 
-        if (empty($tableRows)) {
-            if ($is_allowedToEdit && $origin != 'learnpath') {
-                $content .= '<div id="no-data-view">';
-                $content .= '<h3>'.get_lang('Quiz').'</h3>';
-                $content .= Display::return_icon('quiz.png', '', [], 64);
-                $content .= '<div class="controls">';
-                $content .= Display::url(
-                    '<em class="fa fa-plus"></em> '.get_lang('NewEx'),
-                    'exercise_admin.php?'.api_get_cidreq(),
-                    ['class' => 'btn btn-primary']
-                );
-                $content .= '</div>';
-                $content .= '</div>';
-            }
-        } else {
-            if ($is_allowedToEdit) {
-                $headers = [
-                    get_lang('ExerciseName'),
-                    get_lang('QuantityQuestions'),
-                    get_lang('Actions'),
-                ];
-            } else {
-                $headers = [
-                    get_lang('ExerciseName'),
-                    get_lang('Status'),
-                ];
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('ShowScoreEveryAttemptShowAnswersLastAttempt'),
+            '4',
+            ['id' => 'result_disabled_4']
+        );
 
-                if ($isDrhOfCourse) {
-                    $headers[] = get_lang('Actions');
-                }
-            }
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('DontShowScoreOnlyWhenUserFinishesAllAttemptsButShowFeedbackEachAttempt'),
+            '5',
+            ['id' => 'result_disabled_5', 'onclick' => 'check_results_disabled()']
+        );
 
-            foreach ($tableRows as $roz) {
-                echo $roz;
-            }
-var_dump($tableRows);
-            $content .= '<div class="table-responsive">';
-            $table = new SortableTableFromArrayConfig(
-                $tableRows,
-                1,
-                20,
-                'exercises'
-            );
-            $i = 0;
-            foreach ($headers as $header) {
-                $table->set_header($i++, $header);
-            }
-            $table->set_header($i++, 'aa');
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('ExerciseRankingMode'),
+            RESULT_DISABLE_RANKING,
+            ['id' => 'result_disabled_6']
+        );
 
-            $content .=  $table->return_table();
-            $content .= '</div>';
-        }
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('ExerciseShowOnlyGlobalScoreAndCorrectAnswers'),
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
+            ['id' => 'result_disabled_7']
+        );
 
-        return $content;
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('ExerciseAutoEvaluationAndRankingMode'),
+            RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS_AND_RANKING,
+            ['id' => 'result_disabled_8']
+        );
+
+        $group = $form->addGroup(
+            $resultDisabledGroup,
+            null,
+            get_lang('ShowResultsToStudents')
+        );
+
+        return $group;
     }
 }