Add setting "allow_quiz_question_feedback" requires DB change

- ALTER TABLE c_quiz_question ADD COLUMN feedback text;

See BT#12611
pull/2487/head
jmontoyaa 9 years ago
parent f8434d72c3
commit 41c164230f
  1. 13
      main/exercise/Annotation.php
  2. 23
      main/exercise/Draggable.php
  3. 23
      main/exercise/MatchingDraggable.php
  4. 2
      main/exercise/ReadingComprehension.php
  5. 13
      main/exercise/UniqueAnswerImage.php
  6. 20
      main/exercise/admin.php
  7. 14
      main/exercise/calculated_answer.class.php
  8. 5
      main/exercise/exercise.class.php
  9. 2
      main/exercise/exercise_result.php
  10. 6
      main/exercise/exercise_show.php
  11. 7
      main/exercise/export/aiken/aiken_classes.php
  12. 1
      main/exercise/export/exercise_import.inc.php
  13. 9
      main/exercise/export/qti2/qti2_classes.php
  14. 10
      main/exercise/export/scorm/scorm_classes.php
  15. 18
      main/exercise/fill_blanks.class.php
  16. 11
      main/exercise/freeanswer.class.php
  17. 14
      main/exercise/global_multiple_answer.class.php
  18. 30
      main/exercise/hotspot.class.php
  19. 16
      main/exercise/matching.class.php
  20. 21
      main/exercise/multiple_answer.class.php
  21. 14
      main/exercise/multiple_answer_combination.class.php
  22. 37
      main/exercise/multiple_answer_true_false.class.php
  23. 16
      main/exercise/oral_expression.class.php
  24. 126
      main/exercise/question.class.php
  25. 13
      main/exercise/question_admin.inc.php
  26. 2
      main/exercise/result.php
  27. 24
      main/exercise/unique_answer.class.php
  28. 21
      main/exercise/unique_answer_no_option.class.php
  29. 15
      main/inc/lib/exercise.lib.php
  30. 2
      main/install/configuration.dist.php

