Skip to content

Commit 3e450b4

Browse files
authored
Merge pull request #6092 from AngelFQC/BT22403
Add Pass/fail message & conditional session course subscription in tests - refs BT#22403
2 parents 44adc09 + df3bcf0 commit 3e450b4

File tree

8 files changed

+508
-323
lines changed

8 files changed

+508
-323
lines changed

main/exercise/exercise.class.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class Exercise
5151
public $review_answers;
5252
public $randomByCat;
5353
public $text_when_finished;
54+
public $text_when_finished_failure;
5455
public $display_category_name;
5556
public $pass_percentage;
5657
public $edit_exercise_in_lp = false;
@@ -127,6 +128,7 @@ public function __construct($courseId = 0)
127128
$this->review_answers = false;
128129
$this->randomByCat = 0;
129130
$this->text_when_finished = '';
131+
$this->text_when_finished_failure = '';
130132
$this->display_category_name = 0;
131133
$this->pass_percentage = 0;
132134
$this->modelType = 1;
@@ -204,6 +206,7 @@ public function read($id, $parseQuestionList = true)
204206
$this->saveCorrectAnswers = $object->save_correct_answers;
205207
$this->randomByCat = $object->random_by_category;
206208
$this->text_when_finished = $object->text_when_finished;
209+
$this->text_when_finished_failure = $object->text_when_finished_failure;
207210
$this->display_category_name = $object->display_category_name;
208211
$this->pass_percentage = $object->pass_percentage;
209212
$this->is_gradebook_locked = api_resource_is_locked_by_gradebook($id, LINK_EXERCISE);
@@ -456,6 +459,28 @@ public function updateTextWhenFinished($text)
456459
$this->text_when_finished = $text;
457460
}
458461

