Browse Source

Update from 1.11.x

Julio Montoya 5 years ago
parent
commit
5d80e7d07f

+ 1 - 2
main/admin/user_list.php

@@ -1198,8 +1198,7 @@ if ($table->get_total_number_of_items() == 0) {
                 }
                 if ($add_user) {
                     $row_table = [];
-                    $row_table[] = api_get_person_name($user['firstname'],
-                            $user['lastname']).' ('.$user['username'].') ';
+                    $row_table[] = api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].') ';
                     $row_table[] = $access_info_to_string;
                     $url = api_get_self().'?action=add_user_to_my_url&user_id='.$user['id'].'&sec_token='.Security::getTokenFromSession();
                     $row_table[] = Display::url(

+ 8 - 0
main/course_info/infocours.php

@@ -844,14 +844,22 @@ if (api_get_setting('allow_public_certificates') === 'true') {
     );
 }
 
+// Forum settings
 $group = [
     $form->createElement('radio', 'enable_forum_auto_launch', null, get_lang('RedirectToForumList'), 1),
     $form->createElement('radio', 'enable_forum_auto_launch', null, get_lang('Disabled'), 2),
 ];
 $myButton = $form->addButtonSave(get_lang('SaveSettings'), 'submit_save', true);
 
+// Forum settings
+$groupNotification = [
+    $form->createElement('radio', 'hide_forum_notifications', null, get_lang('Yes'), 1),
+    $form->createElement('radio', 'hide_forum_notifications', null, get_lang('No'), 2),
+];
+
 $globalGroup = [
     get_lang('EnableForumAutoLaunch') => $group,
+    get_lang('HideForumNotifications') => $groupNotification,
     '' => $myButton,
 ];
 

+ 27 - 4
main/exercise/exercise.class.php

@@ -2366,6 +2366,17 @@ class Exercise
 
             $skillList = Skill::addSkillsToForm($form, ITEM_TYPE_EXERCISE, $this->iId);
 
+            /*$extraField = new ExtraField('exercise');
+            $extraField->addElements(
+                $form,
+                $this->iId,
+                [], //exclude
+                false, // filter
+                false, // tag as select
+                [], //show only fields
+                [], // order fields
+                [] // extra data
+            );*/
             $form->addElement('html', '</div>'); //End advanced setting
             $form->addElement('html', '</div>');
         }
@@ -2379,15 +2390,13 @@ class Exercise
 
         $form->addRule('exerciseTitle', get_lang('GiveExerciseName'), 'required');
 
+        // defaults
         if ($type == 'full') {
             // rules
             $form->addRule('exerciseAttempts', get_lang('Numeric'), 'numeric');
             $form->addRule('start_time', get_lang('InvalidDate'), 'datetime');
             $form->addRule('end_time', get_lang('InvalidDate'), 'datetime');
-        }
 
-        // defaults
-        if ($type == 'full') {
             if ($this->id > 0) {
                 //if ($this->random > $this->selectNbrQuestions()) {
                 //    $defaults['randomQuestions'] = $this->selectNbrQuestions();
@@ -2578,6 +2587,11 @@ class Exercise
 
         $iId = $this->save($type);
         if (!empty($iId)) {
+            /*$values = $form->getSubmitValues();
+            $values['item_id'] = $iId;
+            $extraFieldValue = new ExtraFieldValue('exercise');
+            $extraFieldValue->saveFieldValues($values);*/
+
             Skill::saveSkills($form, ITEM_TYPE_EXERCISE, $iId);
         }
     }
@@ -8574,10 +8588,19 @@ class Exercise
             'results_disabled',
             null,
             get_lang('ExerciseShowOnlyGlobalScoreAndCorrectAnswers'),
-            '7',
+            RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
             ['id' => 'result_disabled_7']
         );
 