@ -27,12 +27,11 @@ class Annotation extends Question
} }
/** /**
* @param FormValidator $form * @inheritdoc
* @param int $fck_config
*/ */
public function createForm(&$form, $fck_config = 0) public function createForm(&$form, $exercise)
{ {
parent::createForm($form, $fck_config); parent::createForm($form, $exercise);
$form->addElement( $form->addElement(
'number', 'number',
@ -115,11 +114,11 @@ class Annotation extends Question
} }
/** /**
* @param FormValidator $form * @inheritdoc
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$this->weighting = $form->getSubmitValue('weighting'); $this->weighting = $form->getSubmitValue('weighting');
$this->save(); $this->save($exercise);
} }
} }

@ -29,9 +29,7 @@ class Draggable extends Question
$defaults = array(); $defaults = array();
$nb_matches = $nb_options = 2; $nb_matches = $nb_options = 2;
$matches = array(); $matches = array();
$answer = null; $answer = null;
if ($form->isSubmitted()) { if ($form->isSubmitted()) {
$nb_matches = $form->getSubmitValue('nb_matches'); $nb_matches = $form->getSubmitValue('nb_matches');
$nb_options = $form->getSubmitValue('nb_options'); $nb_options = $form->getSubmitValue('nb_options');
@ -174,29 +172,24 @@ class Draggable extends Question
} }
/** /**
* Abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$this->extra = $form->exportValue('orientation'); $this->extra = $form->exportValue('orientation');
$nb_matches = $form->getSubmitValue('nb_matches'); $nb_matches = $form->getSubmitValue('nb_matches');
$this->weighting = 0; $this->weighting = 0;
$position = 0; $position = 0;
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
// Insert the options // Insert the options
for ($i = 1; $i <= $nb_matches; ++$i) { for ($i = 1; $i <= $nb_matches; ++$i) {
$position++; $position++;
$objAnswer->createAnswer($position, 0, '', 0, $position); $objAnswer->createAnswer($position, 0, '', 0, $position);
} }
// Insert the answers // Insert the answers
for ($i = 1; $i <= $nb_matches; ++$i) { for ($i = 1; $i <= $nb_matches; ++$i) {
$position++; $position++;
$answer = $form->getSubmitValue('answer['.$i.']'); $answer = $form->getSubmitValue('answer['.$i.']');
$matches = $form->getSubmitValue('matches['.$i.']'); $matches = $form->getSubmitValue('matches['.$i.']');
$weighting = $form->getSubmitValue('weighting['.$i.']'); $weighting = $form->getSubmitValue('weighting['.$i.']');
@ -211,19 +204,15 @@ class Draggable extends Question
} }
$objAnswer->save(); $objAnswer->save();
$this->save(); $this->save($exercise);
} }
/** /**
* Shows question title an description * @inheritdoc
* @param string $feedback_type
* @param int $counter
* @param float $score
* @return string
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>' . get_lang('ElementList').'</th> <th>' . get_lang('ElementList').'</th>

@ -17,7 +17,6 @@ class MatchingDraggable extends Question
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->type = MATCHING_DRAGGABLE; $this->type = MATCHING_DRAGGABLE;
$this->isContent = $this->getIsContent(); $this->isContent = $this->getIsContent();
} }
@ -30,10 +29,8 @@ class MatchingDraggable extends Question
$defaults = array(); $defaults = array();
$nb_matches = $nb_options = 2; $nb_matches = $nb_options = 2;
$matches = array(); $matches = array();
$answer = null; $answer = null;
$counter = 1; $counter = 1;
if (isset($this->id)) { if (isset($this->id)) {
$answer = new Answer($this->id); $answer = new Answer($this->id);
$answer->read(); $answer->read();
@ -60,7 +57,7 @@ class MatchingDraggable extends Question
$nb_matches++; $nb_matches++;
$nb_options++; $nb_options++;
} }
} else if (!empty($this->id)) { } elseif (!empty($this->id)) {
if (count($answer->nbrAnswers) > 0) { if (count($answer->nbrAnswers) > 0) {
$nb_matches = $nb_options = 0; $nb_matches = $nb_options = 0;
for ($i = 1; $i <= $answer->nbrAnswers; $i++) { for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
@ -224,16 +221,14 @@ class MatchingDraggable extends Question
} }
/** /**
* Process the creation of answers * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$nb_matches = $form->getSubmitValue('nb_matches'); $nb_matches = $form->getSubmitValue('nb_matches');
$nb_options = $form->getSubmitValue('nb_options'); $nb_options = $form->getSubmitValue('nb_options');
$this->weighting = 0; $this->weighting = 0;
$position = 0; $position = 0;
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
// Insert the options // Insert the options
@ -260,19 +255,15 @@ class MatchingDraggable extends Question
); );
} }
$objAnswer->save(); $objAnswer->save();
$this->save(); $this->save($exercise);
} }
/** /**
* Shows question title an description * @inheritdoc
* @param string $feedback_type
* @param int $counter
* @param float $score
* @return string The header HTML code
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>' . get_lang('ElementList').'</th> <th>' . get_lang('ElementList').'</th>

@ -136,7 +136,7 @@ class ReadingComprehension extends UniqueAnswer
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function createForm(&$form) public function createForm(&$form, $exercise)
{ {
// Categories // Categories
$tabCat = TestCategory::getCategoriesIdAndName(); $tabCat = TestCategory::getCategoriesIdAndName();

@ -274,7 +274,10 @@ class UniqueAnswerImage extends UniqueAnswer
$form->setConstants(array('nb_answers' => $numberAnswers)); $form->setConstants(array('nb_answers' => $numberAnswers));
} }
public function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$correct = $form->getSubmitValue('correct'); $correct = $form->getSubmitValue('correct');
@ -361,12 +364,6 @@ class UniqueAnswerImage extends UniqueAnswer
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
public function return_header($feedback_type = null, $counter = null, $score = null)
{
return parent::return_header($feedback_type, $counter, $score);
}
} }

@ -292,9 +292,15 @@ if (!empty($gradebook) && $gradebook == 'view') {
$interbreadcrumb[] = array("url" => "exercise.php", "name" => get_lang('Exercises')); $interbreadcrumb[] = array("url" => "exercise.php", "name" => get_lang('Exercises'));
if (isset($_GET['newQuestion']) || isset($_GET['editQuestion'])) { if (isset($_GET['newQuestion']) || isset($_GET['editQuestion'])) {
$interbreadcrumb[] = ["url" => "admin.php?exerciseId=".$objExercise->id, "name" => $objExercise->selectTitle(true)]; $interbreadcrumb[] = [
"url" => "admin.php?exerciseId=".$objExercise->id,
"name" => $objExercise->selectTitle(true),
];
} else { } else {
$interbreadcrumb[] = ["url" => "#", "name" => $objExercise->selectTitle(true)]; $interbreadcrumb[] = [
"url" => "#",
"name" => $objExercise->selectTitle(true),
];
} }
// shows a link to go back to the question pool // shows a link to go back to the question pool
@ -314,7 +320,6 @@ if ($modifyIn == 'thisExercise') {
} }
} }
$htmlHeadXtra[] = '<script> $htmlHeadXtra[] = '<script>
function multiple_answer_true_false_onchange(variable) { function multiple_answer_true_false_onchange(variable) {
var result = variable.checked; var result = variable.checked;
var id = variable.id; var id = variable.id;
@ -385,11 +390,10 @@ if ($inATest) {
Display::return_icon('settings.png', get_lang('ModifyExercise'), '', ICON_SIZE_MEDIUM).'</a>'; Display::return_icon('settings.png', get_lang('ModifyExercise'), '', ICON_SIZE_MEDIUM).'</a>';
$maxScoreAllQuestions = 0; $maxScoreAllQuestions = 0;
//$questionList = $objExercise->getQuestionList();
$questionList = $objExercise->selectQuestionList(true, true); $questionList = $objExercise->selectQuestionList(true, true);
if (!empty($questionList)) { if (!empty($questionList)) {
foreach ($questionList as $q) { foreach ($questionList as $questionItemId) {
$question = Question::read($q); $question = Question::read($questionItemId);
if ($question) { if ($question) {
$maxScoreAllQuestions += $question->selectWeighting(); $maxScoreAllQuestions += $question->selectWeighting();
} }
@ -415,7 +419,7 @@ if ($inATest) {
} }
echo '</div>'; echo '</div>';
} else if (isset($_GET['newQuestion'])) { } elseif (isset($_GET['newQuestion'])) {
// we are in create a new question from question pool not in a test // we are in create a new question from question pool not in a test
echo '<div class="actions">'; echo '<div class="actions">';
echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/admin.php?'.api_get_cidreq().'">'. echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/admin.php?'.api_get_cidreq().'">'.
@ -466,7 +470,7 @@ if ($newQuestion || $editQuestion) {
if (isset($_GET['hotspotadmin'])) { if (isset($_GET['hotspotadmin'])) {
if (!is_object($objQuestion)) { if (!is_object($objQuestion)) {
$objQuestion = Question :: read($_GET['hotspotadmin']); $objQuestion = Question::read($_GET['hotspotadmin']);
} }
if (!$objQuestion) { if (!$objQuestion) {
api_not_allowed(); api_not_allowed();

@ -183,10 +183,9 @@ class CalculatedAnswer extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
if (!self::isAnswered()) { if (!self::isAnswered()) {
$table = Database::get_course_table(TABLE_QUIZ_ANSWER); $table = Database::get_course_table(TABLE_QUIZ_ANSWER);
@ -247,14 +246,11 @@ class CalculatedAnswer extends Question
} }
/** /**
* @param null $feedback_type * @inheritdoc
* @param null $counter
* @param null $score
* @return null|string
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Answer").'</th> <th>'.get_lang("Answer").'</th>

@ -73,6 +73,8 @@ class Exercise
public $emailAlert; public $emailAlert;
public $notifyUserByEmail = ''; public $notifyUserByEmail = '';
public $sessionId = 0; public $sessionId = 0;
public $questionFeedbackEnabled = false;
public $questionTypeWithFeedback;
/** /**
* Constructor of the class * Constructor of the class
@ -115,6 +117,9 @@ class Exercise
} }
$this->course_id = $course_info['real_id']; $this->course_id = $course_info['real_id'];
$this->course = $course_info; $this->course = $course_info;
// ALTER TABLE c_quiz_question ADD COLUMN feedback text;
$this->questionFeedbackEnabled = api_get_configuration_value('allow_quiz_question_feedback');
} }
/** /**

@ -177,7 +177,7 @@ $max_score = $objExercise->get_max_score();
echo Display::return_message(get_lang('Saved').'<br />', 'normal', false); echo Display::return_message(get_lang('Saved').'<br />', 'normal', false);
// Display and save questions // Display and save questions
ExerciseLib::display_question_list_by_attempt( ExerciseLib::displayQuestionListByAttempt(
$objExercise, $objExercise,
$exe_id, $exe_id,
true, true,

@ -850,7 +850,11 @@ foreach ($questionList as $questionId) {
if ($show_results) { if ($show_results) {
//Shows question title an description //Shows question title an description
$question_content .= $objQuestionTmp->return_header(null, $counter, $score); $question_content .= $objQuestionTmp->return_header(
$objExercise,
$counter,
$score
);
} }
$counter++; $counter++;
$question_content .= $contents; $question_content .= $contents;

@ -31,12 +31,15 @@ class Aiken2Question extends Question
return $answer; return $answer;
} }
function createAnswersForm($form) public function createAnswersForm($form)
{ {
return true; return true;
} }
function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
return true; return true;
} }

@ -178,6 +178,7 @@ function import_exercise($file)
$last_exercise_id = $exercise->selectId(); $last_exercise_id = $exercise->selectId();
$courseId = api_get_course_int_id(); $courseId = api_get_course_int_id();
if (!empty($last_exercise_id)) { if (!empty($last_exercise_id)) {
//var_dump($exercise_info);exit;
// For each question found... // For each question found...
foreach ($exercise_info['question'] as $question_array) { foreach ($exercise_info['question'] as $question_array) {
//2. Create question //2. Create question

@ -53,12 +53,15 @@ class Ims2Question extends Question
return $answer; return $answer;
} }
function createAnswersForm($form) public function createAnswersForm($form)
{ {
return true; return true;
} }
function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
return true; return true;
} }
@ -234,7 +237,7 @@ class ImsAnswerMatching extends Answer
$i = 0; $i = 0;
if (is_array($this->rightList)) { if (is_array($this->rightList)) {
foreach ($this->rightList as $rightKey=>$rightElement) { foreach ($this->rightList as $rightKey => $rightElement) {
$out .= '<simpleAssociableChoice identifier="right_'.$i.'" > $out .= '<simpleAssociableChoice identifier="right_'.$i.'" >
<![CDATA['.formatExerciseQtiTitle($rightElement['answer']).']]> <![CDATA['.formatExerciseQtiTitle($rightElement['answer']).']]>
</simpleAssociableChoice>'. "\n"; </simpleAssociableChoice>'. "\n";

@ -135,12 +135,18 @@ class ScormQuestion extends Question
return array($js, $html); return array($js, $html);
} }
function createAnswersForm($form) /**
* @inheritdoc
*/
public function createAnswersForm($form)
{ {
return true; return true;
} }
function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
return true; return true;
} }