462+
/**
463+
* Get the text to display when the user has failed the test.
464+
*
465+
* @return string html text : the text to display ay the end of the test
466+
*/
467+
public function getTextWhenFinishedFailure(): string
468+
{
469+
if (empty($this->text_when_finished_failure)) {
470+
return '';
471+
}
472+
473+
return $this->text_when_finished_failure;
474+
}
475+
476+
/**
477+
* Set the text to display when the user has succeeded in the test.
478+
*/
479+
public function setTextWhenFinishedFailure(string $text): void
480+
{
481+
$this->text_when_finished_failure = $text;
482+
}
483+
459484
/**
460485
* return 1 or 2 if randomByCat.
461486
*
@@ -1599,6 +1624,7 @@ public function save($type_e = '')
15991624
$review_answers = isset($this->review_answers) && $this->review_answers ? 1 : 0;
16001625
$randomByCat = (int) $this->randomByCat;
16011626
$text_when_finished = $this->text_when_finished;
1627+
$text_when_finished_failure = $this->text_when_finished_failure;
16021628
$display_category_name = (int) $this->display_category_name;
16031629
$pass_percentage = (int) $this->pass_percentage;
16041630
$session_id = $this->sessionId;
@@ -1654,6 +1680,10 @@ public function save($type_e = '')
16541680
'hide_question_title' => $this->getHideQuestionTitle(),
16551681
];
16561682

1683+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
1684+
$paramsExtra['text_when_finished_failure'] = $text_when_finished_failure;
1685+
}
1686+
16571687
$allow = api_get_configuration_value('allow_quiz_show_previous_button_setting');
16581688
if ($allow === true) {
16591689
$paramsExtra['show_previous_button'] = $this->showPreviousButton();
@@ -1758,6 +1788,10 @@ public function save($type_e = '')
17581788
'hide_question_title' => $this->getHideQuestionTitle(),
17591789
];
17601790

1791+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
1792+
$params['text_when_finished_failure'] = $text_when_finished_failure;
1793+
}
1794+
17611795
$allow = api_get_configuration_value('allow_exercise_categories');
17621796
if (true === $allow) {
17631797
if (!empty($this->getExerciseCategoryId())) {
@@ -2505,6 +2539,16 @@ public function createForm($form, $type = 'full')
25052539
$editor_config
25062540
);
25072541

2542+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
2543+
$form->addHtmlEditor(
2544+
'text_when_finished_failure',
2545+
get_lang('TextAppearingAtTheEndOfTheTestWhenTheUserHasFailed'),
2546+
false,
2547+
false,
2548+
$editor_config
2549+
);
2550+
}
2551+
25082552
$allow = api_get_configuration_value('allow_notification_setting_per_exercise');
25092553
if ($allow === true) {
25102554
$settings = ExerciseLib::getNotificationSettings();
@@ -2572,6 +2616,7 @@ public function createForm($form, $type = 'full')
25722616
'notifications',
25732617
'remedialcourselist',
25742618
'advancedcourselist',
2619+
'subscribe_session_when_finished_failure',
25752620
], //exclude
25762621
false, // filter
25772622
false, // tag as select
@@ -2632,6 +2677,25 @@ public function createForm($form, $type = 'full')
26322677
}
26332678
}
26342679

2680+
if (true === api_get_configuration_value('exercise_subscribe_session_when_finished_failure')) {
2681+
$optionSessionWhenFailure = [];
2682+
2683+
if ($failureSession = ExerciseLib::getSessionWhenFinishedFailure($this->iid)) {
2684+
$defaults['subscribe_session_when_finished_failure'] = $failureSession->getId();
2685+
$optionSessionWhenFailure[$failureSession->getId()] = $failureSession->getName();
2686+
}
2687+
2688+
$form->addSelectAjax(
2689+
'extra_subscribe_session_when_finished_failure',
2690+
get_lang('SubscribeSessionWhenFinishedFailure'),
2691+
$optionSessionWhenFailure,
2692+
[
2693+
'url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?'
2694+
.http_build_query(['a' => 'search_session']),
2695+
]
2696+
);
2697+
}
2698+
26352699
$settings = api_get_configuration_value('exercise_finished_notification_settings');
26362700
if (!empty($settings)) {
26372701
$options = [];
@@ -2687,6 +2751,10 @@ public function createForm($form, $type = 'full')
26872751
$defaults['exercise_category_id'] = $this->getExerciseCategoryId();
26882752
$defaults['prevent_backwards'] = $this->getPreventBackwards();
26892753

2754+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
2755+
$defaults['text_when_finished_failure'] = $this->getTextWhenFinishedFailure();
2756+
}
2757+
26902758
if (!empty($this->start_time)) {
26912759
$defaults['activate_start_date_check'] = 1;
26922760
}
@@ -2715,6 +2783,11 @@ public function createForm($form, $type = 'full')
27152783
$defaults['results_disabled'] = 0;
27162784
$defaults['randomByCat'] = 0;
27172785
$defaults['text_when_finished'] = '';
2786+
2787+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
2788+
$defaults['text_when_finished_failure'] = '';
2789+
}
2790+
27182791
$defaults['start_time'] = date('Y-m-d 12:00:00');
27192792
$defaults['display_category_name'] = 1;
27202793
$defaults['end_time'] = date('Y-m-d 12:00:00', time() + 84600);
@@ -2886,6 +2959,11 @@ public function processCreation($form, $type = '')
28862959
$this->updateSaveCorrectAnswers($form->getSubmitValue('save_correct_answers'));
28872960
$this->updateRandomByCat($form->getSubmitValue('randomByCat'));
28882961
$this->updateTextWhenFinished($form->getSubmitValue('text_when_finished'));
2962+
2963+
if (true === api_get_configuration_value('exercise_text_when_finished_failure')) {
2964+
$this->setTextWhenFinishedFailure($form->getSubmitValue('text_when_finished_failure'));
2965+
}
2966+
28892967
$this->updateDisplayCategoryName($form->getSubmitValue('display_category_name'));
28902968
$this->updateReviewAnswers($form->getSubmitValue('review_answers'));
28912969
$this->updatePassPercentage($form->getSubmitValue('pass_percentage'));
@@ -11759,6 +11837,34 @@ public static function getFeedbackTypeLiteral(int $feedbackType): string
1175911837
return $result;
1176011838
}
1176111839

11840+
/**
11841+
* Return the text to display, based on the score and the max score.
11842+
*
11843+
* @param int|float $score
11844+
* @param int|float $maxScore
11845+
*/
11846+
public function getFinishText($score, $maxScore): string
11847+
{
11848+
if (true !== api_get_configuration_value('exercise_text_when_finished_failure')) {
11849+
return $this->getTextWhenFinished();
11850+
}
11851+
11852+
$passPercentage = $this->selectPassPercentage();
11853+
11854+
if (!empty($passPercentage)) {
11855+
$percentage = float_format(
11856+
($score / (0 != $maxScore ? $maxScore : 1)) * 100,
11857+
1
11858+
);
11859+
11860+
if ($percentage < $passPercentage) {
11861+
return $this->getTextWhenFinishedFailure();
11862+
}
11863+
}
11864+
11865+
return $this->getTextWhenFinished();
11866+
}
11867+
1176211868
/**
1176311869
* Get number of questions in exercise by user attempt.
1176411870
*

main/exercise/exercise_show.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,6 @@ function getFCK(vals, marksid) {
379379
$questionList = $question_list_from_database;
380380
}
381381

382-
// Display the text when finished message if we are on a LP #4227
383-
$end_of_message = $objExercise->getTextWhenFinished();
384-
if (!empty($end_of_message) && ($origin === 'learnpath')) {
385-
echo Display::return_message($end_of_message, 'normal', false);
386-
echo "<div class='clear'>&nbsp;</div>";
387-
}
388-
389382
// for each question
390383
$total_weighting = 0;
391384
foreach ($questionList as $questionId) {
@@ -884,6 +877,13 @@ class="exercise_mark_select"
884877
$exercise_content .= Display::panel($question_content);
885878
} // end of large foreach on questions
886879

880+
// Display the text when finished message if we are on a LP #4227
881+
$end_of_message = $objExercise->getFinishText($totalScore, $totalWeighting);
882+
if (!empty($end_of_message) && ($origin === 'learnpath')) {
883+
echo Display::return_message($end_of_message, 'normal', false);
884+
echo "<div class='clear'>&nbsp;</div>";
885+
}
886+
887887
$totalScoreText = '';
888888
if ($answerType != MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
889889
$pluginEvaluation = QuestionOptionsEvaluationPlugin::create();

main/inc/lib/exercise.lib.php

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/* For licensing terms, see /license.txt */
44