+        $resultDisabledGroup[] = $form->createElement(
+            'radio',
+            'results_disabled',
+            null,
+            get_lang('AutoEvaluationAndRankingMode'),
+            RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
+            ['id' => 'result_disabled_8']
+        );
+
         $group = $form->addGroup(
             $resultDisabledGroup,
             null,

+ 2 - 0
main/exercise/exercise.php

@@ -1151,6 +1151,7 @@ if (!empty($exerciseList)) {
                                     RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
                                     RESULT_DISABLE_SHOW_SCORE_ONLY,
                                     RESULT_DISABLE_RANKING,
+                                    RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
                                 ]
                             )
                         ) {
@@ -1217,6 +1218,7 @@ if (!empty($exerciseList)) {
                                 RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
                                 RESULT_DISABLE_SHOW_SCORE_ONLY,
                                 RESULT_DISABLE_RANKING,
+                                RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
                             ]
                         )
                     ) {

+ 4 - 1
main/exercise/exercise_show.php

@@ -1026,7 +1026,10 @@ if (!empty($category_list) && ($show_results || $show_only_total_score || $showT
     );
 }
 
-if (RESULT_DISABLE_RANKING == $track_exercise_info['results_disabled']) {
+if (in_array(
+    $track_exercise_info['results_disabled'],
+    [RESULT_DISABLE_RANKING, RESULT_DISABLE_AUTOEVALUATION_AND_RANKING]
+)) {
     echo Display::page_header(get_lang('Ranking'), null, 'h4');
     echo ExerciseLib::displayResultsInRanking(
         $objExercise->iId,

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

@@ -234,8 +234,8 @@ class MultipleAnswer extends Question
         $header = parent::return_header($exercise, $counter, $score);
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
+        $header .= '<th>'.get_lang('Choice').'</th>';
         if ($exercise->results_disabled != RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER) {
-            $header .= '<th>'.get_lang('Choice').'</th>';
             $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
         }
 
@@ -243,6 +243,7 @@ class MultipleAnswer extends Question
         if ($exercise->showExpectedChoice()) {
             $header .= '<th>'.get_lang('Status').'</th>';
         }
+
         $header .= '<th>'.get_lang('Comment').'</th>';
         $header .= '</tr>';
 

+ 5 - 3
main/exercise/overview.php

@@ -219,9 +219,7 @@ if (!empty($attempts)) {
         );
         $attempt_url = api_get_path(WEB_CODE_PATH).'exercise/result.php?';
         $attempt_url .= api_get_cidreq().'&show_headers=1&';
-        $attempt_url .= http_build_query([
-            'id' => $attempt_result['exe_id'],
-        ]);
+        $attempt_url .= http_build_query(['id' => $attempt_result['exe_id']]);
         $attempt_url .= $url_suffix;
 
         $attempt_link = Display::url(
@@ -258,6 +256,7 @@ if (!empty($attempts)) {
                 RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK,
                 RESULT_DISABLE_RANKING,
                 RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
+                RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
             ]
         )) {
             $row['result'] = $score;
@@ -272,6 +271,7 @@ if (!empty($attempts)) {
                 RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK,
                 RESULT_DISABLE_RANKING,
                 RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
+                RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
             ]
         ) || (
             $objExercise->results_disabled == RESULT_DISABLE_SHOW_SCORE_ONLY &&
@@ -290,6 +290,7 @@ if (!empty($attempts)) {
                     unset($row['result']);
                 }
             }
+
             $row['attempt_link'] = $attempt_link;
         }
         $my_attempt_array[] = $row;
@@ -328,6 +329,7 @@ if (!empty($attempts)) {
             }
             break;
         case RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS:
+        case RESULT_DISABLE_AUTOEVALUATION_AND_RANKING:
         case RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES:
         case RESULT_DISABLE_RANKING:
             $header_names = [

+ 91 - 9
main/exercise/question_pool.php

@@ -114,7 +114,7 @@ if ($is_allowedToEdit) {
         unset($objQuestionTmp);
     } elseif ($recup && $fromExercise) {
         // gets an existing question and copies it into a new exercise
-        $objQuestionTmp = Question :: read($recup);
+        $objQuestionTmp = Question::read($recup);
         // if the question exists
         if ($objQuestionTmp) {
             /* Adds the exercise ID represented by $fromExercise into the list
@@ -209,10 +209,6 @@ $htmlHeadXtra[] = "
     }
 </script>";
 
-Display::display_header($nameTools, 'Exercise');
-
-// Menu
-echo '<div class="actions">';
 $url = api_get_self().'?'.api_get_cidreq().'&'.http_build_query(
     [
         'fromExercise' => $fromExercise,
@@ -229,6 +225,41 @@ $url = api_get_self().'?'.api_get_cidreq().'&'.http_build_query(
     ]
 );
 
+if (isset($_REQUEST['action'])) {
+    switch ($_REQUEST['action']) {
+        // Delete selected courses
+        case 'reuse':
+            if (!empty($_REQUEST['questions']) && !empty($fromExercise)) {
+                $questions = $_REQUEST['questions'];
+                $objExercise = new Exercise();
+                $objExercise->read($fromExercise, false);
+
+                if (count($questions) > 0) {
+                    foreach ($questions as $questionId) {
+                        // gets an existing question and copies it into a new exercise
+                        $objQuestionTmp = Question::read($questionId);
+                        // if the question exists
+                        if ($objQuestionTmp) {
+                            if ($objExercise->hasQuestion($questionId) === false) {
+                                $objExercise->addToList($questionId);
+                                $objQuestionTmp->addToList($fromExercise);
+                            }
+                        }
+                    }
+                }
+
+                Display::addFlash(Display::return_message(get_lang('Added')));
+                header('Location: '.$url);
+                exit;
+            }
+            break;
+    }
+}
+
+Display::display_header($nameTools, 'Exercise');
+
+// Menu
+echo '<div class="actions">';
 if (isset($fromExercise) && $fromExercise > 0) {
     echo '<a href="admin.php?'.api_get_cidreq().'&exerciseId='.$fromExercise.'">'.
             Display::return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM).'</a>';
@@ -791,6 +822,18 @@ if (is_array($mainQuestionList)) {
         }
         $sessionId = isset($question['session_id']) ? $question['session_id'] : null;
         $exerciseName = isset($question['exercise_name']) ? '<br />('.$question['exercise_id'].') ' : null;
+
+        if (!$objExercise->hasQuestion($question['id'])) {
+            $row[] = Display::input(
+                'checkbox',
+                'questions[]',
+                $question['id'],
+                ['class' => 'question_checkbox']
+            );
+        } else {
+            $row[] = '';
+        }
+
         $row[] = getLinkForQuestion(
             $questionTagA,
             $fromExercise,
@@ -838,6 +881,13 @@ if (is_array($mainQuestionList)) {
 
 // Display table
 $header = [
+    [
+        '',
+        false,
+        ['style' => 'text-align:center'],
+        ['style' => 'text-align:center'],
+        '',
+    ],
     [
         get_lang('QuestionUpperCaseFirstLetter'),
         false,
@@ -876,12 +926,44 @@ $header = [
 
 echo $pagination;
 
+echo '<form id="question_pool_id" method="get" action="'.$url.'">';
+echo '<input type="hidden" name="fromExercise" value="'.$fromExercise.'">';
+echo '<input type="hidden" name="cidReq" value="'.$_course['code'].'">';
 Display::display_sortable_table(
     $header,
     $data,
     '',
     ['per_page_default' => 999, 'per_page' => 999, 'page_nr' => 1]
 );
+echo '</form>';
+
+$tableId = 'question_pool_id';
+$html = '<div class="btn-toolbar">';
+$html .= '<div class="btn-group">';
+$html .= '<a class="btn btn-default" href="?'.$url.'selectall=1" onclick="javascript: setCheckbox(true, \''.$tableId.'\'); return false;">'.
+    get_lang('SelectAll').'</a>';
+$html .= '<a class="btn btn-default" href="?'.$url.'" onclick="javascript: setCheckbox(false, \''.$tableId.'\'); return false;">'.get_lang('UnSelectAll').'</a> ';
+$html .= '</div>';
+$html .= '<div class="btn-group">
+            <button class="btn btn-default" onclick="javascript:return false;">'.get_lang('Actions').'</button>
+            <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+                <span class="caret"></span>
+            </button>';
+$html .= '<ul class="dropdown-menu">';
+
+$actions = ['reuse' => get_lang('ReuseQuestion')];
+foreach ($actions as $action => &$label) {
+    $html .= '<li>
+                <a data-action ="'.$action.'" href="#" onclick="javascript:action_click(this, \''.$tableId.'\');">'.
+                    $label.'
+                </a>
+              </li>';
+}
+$html .= '</ul>';
+$html .= '</div>'; //btn-group
+$html .= '</div>'; //toolbar
+
+echo $html;
 
 Display::display_footer();
 
@@ -916,9 +998,9 @@ function reset_menu_exo_lvl_type()
  * return the <a> link to admin question, if needed.
  *
  * @param int    $in_addA
- * @param int    $in_fromex
+ * @param int    $fromExercise
  * @param int    $questionId
- * @param int    $questiontype
+ * @param int    $questionType
  * @param string $questionName
  * @param int    $sessionId
  * @param int    $exerciseId
@@ -949,7 +1031,7 @@ function getLinkForQuestion(
 
         $result = Display::url(
             $questionName.$sessionIcon,
-            "admin.php?".api_get_cidreq().
+            'admin.php?'.api_get_cidreq().
             "&exerciseId=$exerciseId&editQuestion=$questionId&type=$questionType&fromExercise=$fromExercise"
         );
     }
@@ -1015,7 +1097,7 @@ function get_action_icon_for_question(
                 $res = "<a href='".api_get_self()."?".
                     api_get_cidreq().$getParams."&recup=$in_questionid&fromExercise=$from_exercise'>";
                 $res .= Display::return_icon('view_more_stats.gif', get_lang('InsertALinkToThisQuestionInTheExercise'));
-                $res .= "</a>";
+                $res .= '</a>';
             }
             break;
         case 'clone':

+ 1 - 1
main/exercise/unique_answer.class.php

@@ -416,8 +416,8 @@ class UniqueAnswer extends Question
         $header = parent::return_header($exercise, $counter, $score);
         $header .= '<table class="'.$this->question_table_class.'"><tr>';
 
+        $header .= '<th>'.get_lang('Choice').'</th>';
         if ($exercise->results_disabled != RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER) {
-            $header .= '<th>'.get_lang('Choice').'</th>';
             $header .= '<th>'.get_lang('ExpectedChoice').'</th>';
         }
 

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

@@ -1856,15 +1856,17 @@ switch ($action) {
                 continue;
             }
             $skills = $obj->getSkillsByGradebook($item['id']);
+            $courseId = $item['c_id'];
+            $courseInfo = api_get_course_info_by_id($courseId);
 
             //Fixes bug when gradebook doesn't have names
             if (empty($item['name'])) {
-                $item['name'] = $item['course_code'];
+                $item['name'] = $courseInfo['code'];
             }
 
             $item['name'] = Display::url(
                 $item['name'],
-                api_get_path(WEB_CODE_PATH).'gradebook/index.php?id_session=0&cidReq='.$item['course_code']
+                api_get_path(WEB_CODE_PATH).'gradebook/index.php?id_session=0&cidReq='.$courseInfo['code']
             );
 
             if (!empty($item['certif_min_score']) && !empty($item['document_id'])) {

+ 1 - 0
main/inc/lib/AnnouncementManager.php

@@ -1,6 +1,7 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CoreBundle\Entity\ExtraField as ExtraFieldEntity;
 use Chamilo\CoreBundle\Entity\ExtraFieldValues;
 use Chamilo\CourseBundle\Entity\CAnnouncement;
 use Chamilo\CourseBundle\Entity\CItemProperty;

+ 29 - 12
main/inc/lib/api.lib.php

@@ -478,6 +478,7 @@ define('RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT', 4);
 define('RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK', 5);
 define('RESULT_DISABLE_RANKING', 6);
 define('RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER', 7);
+define('RESULT_DISABLE_AUTOEVALUATION_AND_RANKING', 8);
 
 // 4: Show final score only with  and show expected answers only on the last attempt
 
@@ -6371,7 +6372,7 @@ function api_get_current_access_url_id()
             return -1;
         }
 
-        return $access_url_id;
+        return (int) $access_url_id;
     }
 
     //if the url in WEB_PATH was not found, it can only mean that there is
@@ -8925,11 +8926,17 @@ function api_mail_html(
  */
 function api_protect_course_group($tool, $showHeader = true)
 {
-    $userId = api_get_user_id();
     $groupId = api_get_group_id();
-    $groupInfo = GroupManager::get_group_properties($groupId);
+    if (!empty($groupId)) {
+        $userId = api_get_user_id();
+        $groupInfo = GroupManager::get_group_properties($groupId);
+
+        // Group doesn't exists
+        if (empty($groupInfo)) {
+            api_not_allowed($showHeader);
+        }
 
-    if (!empty($groupInfo)) {
+        // Check group access
         $allow = GroupManager::user_has_access(
             $userId,
             $groupInfo['iid'],
@@ -9450,24 +9457,34 @@ function api_get_language_translate_html()
     $languageList = api_get_languages();
     $hideAll = '';
     foreach ($languageList['all'] as $language) {
-        $hideAll .=
-            '$("span:lang('.$language['isocode'].')").filter(
-                function() {
-                    // Ignore ckeditor classes
-                    return !this.className.match(/cke(.*)/);
-            }).hide();';
+        $hideAll .= '
+        $("span:lang('.$language['isocode'].')").filter(
+            function(e, val) {
+                // Only find the spans if they have set the lang                
+                if ($(this).attr("lang") == null) {                
+                    return false;
+                }
+                
+                // Ignore ckeditor classes
+                return !this.className.match(/cke(.*)/);
+        }).hide();'."\n";
     }
 
     $userInfo = api_get_user_info();
     $languageId = api_get_language_id($userInfo['language']);
     $languageInfo = api_get_language_info($languageId);
+    $isoCode = 'en';
+
+    if (!empty($languageInfo)) {
+        $isoCode = $languageInfo['isocode'];
+    }
 
     return '
             $(function() {
                 '.$hideAll.'                 
-                var defaultLanguageFromUser = "'.$languageInfo['isocode'].'";   
+                var defaultLanguageFromUser = "'.$isoCode.'";   
                                              
-                $("span:lang('.$languageInfo['isocode'].')").filter(
+                $("span:lang('.$isoCode.')").filter(
                     function() {
                         // Ignore ckeditor classes
                         return !this.className.match(/cke(.*)/);

+ 1 - 0
main/inc/lib/course.lib.php

@@ -1666,6 +1666,7 @@ class CourseManager
                                 $sessionId
                             )
                         );
+
                         $report_info['progress_100'] = $progress == 100 ? Display::label(get_lang('Yes'), 'success') : Display::label(get_lang('No'));
                         $report_info['progress'] = $progress."%";
 

+ 19 - 11
main/inc/lib/exercise.lib.php

@@ -2793,7 +2793,7 @@ HOTSPOT;
      * @param string $thousandSeparator
      * @param bool   $roundValues           This option rounds the float values into a int using ceil()
      *
-     * @return array an html with the score modified
+     * @return string an html with the score modified
      */
     public static function show_score(
         $score,
@@ -4426,11 +4426,14 @@ EOT;
         // Hide results
         $show_results = false;
         $show_only_score = false;
-        if ($objExercise->results_disabled == RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS) {
-            $show_results = true;
-        }
 
-        if ($objExercise->results_disabled == RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER) {
+        if (in_array($objExercise->results_disabled,
+            [
+                RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER,
+                RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS,
+                RESULT_DISABLE_AUTOEVALUATION_AND_RANKING,
+            ]
+        )) {
             $show_results = true;
         }
 
@@ -4497,7 +4500,9 @@ EOT;
                 }
             }
 
-            if ($objExercise->results_disabled == RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK) {
+            if ($objExercise->results_disabled ==
+                RESULT_DISABLE_DONT_SHOW_SCORE_ONLY_IF_USER_FINISHES_ATTEMPTS_SHOW_ALWAYS_FEEDBACK
+            ) {
                 $show_only_score = false;
                 $show_results = true;
                 $show_all_but_expected_answer = false;
@@ -4510,7 +4515,7 @@ EOT;
             }
         }
 
-        if (($show_results || $show_only_score) && $origin != 'embeddable') {
+        if (($show_results || $show_only_score) && $origin !== 'embeddable') {
             if (isset($exercise_stat_info['exe_user_id'])) {
                 $user_info = api_get_user_info($exercise_stat_info['exe_user_id']);
                 if ($user_info) {
@@ -4524,9 +4529,9 @@ EOT;
         }
 
         // Display text when test is finished #4074 and for LP #4227
-        $end_of_message = $objExercise->selectTextWhenFinished();
-        if (!empty($end_of_message)) {
-            echo Display::return_message($end_of_message, 'normal', false);
+        $endOfMessage = $objExercise->selectTextWhenFinished();
+        if (!empty($endOfMessage)) {
+            echo Display::return_message($endOfMessage, 'normal', false);
             echo "<div class='clear'>&nbsp;</div>";
         }
 
@@ -4856,7 +4861,10 @@ EOT;
             }
         }
 
-        if (RESULT_DISABLE_RANKING == $objExercise->selectResultsDisabled()) {
+        if (in_array(
+            $objExercise->selectResultsDisabled(),
+            [RESULT_DISABLE_RANKING, RESULT_DISABLE_AUTOEVALUATION_AND_RANKING]
+        )) {
             echo Display::page_header(get_lang('Ranking'), null, 'h4');
             echo self::displayResultsInRanking(
                 $objExercise->iId,

+ 13 - 6
main/inc/lib/exercise_show_functions.lib.php

@@ -341,11 +341,12 @@ class ExerciseShowFunctions
         $showComment = false;
         switch ($resultsDisabled) {
             case RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER:
-                $hideStudentChoice = true;
+                $hideStudentChoice = false;
                 $hide_expected_answer = true;
                 $status = Display::label(get_lang('Correct'), 'success');
                 $showComment = true;
-                if (!$answerCorrect) {
+                //var_dump($answerCorrect."-".$studentChoice ." - ".$answerCorrectChoice);
+                if (!$answerCorrect && empty($studentChoice)) {
                     return '';
                 }
                 break;
@@ -370,7 +371,14 @@ class ExerciseShowFunctions
         $iconAnswer .= $answerCorrect ? '_on' : '_off';
         $iconAnswer .= '.png';
 
-        echo '<tr>';
+        $studentChoiceClass = '';
+        if ($resultsDisabled == RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER) {
+            if ($answerCorrect) {
+                $studentChoiceClass = 'success';
+            }
+        }
+
+        echo '<tr class="'.$studentChoiceClass.'">';
         if ($hideStudentChoice === false) {
             echo '<td width="5%">';
             echo Display::return_icon($icon, null, null, ICON_SIZE_TINY);
@@ -396,7 +404,7 @@ class ExerciseShowFunctions
         if ($feedbackType != EXERCISE_FEEDBACK_TYPE_EXAM && $studentChoice) {
             $showComment = true;
             if (!$answerCorrect && $resultsDisabled == RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER) {
-                $showComment = false;
+                // $showComment = false;
             }
         }
 
@@ -452,7 +460,7 @@ class ExerciseShowFunctions
         $hideStudentChoice = false;
         switch ($resultsDisabled) {
             case RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER:
-                $hideStudentChoice = true;
+                $hideStudentChoice = false;
                 $hide_expected_answer = true;
                 break;
             case RESULT_DISABLE_SHOW_SCORE_ONLY:
@@ -470,7 +478,6 @@ class ExerciseShowFunctions
         }
 
         $content = '<tr>';
-
         if ($hideStudentChoice === false) {
             $content .= '<td width="5%">';
             $course_id = api_get_course_int_id();

+ 4 - 0
main/inc/lib/extra_field.lib.php

@@ -118,6 +118,9 @@ class ExtraField extends Model
                 $this->extraFieldType = EntityExtraField::SESSION_FIELD_TYPE;
                 $this->primaryKey = 'id';
                 break;
+            case 'exercise':
+                $this->extraFieldType = EntityExtraField::EXERCISE_FIELD_TYPE;
+                break;
             case 'question':
                 $this->extraFieldType = EntityExtraField::QUESTION_FIELD_TYPE;
                 break;
@@ -190,6 +193,7 @@ class ExtraField extends Model
             'terms_and_condition',
             'forum_category',
             'forum_post',
+            'exercise',
         ];
 
         if (api_get_configuration_value('allow_scheduled_announcements')) {

+ 1 - 14
main/inc/lib/pdf.lib.php

@@ -62,20 +62,7 @@ class PDF
         $this->params['pdf_date'] = isset($params['pdf_date']) ? $params['pdf_date'] : api_format_date($localTime, DATE_TIME_FORMAT_LONG);
         $this->params['pdf_date_only'] = isset($params['pdf_date']) ? $params['pdf_date'] : api_format_date($localTime, DATE_FORMAT_LONG);
 
-        /*$this->pdf = new Mpdf(
-            'UTF-8',
-            $pageFormat,
-            '',
-            '',
-            $params['left'],
-            $params['right'],
-            $params['top'],
-            $params['bottom'],
-            8,
-            8,
-            $orientation
-        );*/
-        $params = [
+         $params = [
             'tempDir' => api_get_path(SYS_ARCHIVE_PATH).'mpdf',
             'mode' => 'utf-8',
             'format' => $pageFormat,

+ 5 - 3
main/inc/lib/sessionmanager.lib.php

@@ -513,8 +513,8 @@ class SessionManager
         $isMakingOrder = false;
         $showCountUsers = false;
 
-        if ($getCount == true) {
-            $select = " SELECT count(DISTINCT s.id) as total_rows";
+        if ($getCount === true) {
+            $select = ' SELECT count(DISTINCT s.id) as total_rows ';
         } else {
             if (!empty($columns['column_model'])) {
                 foreach ($columns['column_model'] as $column) {
@@ -1861,7 +1861,9 @@ class SessionManager
         $empty_users = true,
         $registerUsersToAllCourses = true
     ) {
-        if ($sessionId != strval(intval($sessionId))) {
+        $sessionId = (int) $sessionId;
+
+        if (empty($sessionId)) {
             return false;
         }
 

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

@@ -3170,7 +3170,8 @@ class SocialManager extends UserManager
             }
         } else {
             // Load my groups
-            $results = $userGroup->get_groups_by_user($userId,
+            $results = $userGroup->get_groups_by_user(
+                $userId,
                 [
                     GROUP_USER_PERMISSION_ADMIN,
                     GROUP_USER_PERMISSION_READER,

+ 14 - 7
main/inc/lib/sortable_table.class.php

@@ -1054,23 +1054,30 @@ class SortableTableFromArray extends SortableTable
     /**
      * Constructor.
      *
-     * @param array $table_data
-     * @param int   $default_column
-     * @param int   $default_items_per_page
+     * @param array  $table_data
+     * @param int    $default_column
+     * @param int    $default_items_per_page
+     * @param string $tableName
+     * @param string $get_total_number_function
+     * @param string $tableId
+     *
      */
     public function __construct(
         $table_data,
         $default_column = 1,
         $default_items_per_page = 20,
-        $tablename = 'tablename',
-        $get_total_number_function = null
+        $tableName = 'tablename',
+        $get_total_number_function = null,
+        $tableId = ''
     ) {
         parent:: __construct(
-            $tablename,
+            $tableName,
             $get_total_number_function,
             null,
             $default_column,
-            $default_items_per_page
+            $default_items_per_page,
+            null,
+            $tableId
         );
         $this->table_data = $table_data;
     }

+ 3 - 3
main/inc/lib/tracking.lib.php

@@ -272,7 +272,7 @@ class Tracking
 
         $result_disabled_ext_all = true;
         $chapterTypes = learnpath::getChapterTypes();
-
+        $accessToPdfExport = api_is_allowed_to_edit(false, false, true);
         // Show lp items
         if (is_array($list) && count($list) > 0) {
             foreach ($list as $my_item_id) {
@@ -419,7 +419,7 @@ class Tracking
                                     Display::return_icon('visible.png', get_lang('HideAttemptView')),
                                     api_get_self().'?action=stats&extend_id='.$my_item_id.'&fold_attempt_id='.$row['iv_id'].$url_suffix
                                 );
-                                if (api_is_allowed_to_edit()) {
+                                if ($accessToPdfExport) {
                                     $extend_attempt_link .= '&nbsp;'.
                                         Display::url(
                                             Display::return_icon('pdf.png', get_lang('ExportToPdf')),
@@ -433,7 +433,7 @@ class Tracking
                                     Display::return_icon('invisible.png', get_lang('ExtendAttemptView')),
                                     api_get_self().'?action=stats&extend_id='.$my_item_id.'&extend_attempt_id='.$row['iv_id'].$url_suffix
                                 );
-                                if (api_is_allowed_to_edit()) {
+                                if ($accessToPdfExport) {
                                     $extend_attempt_link .= '&nbsp;'.
                                         Display::url(
                                             Display::return_icon('pdf.png', get_lang('ExportToPdf')),

+ 3 - 3
main/lang/arabic/trad4all.inc.php

@@ -681,7 +681,7 @@ $NewUserEmailAlertToTeacharAndTutor = "ارسل بريد للمدرس والمع
 $NewUserEmailAlertDisable = "عدم اخطار المدرس بخصوص التسجيل التلقائي";
 $PressAgain = "اضغط 'خزن' مرة أخرى";
 $Rights = "حقوق الإستخدام";
-$Version = "النسخة";
+$Version = "الاصدار";
 $StatusTip = "اختر من القائمة";
 $CreatedSize = "تم إنشاءها , الحجم";
 $AuthorTip = "بتنسيق VCARD";
@@ -1858,7 +1858,7 @@ $SurveyEmailSenderNoReplyComment = "إذا أرسلت رسالة بالبريد
 $CourseCoachEmailSender = "عنوان البريد الإلكتروني للمدرب / المعلم";
 $NoReplyEmailSender = "لا عنوان إجابة البريد إلكتروني";
 $OpenIdAuthenticationComment = "تمكين التوثيق المفتوح المعتمد على معرف المواقع URL( عرض دخول إضافي من الصفحة الرئيسية )";
-$VersionCheckEnabled = "يمكن  فحص النسخة";
+$VersionCheckEnabled = "تم تمكين فحص الاصدار";
 $InstallDirAccessibleSecurityThreat = "الدليل الرئيسي / المؤقت  لنظام دوكيوس سهل الوصول إلى مستخدمي  الويب. وهذا قد يمثل  تهديد أمنِي لتنصيبك.  ولذلك نوصيك بأن تزيل هذا الدليلِ أَو تغير ترخيصه حتى لايستطيع مستخدمي  الويب استعمال المستندات التي تحتوي عليه.";
 $GradebookActivation = "تنشيط أداة Gradebook";
 $GradebookActivationComment = "تمكين اداة gradebook  تمنح امكانية ضبط  اهداف ونتائج التعلم , لكن اذا كنت لاتحتاجها ستصبح واجهة الاداة غير ضرورية . هل تريد تمكين هذه الاداة ؟";
@@ -2470,7 +2470,7 @@ $LearnpathLessonTitle = "عنوان الخطوة";
 $LearnpathStatus = "الحالة";
 $LearnpathScore = "النقاط";
 $LearnpathTime = "الوقت";
-$LearnpathVersion = "النسخة";
+$LearnpathVersion = "الاصدار";
 $LearnpathRestarted = "كل الخطوات حاليا غير مكتملة";
 $LearnpathNoNext = "هذه هي الخطوة الأخيرة.";
 $LearnpathNoPrev = "هذه هي الخطوة الأولى.";

+ 6 - 0
main/lang/english/trad4all.inc.php

@@ -8399,4 +8399,10 @@ $WelcomeToPortalXInCourseSessionX = "Welcome to portal %s Course session: %s";
 $WelcomeToPortalXInCourseSessionXCoursePartOfCareerX = "Welcome to portal %s in course %s, part of career %s";
 $YourNextModule = "Your next module";
 $FirstLesson = "First lesson";
+$ImportCourseTeachersAsCourseCoach = "Import course teachers as course coach in the session";
+$ResumeImport = "Resume import";
+$Candidate = "Candidate";
+$GeneralTotal = "General total";
+$Domains = "Domains";
+$ScormStartAttemptDate = "Date";
 ?>

+ 6 - 0
main/lang/french/trad4all.inc.php

@@ -8331,4 +8331,10 @@ $WelcomeToPortalXInCourseSessionX = "Bienvenue sur le portail %s, Cours/session:
 $WelcomeToPortalXInCourseSessionXCoursePartOfCareerX = "Bienvenue sur le portail %s dans le cours %s qui fait partie de la carrière %s";
 $YourNextModule = "Votre module suivant";
 $FirstLesson = "Première leçon";
+$ImportCourseTeachersAsCourseCoach = "Importer les professeurs du cours comme tuteur du cours dans la session";
+$ResumeImport = "Continuer l'import";
+$Candidate = "Candidat";
+$GeneralTotal = "Total général";
+$Domains = "Domaines";
+$ScormStartAttemptDate = "Date";
 ?>

+ 6 - 0
main/lang/spanish/trad4all.inc.php

@@ -8427,4 +8427,10 @@ $WelcomeToPortalXInCourseSessionX = "Bienvenid@ en el portal %s, Curso/sesión:
 $WelcomeToPortalXInCourseSessionXCoursePartOfCareerX = "Bienvenid@ en el portal %s en el curso %s, parte de la carrera %s";
 $YourNextModule = "Su próximo módulo";
 $FirstLesson = "Primera lección";
+$ImportCourseTeachersAsCourseCoach = "Importar los profesores del curso como tutores del curso en la session";
+$ResumeImport = "Reanudar importación";
+$Candidate = "Candidato";
+$GeneralTotal = "Total general";
+$Domains = "Dominios";
+$ScormStartAttemptDate = "Fecha";
 ?>

+ 1 - 1
main/mySpace/lp_tracking.php

@@ -83,7 +83,7 @@ $origin = 'tracking';
 $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
 switch ($action) {
     case 'export_stats':
-        if (!api_is_allowed_to_edit()) {
+        if (!api_is_allowed_to_edit(false, false, true)) {
             api_not_allowed();
         }
         $tpl = new Template(null, false, false);

+ 4 - 0
main/mySpace/myStudents.php

@@ -917,6 +917,10 @@ if ($details == 'true') {
     $userInfo['time_spent_course'] = $time_spent_on_the_course;
 }
 
+$icon = '';
+$timeLegalAccept = '';
+$btn = '';
+
 if (api_get_setting('allow_terms_conditions') === 'true') {
     $isBoss = UserManager::userIsBossOfStudent(api_get_user_id(), $student_id);
     if ($isBoss || api_is_platform_admin()) {