@ -346,10 +346,9 @@ class FillBlanks extends Question
} }
/** /**
* Function which creates the form to create/edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$answer = $form->getSubmitValue('answer'); $answer = $form->getSubmitValue('answer');
// Due the ckeditor transform the elements to their HTML value // Due the ckeditor transform the elements to their HTML value
@ -372,7 +371,7 @@ class FillBlanks extends Question
// remove spaces at the beginning and the end of text in square brackets // remove spaces at the beginning and the end of text in square brackets
$answer = preg_replace_callback( $answer = preg_replace_callback(
"/".$blankStartSeparatorRegexp."[^]]+".$blankEndSeparatorRegexp."/", "/".$blankStartSeparatorRegexp."[^]]+".$blankEndSeparatorRegexp."/",
function($matches) use ($blankStartSeparator, $blankEndSeparator) { function ($matches) use ($blankStartSeparator, $blankEndSeparator) {
$matchingResult = $matches[0]; $matchingResult = $matches[0];
$matchingResult = trim($matchingResult, $blankStartSeparator); $matchingResult = trim($matchingResult, $blankStartSeparator);
$matchingResult = trim($matchingResult, $blankEndSeparator); $matchingResult = trim($matchingResult, $blankEndSeparator);
@ -457,21 +456,18 @@ class FillBlanks extends Question
$is_multiple = $form -> getSubmitValue('multiple_answer'); $is_multiple = $form -> getSubmitValue('multiple_answer');
$answer .= '@'.$is_multiple; $answer .= '@'.$is_multiple;
$this->save(); $this->save($exercise);
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
$objAnswer->createAnswer($answer, 0, '', 0, 1); $objAnswer->createAnswer($answer, 0, '', 0, 1);
$objAnswer->save(); $objAnswer->save();
} }
/** /**
* @param null $feedback_type * @inheritdoc
* @param null $counter
* @param null $score
* @return string
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Answer").'</th> <th>'.get_lang("Answer").'</th>

@ -42,22 +42,21 @@ class FreeAnswer extends Question
} }
/** /**
* abstract function which creates the form to create/edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$this->weighting = $form->getSubmitValue('weighting'); $this->weighting = $form->getSubmitValue('weighting');
$this->save(); $this->save($exercise);
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function return_header($feedback_type = null, $counter = null, $score = []) public function return_header($exercise, $counter = null, $score = [])
{ {
$score['revised'] = $this->isQuestionWaitingReview($score); $score['revised'] = $this->isQuestionWaitingReview($score);
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'" > $header .= '<table class="'.$this->question_table_class.'" >
<tr> <tr>
<th>' . get_lang("Answer").'</th> <th>' . get_lang("Answer").'</th>

@ -200,10 +200,9 @@ class GlobalMultipleAnswer extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
$nb_answers = $form->getSubmitValue('nb_answers'); $nb_answers = $form->getSubmitValue('nb_answers');
@ -254,15 +253,18 @@ class GlobalMultipleAnswer extends Question
// sets the total weighting of the question --> sert <EFBFBD> donner le score total pendant l'examen // sets the total weighting of the question --> sert <EFBFBD> donner le score total pendant l'examen
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
/**
* @inheritdoc
*/
public function return_header( public function return_header(
$feedback_type = null, $exercise,
$counter = null, $counter = null,
$score = null $score = null
) { ) {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>' . get_lang("Choice").'</th> <th>' . get_lang("Choice").'</th>

@ -30,12 +30,11 @@ class HotSpot extends Question
} }
/** /**
* @param FormValidator $form * @inheritdoc
* @param int $fck_config */
*/ public function createForm(&$form, $exercise)
public function createForm(&$form, $fck_config = 0)
{ {
parent::createForm($form, $fck_config); parent::createForm($form, $exercise);
if (!isset($_GET['editQuestion'])) { if (!isset($_GET['editQuestion'])) {
$icon = Display::return_icon( $icon = Display::return_icon(
@ -100,7 +99,10 @@ class HotSpot extends Question
// nothing // nothing
} }
function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
// nothing // nothing
} }
@ -120,12 +122,15 @@ class HotSpotDelineation extends HotSpot
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this -> type = HOT_SPOT_DELINEATION; $this->type = HOT_SPOT_DELINEATION;
} }
public function createForm(&$form, $fck_config = 0) /**
* @inheritdoc
*/
public function createForm(&$form, $exercise)
{ {
parent::createForm($form, $fck_config); parent::createForm($form);
} }
public function processCreation($form, $objExercise = null) public function processCreation($form, $objExercise = null)
@ -139,8 +144,11 @@ class HotSpotDelineation extends HotSpot
parent::createAnswersForm($form); parent::createAnswersForm($form);
} }
public function processAnswersCreation($form) /**
* @inheritdoc
*/
public function processAnswersCreation($form, $exercise)
{ {
parent::processAnswersCreation($form); parent::processAnswersCreation($form, $exercise);
} }
} }