55
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
6+
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
67
use Chamilo\CoreBundle\Entity\TrackEExercises;
78
use Chamilo\CourseBundle\Entity\CQuizQuestion;
89
use ChamiloSession as Session;
@@ -5368,21 +5369,6 @@ public static function displayQuestionListByAttempt(
53685369
);
53695370
}
53705371

5371-
// Display text when test is finished #4074 and for LP #4227
5372-
// Allows to do a remove_XSS for end text result of exercise with
5373-
// user status COURSEMANAGERLOWSECURITY BT#20194
5374-
if (true === api_get_configuration_value('exercise_result_end_text_html_strict_filtering')) {
5375-
$endOfMessage = Security::remove_XSS($objExercise->getTextWhenFinished(), COURSEMANAGERLOWSECURITY);
5376-
} else {
5377-
$endOfMessage = Security::remove_XSS($objExercise->getTextWhenFinished());
5378-
}
5379-
if (!empty($endOfMessage)) {
5380-
echo Display::div(
5381-
$endOfMessage,
5382-
['id' => 'quiz_end_message']
5383-
);
5384-
}
5385-
53865372
$question_list_answers = [];
53875373
$category_list = [];
53885374
$loadChoiceFromSession = false;
@@ -5618,6 +5604,22 @@ public static function displayQuestionListByAttempt(
56185604
}
56195605
}
56205606