@ -239,10 +239,9 @@ class Matching extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$nb_matches = $form->getSubmitValue('nb_matches'); $nb_matches = $form->getSubmitValue('nb_matches');
$nb_options = $form->getSubmitValue('nb_options'); $nb_options = $form->getSubmitValue('nb_options');
@ -274,18 +273,15 @@ class Matching extends Question
); );
} }
$objAnswer->save(); $objAnswer->save();
$this->save(); $this->save($exercise);
} }
/** /**
* @param null $feedback_type * @inheritdoc
* @param null $counter
* @param null $score
* @return string
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'">'; $header .= '<table class="'.$this->question_table_class.'">';
$header .= '<tr> $header .= '<tr>
<th>'.get_lang('ElementList').'</th> <th>'.get_lang('ElementList').'</th>

@ -182,19 +182,17 @@ class MultipleAnswer extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param the formvalidator instance
* @param the answers number to display
*/ */
function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
$nb_answers = $form->getSubmitValue('nb_answers'); $nb_answers = $form->getSubmitValue('nb_answers');
for ($i = 1; $i <= $nb_answers; $i++) { for ($i = 1; $i <= $nb_answers; $i++) {
$answer = trim(str_replace(['<p>', '</p>'], '', $form -> getSubmitValue('answer['.$i.']'))); $answer = trim(str_replace(['<p>', '</p>'], '', $form->getSubmitValue('answer['.$i.']')));
$comment = trim(str_replace(['<p>', '</p>'], '', $form -> getSubmitValue('comment['.$i.']'))); $comment = trim(str_replace(['<p>', '</p>'], '', $form->getSubmitValue('comment['.$i.']')));
$weighting = trim($form -> getSubmitValue('weighting['.$i.']')); $weighting = trim($form -> getSubmitValue('weighting['.$i.']'));
$goodAnswer = trim($form -> getSubmitValue('correct['.$i.']')); $goodAnswer = trim($form -> getSubmitValue('correct['.$i.']'));
@ -221,12 +219,15 @@ class MultipleAnswer extends Question
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
function return_header($feedback_type = null, $counter = null, $score = null) /**
* @inheritdoc
*/
public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Choice").'</th> <th>'.get_lang("Choice").'</th>

@ -177,10 +177,9 @@ class MultipleAnswerCombination extends Question
} }
/** /**
* abstract function which creates the form to create/edit the answers of the question * @inheritdoc
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
@ -219,12 +218,15 @@ class MultipleAnswerCombination extends Question
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
function return_header($feedback_type = null, $counter = null, $score = null) /**
* @inheritdoc
*/
public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Choice").'</th> <th>'.get_lang("Choice").'</th>

@ -235,15 +235,13 @@ class MultipleAnswerTrueFalse extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param FormValidator $form */
*/ public function processAnswersCreation($form, $exercise)
public function processAnswersCreation($form)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$objAnswer = new Answer($this->id); $objAnswer = new Answer($this->id);
$nb_answers = $form->getSubmitValue('nb_answers'); $nb_answers = $form->getSubmitValue('nb_answers');
//$options_count = $form->getSubmitValue('options_count');
$course_id = api_get_course_int_id(); $course_id = api_get_course_int_id();
$correct = array(); $correct = array();
@ -273,7 +271,7 @@ class MultipleAnswerTrueFalse extends Question
$new_options = Question::readQuestionOption($this->id, $course_id); $new_options = Question::readQuestionOption($this->id, $course_id);
$sorted_by_position = array(); $sorted_by_position = array();
foreach ($new_options as $item) { foreach ($new_options as $item) {
$sorted_by_position[$item['position']] = $item; $sorted_by_position[$item['position']] = $item;
} }
/* Saving quiz_question.extra values that has the correct scores of /* Saving quiz_question.extra values that has the correct scores of
@ -295,7 +293,7 @@ class MultipleAnswerTrueFalse extends Question
// change the default values from the form 1 and 2 by the correct "option id" registered // change the default values from the form 1 and 2 by the correct "option id" registered
$goodAnswer = $sorted_by_position[$goodAnswer]['id']; $goodAnswer = $sorted_by_position[$goodAnswer]['id'];
} }
$questionWeighting += $extra_values[0]; //By default 0 has the correct answers $questionWeighting += $extra_values[0]; //By default 0 has the correct answers
$objAnswer->createAnswer($answer, $goodAnswer, $comment, '', $i); $objAnswer->createAnswer($answer, $goodAnswer, $comment, '', $i);
} }
@ -303,28 +301,25 @@ class MultipleAnswerTrueFalse extends Question
$objAnswer->save(); $objAnswer->save();
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
/** /**
* @param int $feedback_type * @inheritdoc
* @param int $counter
* @param float $score
* @return null|string
*/ */
function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Choice").'</th> <th>'.get_lang("Choice").'</th>
<th>'. get_lang("ExpectedChoice").'</th> <th>'. get_lang("ExpectedChoice").'</th>
<th>'. get_lang("Answer").'</th>'; <th>'. get_lang("Answer").'</th>';
if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) { if ($exercise->feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
$header .= '<th>'.get_lang("Comment").'</th>'; $header .= '<th>'.get_lang("Comment").'</th>';
} else { } else {
$header .= '<th>&nbsp;</th>'; $header .= '<th>&nbsp;</th>';
} }
$header .= '</tr>'; $header .= '</tr>';
return $header; return $header;
} }