5607+
// Display text when test is finished #4074 and for LP #4227
5608+
// Allows to do a remove_XSS for end text result of exercise with
5609+
// user status COURSEMANAGERLOWSECURITY BT#20194
5610+
$finishMessage = $objExercise->getFinishText($total_score, $total_weight);
5611+
if (true === api_get_configuration_value('exercise_result_end_text_html_strict_filtering')) {
5612+
$endOfMessage = Security::remove_XSS($finishMessage, COURSEMANAGERLOWSECURITY);
5613+
} else {
5614+
$endOfMessage = Security::remove_XSS($finishMessage);
5615+
}
5616+
if (!empty($endOfMessage)) {
5617+
echo Display::div(
5618+
$endOfMessage,
5619+
['id' => 'quiz_end_message']
5620+
);
5621+
}
5622+
56215623
$totalScoreText = null;
56225624
$certificateBlock = '';
56235625
if (($show_results || $show_only_score) && $showTotalScore) {
@@ -5791,6 +5793,13 @@ public static function displayQuestionListByAttempt(
57915793
$total_weight
57925794
);
57935795

5796+
if ($save_user_result
5797+
&& !$passed
5798+
&& true === api_get_configuration_value('exercise_subscribe_session_when_finished_failure')
5799+
) {
5800+
self::subscribeSessionWhenFinishedFailure($objExercise->iid);
5801+
}
5802+
57945803
$percentage = 0;
57955804
if (!empty($total_weight)) {
57965805
$percentage = ($total_score / $total_weight) * 100;
@@ -5811,6 +5820,26 @@ public static function displayQuestionListByAttempt(
58115820
];
58125821
}
58135822

5823+
public static function getSessionWhenFinishedFailure(int $exerciseId): ?SessionEntity
5824+
{
5825+
$objExtraField = new ExtraField('exercise');
5826+
$objExtraFieldValue = new ExtraFieldValue('exercise');
5827+
5828+
$subsSessionWhenFailureField = $objExtraField->get_handler_field_info_by_field_variable(
5829+
'subscribe_session_when_finished_failure'
5830+
);
5831+
$subsSessionWhenFailureValue = $objExtraFieldValue->get_values_by_handler_and_field_id(
5832+
$exerciseId,
5833+
$subsSessionWhenFailureField['id']
5834+
);
5835+
5836+
if (!empty($subsSessionWhenFailureValue['value'])) {
5837+
return api_get_session_entity((int) $subsSessionWhenFailureValue['value']);
5838+
}
5839+
5840+
return null;
5841+
}
5842+
58145843
/**
58155844
* It validates unique score when all user answers are correct by question.
58165845
* It is used for global questions.
@@ -7373,4 +7402,18 @@ public static function exportExerciseAllResultsZip(
73737402

73747403
return false;
73757404
}
7405+
7406+
private static function subscribeSessionWhenFinishedFailure(int $exerciseId): void
7407+
{
7408+
$failureSession = self::getSessionWhenFinishedFailure($exerciseId);
7409+
7410+
if ($failureSession) {
7411+
SessionManager::subscribeUsersToSession(
7412+
$failureSession->getId(),
7413+
[api_get_user_id()],
7414+
SESSION_VISIBLE_READ_ONLY,
7415+
false
7416+
);
7417+
}
7418+
}
73767419
}

main/install/configuration.dist.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,6 +2555,19 @@
25552555
// Add more speed options to reading comprehension question type (type id = 21) in words per minute
25562556
//$_configuration['exercise_question_reading_comprehension_extra_speeds'] = ['speeds' => [70, 110, 170]];
25572557

2558+
// Text appearing at the end of the test when the user has failed. Requires DB changes.
2559+
/*
2560+
ALTER TABLE c_quiz ADD text_when_finished_failure LONGTEXT DEFAULT NULL;
2561+
*/
2562+
// Then add the "@" symbol to the CQuiz class in the ORM\Column() line for its $textWhenFinishedFailure property.
2563+
//$_configuration['exercise_text_when_finished_failure'] = false;
2564+
2565+
// Add an option to subscribe the user at the end of test when the user has failed. Requires DB changes.
2566+
/*
2567+
INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES (17, 5, 'subscribe_session_when_finished_failure', 'SubscribeSessionWhenFinishedFailure', '', 0, 1, 0, 1, 0, NOW());
2568+
*/
2569+
//$_configuration['exercise_subscribe_session_when_finished_failure'] = false;
2570+
25582571
//hide copy icon in LP's authoring options
25592572
//$_configuration['lp_hide_copy_option'] = false;
25602573

0 commit comments

Comments
 (0)