@ -55,25 +55,21 @@ class OralExpression extends Question
} }
/** /**
* abstract function which creates the form to create / edit the answers of the question * @inheritdoc
* @param the FormValidator $form
*/ */
function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$this->weighting = $form->getSubmitValue('weighting'); $this->weighting = $form->getSubmitValue('weighting');
$this->save(); $this->save($exercise);
} }
/** /**
* @param null $feedback_type * @inheritdoc
* @param null $counter
* @param null $score
* @return null|string
*/ */
public function return_header($feedback_type = null, $counter = null, $score = null) public function return_header($exercise, $counter = null, $score = null)
{ {
$score['revised'] = $this->isQuestionWaitingReview($score); $score['revised'] = $this->isQuestionWaitingReview($score);
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>&nbsp;</th> <th>&nbsp;</th>

@ -1,10 +1,12 @@
<?php <?php
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use Chamilo\CourseBundle\Entity\CQuizAnswer;
/** /**
* Class Question * Class Question
* *
* This class allows to instantiate an object of type Question * This class allows to instantiate an object of type Question
* *
* @author Olivier Brouckaert, original author * @author Olivier Brouckaert, original author
* @author Patrick Cool, LaTeX support * @author Patrick Cool, LaTeX support
@ -28,9 +30,11 @@ abstract class Question
public $category; public $category;
public $isContent; public $isContent;
public $course; public $course;
public $feedback;
public static $typePicture = 'new_question.png'; public static $typePicture = 'new_question.png';
public static $explanationLangVar = ''; public static $explanationLangVar = '';
public $question_table_class = 'table table-striped'; public $question_table_class = 'table table-striped';
public $questionTypeWithFeedback;
public static $questionTypes = array( public static $questionTypes = array(
UNIQUE_ANSWER => array('unique_answer.class.php', 'UniqueAnswer'), UNIQUE_ANSWER => array('unique_answer.class.php', 'UniqueAnswer'),
MULTIPLE_ANSWER => array('multiple_answer.class.php', 'MultipleAnswer'), MULTIPLE_ANSWER => array('multiple_answer.class.php', 'MultipleAnswer'),
@ -79,6 +83,12 @@ abstract class Question
$this->course = api_get_course_info(); $this->course = api_get_course_info();
$this->category_list = array(); $this->category_list = array();
$this->parent_id = 0; $this->parent_id = 0;
$this->questionTypeWithFeedback = [
MATCHING,
MATCHING_DRAGGABLE,
DRAGGABLE,
FILL_IN_BLANKS
];
} }
/** /**
@ -107,7 +117,6 @@ abstract class Question
public static function read($id, $course_id = null) public static function read($id, $course_id = null)
{ {
$id = intval($id); $id = intval($id);
if (!empty($course_id)) { if (!empty($course_id)) {
$course_info = api_get_course_info_by_id($course_id); $course_info = api_get_course_info_by_id($course_id);
} else { } else {
@ -123,10 +132,9 @@ abstract class Question
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$sql = "SELECT question, description, ponderation, position, type, picture, level, extra $sql = "SELECT *
FROM $TBL_QUESTIONS FROM $TBL_QUESTIONS
WHERE c_id = $course_id AND id = $id "; WHERE c_id = $course_id AND id = $id ";
$result = Database::query($sql); $result = Database::query($sql);
// if the question has been found // if the question has been found
@ -143,6 +151,7 @@ abstract class Question
$objQuestion->level = (int) $object->level; $objQuestion->level = (int) $object->level;
$objQuestion->extra = $object->extra; $objQuestion->extra = $object->extra;
$objQuestion->course = $course_info; $objQuestion->course = $course_info;
$objQuestion->feedback = isset($object->feedback) ? $object->feedback : '';
$objQuestion->category = TestCategory::getCategoryForQuestion($id); $objQuestion->category = TestCategory::getCategoryForQuestion($id);
$tblQuiz = Database::get_course_table(TABLE_QUIZ_TEST); $tblQuiz = Database::get_course_table(TABLE_QUIZ_TEST);
@ -881,7 +890,8 @@ abstract class Question
} }
/** /**
* Sets the title * Set title
* @param string $title
*/ */
public function setTitle($title) public function setTitle($title)
{ {
@ -902,13 +912,14 @@ abstract class Question
* if an exercise ID is provided, we add that exercise ID into the exercise list * if an exercise ID is provided, we add that exercise ID into the exercise list
* *
* @author Olivier Brouckaert * @author Olivier Brouckaert
* @param integer $exerciseId - exercise ID if saving in an exercise * @param Exercise $exercise
*/ */
public function save($exerciseId = 0) public function save($exercise)
{ {
$TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$em = Database::getManager(); $em = Database::getManager();
$exerciseId = $exercise->id;
$id = $this->id; $id = $this->id;
$question = $this->question; $question = $this->question;
@ -934,6 +945,9 @@ abstract class Question
'extra' => $extra, 'extra' => $extra,
'level' => $level, 'level' => $level,
]; ];
if ($exercise->questionFeedbackEnabled) {
$params['feedback'] = $this->feedback;
}
Database::update( Database::update(
$TBL_QUESTIONS, $TBL_QUESTIONS,
$params, $params,
@ -952,7 +966,7 @@ abstract class Question
} }
if (api_get_setting('search_enabled') == 'true') { if (api_get_setting('search_enabled') == 'true') {
if ($exerciseId != 0) { if ($exerciseId != 0) {
$this -> search_engine_edit($exerciseId); $this->search_engine_edit($exerciseId);
} else { } else {
/** /**
* actually there is *not* an user interface for * actually there is *not* an user interface for
@ -987,6 +1001,10 @@ abstract class Question
'level' => $level 'level' => $level
]; ];
if ($exercise->questionFeedbackEnabled) {
$params['feedback'] = $this->feedback;
}
$this->id = Database::insert($TBL_QUESTIONS, $params); $this->id = Database::insert($TBL_QUESTIONS, $params);
if ($this->id) { if ($this->id) {
@ -1003,7 +1021,7 @@ abstract class Question
// If hotspot, create first answer // If hotspot, create first answer
if ($type == HOT_SPOT || $type == HOT_SPOT_ORDER) { if ($type == HOT_SPOT || $type == HOT_SPOT_ORDER) {
$quizAnswer = new \Chamilo\CourseBundle\Entity\CQuizAnswer(); $quizAnswer = new CQuizAnswer();
$quizAnswer $quizAnswer
->setCId($c_id) ->setCId($c_id)
->setQuestionId($this->id) ->setQuestionId($this->id)
@ -1029,7 +1047,7 @@ abstract class Question
} }
if ($type == HOT_SPOT_DELINEATION) { if ($type == HOT_SPOT_DELINEATION) {
$quizAnswer = new \Chamilo\CourseBundle\Entity\CQuizAnswer(); $quizAnswer = new CQuizAnswer();
$quizAnswer $quizAnswer
->setCId($c_id) ->setCId($c_id)
->setQuestionId($this->id) ->setQuestionId($this->id)
@ -1523,7 +1541,6 @@ abstract class Question
if (!is_null($type)) { if (!is_null($type)) {
list($file_name, $class_name) = self::get_question_type($type); list($file_name, $class_name) = self::get_question_type($type);
if (!empty($file_name)) { if (!empty($file_name)) {
include_once $file_name;
if (class_exists($class_name)) { if (class_exists($class_name)) {
return new $class_name(); return new $class_name();
} else { } else {
@ -1539,8 +1556,9 @@ abstract class Question
* Creates the form to create / edit a question * Creates the form to create / edit a question
* A subclass can redefine this function to add fields... * A subclass can redefine this function to add fields...
* @param FormValidator $form * @param FormValidator $form
* @param Exercise $exercise
*/ */
public function createForm(&$form) public function createForm(&$form, $exercise)
{ {
echo '<style> echo '<style>
.media { display:none;} .media { display:none;}
@ -1563,7 +1581,14 @@ abstract class Question
// question name // question name
if (api_get_configuration_value('save_titles_as_html')) { if (api_get_configuration_value('save_titles_as_html')) {
$editorConfig = ['ToolbarSet' => 'Minimal']; $editorConfig = ['ToolbarSet' => 'Minimal'];
$form->addHtmlEditor('questionName', get_lang('Question'), false, false, $editorConfig, true); $form->addHtmlEditor(
'questionName',
get_lang('Question'),
false,
false,
$editorConfig,
true
);
} else { } else {
$form->addElement('text', 'questionName', get_lang('Question')); $form->addElement('text', 'questionName', get_lang('Question'));
} }
@ -1589,7 +1614,13 @@ abstract class Question
$form->addButtonAdvancedSettings('advanced_params'); $form->addButtonAdvancedSettings('advanced_params');
$form->addElement('html', '<div id="advanced_params_options" style="display:none">'); $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
$form->addHtmlEditor('questionDescription', get_lang('QuestionDescription'), false, false, $editorConfig); $form->addHtmlEditor(
'questionDescription',
get_lang('QuestionDescription'),
false,
false,
$editorConfig
);
// hidden values // hidden values
$my_id = isset($_REQUEST['myid']) ? intval($_REQUEST['myid']) : null; $my_id = isset($_REQUEST['myid']) ? intval($_REQUEST['myid']) : null;
@ -1669,12 +1700,20 @@ abstract class Question
} }
} }
if (!is_null($exercise)) {
if ($exercise->questionFeedbackEnabled && $this->showFeedback($exercise)) {
$form->addTextarea('feedback', get_lang('FeedbackIfCorrect'));
}
}
// default values // default values
$defaults = array(); $defaults = array();
$defaults['questionName'] = $this->question; $defaults['questionName'] = $this->question;
$defaults['questionDescription'] = $this->description; $defaults['questionDescription'] = $this->description;
$defaults['questionLevel'] = $this->level; $defaults['questionLevel'] = $this->level;
$defaults['questionCategory'] = $this->category; $defaults['questionCategory'] = $this->category;
$defaults['feedback'] = $this->feedback;
// Came from he question pool // Came from he question pool
if (isset($_GET['fromExercise'])) { if (isset($_GET['fromExercise'])) {
@ -1693,22 +1732,23 @@ abstract class Question
/** /**
* function which process the creation of questions * function which process the creation of questions
* @param FormValidator $form * @param FormValidator $form
* @param Exercise $objExercise * @param Exercise $exercise
*/ */
public function processCreation($form, $objExercise = null) public function processCreation($form, $exercise)
{ {
$this->updateTitle($form->getSubmitValue('questionName')); $this->updateTitle($form->getSubmitValue('questionName'));
$this->updateDescription($form->getSubmitValue('questionDescription')); $this->updateDescription($form->getSubmitValue('questionDescription'));
$this->updateLevel($form->getSubmitValue('questionLevel')); $this->updateLevel($form->getSubmitValue('questionLevel'));
$this->updateCategory($form->getSubmitValue('questionCategory')); $this->updateCategory($form->getSubmitValue('questionCategory'));
$this->setFeedback($form->getSubmitValue('feedback'));
//Save normal question if NOT media //Save normal question if NOT media
if ($this->type != MEDIA_QUESTION) { if ($this->type != MEDIA_QUESTION) {
$this->save($objExercise->id); $this->save($exercise);
// modify the exercise // modify the exercise
$objExercise->addToList($this->id); $exercise->addToList($this->id);
$objExercise->update_question_positions(); $exercise->update_question_positions();
} }
} }
@ -1720,9 +1760,10 @@ abstract class Question
/** /**
* abstract function which process the creation of answers * abstract function which process the creation of answers
* @param the FormValidator $form * @param FormValidator $form
* @param Exercise $exercise
*/ */
abstract public function processAnswersCreation($form); abstract public function processAnswersCreation($form, $exercise);
/** /**
* Displays the menu of question types * Displays the menu of question types
@ -1763,8 +1804,6 @@ abstract class Question
eval('$explanation = get_lang('.$a_type[1].'::$explanationLangVar);'); eval('$explanation = get_lang('.$a_type[1].'::$explanationLangVar);');
echo '<li>'; echo '<li>';
echo '<div class="icon-image">'; echo '<div class="icon-image">';
$icon = '<a href="admin.php?'.api_get_cidreq().'&newQuestion=yes&answerType='.$i.'">'. $icon = '<a href="admin.php?'.api_get_cidreq().'&newQuestion=yes&answerType='.$i.'">'.
Display::return_icon($img, $explanation, null, ICON_SIZE_BIG).'</a>'; Display::return_icon($img, $explanation, null, ICON_SIZE_BIG).'</a>';
@ -1886,13 +1925,14 @@ abstract class Question
/** /**
* Shows question title an description * Shows question title an description
* *
* @param string $feedback_type * @param Exercise $exercise
* @param int $counter * @param int $counter
* @param array $score * @param array $score
* @return string HTML string with the header of the question (before the answers table) * @return string HTML string with the header of the question (before the answers table)
*/ */
public function return_header($feedback_type = null, $counter = null, $score = []) public function return_header($exercise, $counter = null, $score = [])
{ {
$feedbackType = $exercise->feedback_type;
$counter_label = ''; $counter_label = '';
if (!empty($counter)) { if (!empty($counter)) {
$counter_label = intval($counter); $counter_label = intval($counter);
@ -1950,6 +1990,12 @@ abstract class Question
$header .= $message.'<br />'; $header .= $message.'<br />';
} }
if (isset($score['pass']) && $score['pass'] === true) {
if ($this->showFeedback($exercise)) {
$header .= $this->returnFormatFeedback();
}
}
return $header; return $header;
} }
@ -2043,6 +2089,8 @@ abstract class Question
* Get course medias * Get course medias
* @param int course id * @param int course id
* @param integer $course_id * @param integer $course_id
*
* @return array
*/ */
static function get_course_medias( static function get_course_medias(
$course_id, $course_id,
@ -2173,7 +2221,6 @@ abstract class Question
return $swappedAnswer; return $swappedAnswer;
} }
/** /**
* @param array $score * @param array $score
* @return bool * @return bool
@ -2187,4 +2234,31 @@ abstract class Question
return $isReview; return $isReview;
} }
/**
* @param string $value
*/
public function setFeedback($value)
{
$this->feedback = $value;
}
/**
* @param Exercise $exercise
* @return bool
*/
public function showFeedback($exercise)
{
return
in_array($this->type, $this->questionTypeWithFeedback) &&
$exercise->feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM;
}
/**
* @return string
*/
public function returnFormatFeedback()
{
return '<br /><br />'.Display::return_message($this->feedback, 'normal', false);
}
} }

@ -13,7 +13,7 @@ if (isset($_GET['editQuestion'])) {
$objQuestion = Question::read($_GET['editQuestion']); $objQuestion = Question::read($_GET['editQuestion']);
$action = api_get_self()."?".api_get_cidreq()."&myid=1&modifyQuestion=".$modifyQuestion."&editQuestion=".$objQuestion->id; $action = api_get_self()."?".api_get_cidreq()."&myid=1&modifyQuestion=".$modifyQuestion."&editQuestion=".$objQuestion->id;
} else { } else {
$objQuestion = Question :: getInstance($_REQUEST['answerType']); $objQuestion = Question::getInstance($_REQUEST['answerType']);
$action = api_get_self()."?".api_get_cidreq()."&modifyQuestion=".$modifyQuestion."&newQuestion=".$newQuestion; $action = api_get_self()."?".api_get_cidreq()."&modifyQuestion=".$modifyQuestion."&newQuestion=".$newQuestion;
} }
@ -37,7 +37,7 @@ if (is_object($objQuestion)) {
$form->addHeader($text.': '.$form_title_extra); $form->addHeader($text.': '.$form_title_extra);
// question form elements // question form elements
$objQuestion->createForm($form); $objQuestion->createForm($form, $objExercise);
// answer form elements // answer form elements
$objQuestion->createAnswersForm($form); $objQuestion->createAnswersForm($form);
@ -51,15 +51,14 @@ if (is_object($objQuestion)) {
if (isset($_POST['submitQuestion']) && $form->validate()) { if (isset($_POST['submitQuestion']) && $form->validate()) {
// Question // Question
$objQuestion->processCreation($form, $objExercise); $objQuestion->processCreation($form, $objExercise);
$objQuestion->processAnswersCreation($form, $objExercise);
// Answers
$nb_answers = isset($nb_answers) ? $nb_answers : 0;
$objQuestion->processAnswersCreation($form, $nb_answers);
// TODO: maybe here is the better place to index this tool, including answers text // TODO: maybe here is the better place to index this tool, including answers text
// redirect // redirect
if ($objQuestion->type != HOT_SPOT && $objQuestion->type != HOT_SPOT_DELINEATION) { if ($objQuestion->type != HOT_SPOT &&
$objQuestion->type != HOT_SPOT_DELINEATION
) {
if (isset($_GET['editQuestion'])) { if (isset($_GET['editQuestion'])) {
echo '<script type="text/javascript">window.location.href="admin.php?exerciseId='.$exerciseId.'&'.api_get_cidreq().'&message=ItemUpdated"</script>'; echo '<script type="text/javascript">window.location.href="admin.php?exerciseId='.$exerciseId.'&'.api_get_cidreq().'&message=ItemUpdated"</script>';
} else { } else {

@ -74,7 +74,7 @@ if ($show_headers) {
$message = Session::read('attempt_remaining'); $message = Session::read('attempt_remaining');
Session::erase('attempt_remaining'); Session::erase('attempt_remaining');
ExerciseLib::display_question_list_by_attempt( ExerciseLib::displayQuestionListByAttempt(
$objExercise, $objExercise,
$id, $id,
false, false,

@ -316,11 +316,9 @@ class UniqueAnswer extends Question
} }
/** /**
* Receives the unique answer question type creation form data and creates * @inheritdoc
* or updates the answers from that question
* @param FormValidator $form
*/ */
public function processAnswersCreation($form) public function processAnswersCreation($form, $exercise)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$correct = $form->getSubmitValue('correct'); $correct = $form->getSubmitValue('correct');
@ -405,27 +403,23 @@ class UniqueAnswer extends Question
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
/** /**
* Helper function to print the column titles in the answers edition form * @inheritdoc
* @param null $feedback_type The type of feedback influences what columns are shown to the editor
* @param null $counter The number of answers to show, in case there should be pagination
* @param null $score The maximum score for the question
* @return string HTML string for a table header + a wrapper before it
*/ */
public function return_header( public function return_header(
$feedback_type = null, $exercise,
$counter = null, $counter = null,
$score = null $score = null
) { ) {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>' . get_lang("Choice").'</th> <th>'.get_lang("Choice").'</th>
<th>' . get_lang("ExpectedChoice").'</th> <th>'.get_lang("ExpectedChoice").'</th>
<th>' . get_lang("Answer").'</th>'; <th>'.get_lang("Answer").'</th>';
$header .= '<th>'.get_lang("Comment").'</th>'; $header .= '<th>'.get_lang("Comment").'</th>';
$header .= '</tr>'; $header .= '</tr>';

@ -284,11 +284,9 @@ class UniqueAnswerNoOption extends Question
} }
/** /**
* Function which creates the form to create / edit the answers of the question * @inheritdoc
* @param the formvalidator instance */
* @param the answers number to display public function processAnswersCreation($form, $exercise)
*/
function processAnswersCreation($form)
{ {
$questionWeighting = $nbrGoodAnswers = 0; $questionWeighting = $nbrGoodAnswers = 0;
$correct = $form->getSubmitValue('correct'); $correct = $form->getSubmitValue('correct');
@ -398,17 +396,20 @@ class UniqueAnswerNoOption extends Question
// sets the total weighting of the question // sets the total weighting of the question
$this->updateWeighting($questionWeighting); $this->updateWeighting($questionWeighting);
$this->save(); $this->save($exercise);
} }
function return_header($feedback_type = null, $counter = null, $score = null) /**
* @inheritdoc
*/
public function return_header($exercise, $counter = null, $score = null)
{ {
$header = parent::return_header($feedback_type, $counter, $score); $header = parent::return_header($exercise, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'"> $header .= '<table class="'.$this->question_table_class.'">
<tr> <tr>
<th>'.get_lang("Choice").'</th> <th>'.get_lang("Choice").'</th>
<th>'. get_lang("ExpectedChoice").'</th> <th>'.get_lang("ExpectedChoice").'</th>
<th>'. get_lang("Answer").'</th>'; <th>'.get_lang("Answer").'</th>';
$header .= '<th>'.get_lang("Comment").'</th>'; $header .= '<th>'.get_lang("Comment").'</th>';
$header .= '</tr>'; $header .= '</tr>';

@ -3630,7 +3630,7 @@ HOTSPOT;
* @param bool $save_user_result save users results (true) or just show the results (false) * @param bool $save_user_result save users results (true) or just show the results (false)
* @param string $remainingMessage * @param string $remainingMessage
*/ */
public static function display_question_list_by_attempt( public static function displayQuestionListByAttempt(
$objExercise, $objExercise,
$exe_id, $exe_id,
$save_user_result = false, $save_user_result = false,
@ -3817,7 +3817,6 @@ HOTSPOT;
// Category report // Category report
$category_was_added_for_this_test = false; $category_was_added_for_this_test = false;
if (isset($objQuestionTmp->category) && !empty($objQuestionTmp->category)) { if (isset($objQuestionTmp->category) && !empty($objQuestionTmp->category)) {
if (!isset($category_list[$objQuestionTmp->category]['score'])) { if (!isset($category_list[$objQuestionTmp->category]['score'])) {
$category_list[$objQuestionTmp->category]['score'] = 0; $category_list[$objQuestionTmp->category]['score'] = 0;
@ -3851,7 +3850,8 @@ HOTSPOT;
$category_list['none']['total'] += $my_total_weight; $category_list['none']['total'] += $my_total_weight;
} }
if ($objExercise->selectPropagateNeg() == 0 && $my_total_score < 0 if ($objExercise->selectPropagateNeg() == 0 &&
$my_total_score < 0
) { ) {
$my_total_score = 0; $my_total_score = 0;
} }
@ -3866,7 +3866,7 @@ HOTSPOT;
} }
if ($show_results) { if ($show_results) {
$score = array( $score = [
'result' => self::show_score( 'result' => self::show_score(
$my_total_score, $my_total_score,
$my_total_weight, $my_total_weight,
@ -3877,9 +3877,9 @@ HOTSPOT;
'score' => $my_total_score, 'score' => $my_total_score,
'weight' => $my_total_weight, 'weight' => $my_total_weight,
'comments' => $comnt, 'comments' => $comnt,
); ];
} else { } else {
$score = array(); $score = [];
} }
if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION])) { if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION])) {
@ -3895,7 +3895,7 @@ HOTSPOT;
$question_content = '<div class="question_row_answer">'; $question_content = '<div class="question_row_answer">';
// Shows question title an description // Shows question title an description
$question_content .= $objQuestionTmp->return_header( $question_content .= $objQuestionTmp->return_header(
null, $objExercise,
$counter, $counter,
$score $score
); );
@ -3940,6 +3940,7 @@ HOTSPOT;
"ExerciseWithFeedbackWithoutCorrectionComment" "ExerciseWithFeedbackWithoutCorrectionComment"
)."</div>"; )."</div>";
} }
// Remove audio auto play from questions on results page - refs BT#7939 // Remove audio auto play from questions on results page - refs BT#7939
$exercise_content = preg_replace( $exercise_content = preg_replace(
['/autoplay[\=\".+\"]+/', '/autostart[\=\".+\"]+/'], ['/autoplay[\=\".+\"]+/', '/autostart[\=\".+\"]+/'],

@ -386,3 +386,5 @@ $_configuration['agenda_legend'] = [
// If the MySpace page takes too long to load, you might want to remove the // If the MySpace page takes too long to load, you might want to remove the
// processing of generic statistics for the user. In this case set the following to true. // processing of generic statistics for the user. In this case set the following to true.
//$_configuration['tracking_skip_generic_data'] = false; //$_configuration['tracking_skip_generic_data'] = false;
// Show question feedback (requires DB change)
//$_configuration['allow_quiz_question_feedback'] = false;

Loading…
Cancel
Save