Add quiz_confirm_saved_answers conf setting - refs BT#17519

Add a checkbox to allow to user confirm the number of answers saved in quiz attempt
- Requires to edit the src/Chamilo/CoreBundle/Entity/TrackEExerciseConfirmation.php file adding the "@" in the ORM phpdoc block
- Requires DB changes:
 CREATE TABLE track_e_exercise_confirmation (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, course_id INT NOT NULL, attempt_id INT NOT NULL, quiz_id INT NOT NULL, session_id INT NOT NULL, confirmed TINYINT(1) DEFAULT '0' NOT NULL, questions_count INT NOT NULL, saved_answers_count INT NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
pull/3356/head
Angel Fernando Quiroz Campos 5 years ago
parent 7b83e05f40
commit adbd49989c
  1. 45
      main/exercise/exercise.class.php
  2. 5
      main/exercise/exercise_show.php
  3. 50
      main/inc/ajax/exercise.ajax.php
  4. 10
      main/inc/lib/exercise.lib.php
  5. 5
      main/install/configuration.dist.php
  6. 72
      main/template/default/exercise/partials/result_exercise.tpl
  7. 301
      src/Chamilo/CoreBundle/Entity/TrackEExerciseConfirmation.php

@ -3,6 +3,7 @@
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\GradebookLink;
use Chamilo\CoreBundle\Entity\TrackEExerciseConfirmation;
use Chamilo\CoreBundle\Entity\TrackEHotspot;
use Chamilo\CourseBundle\Entity\CExerciseCategory;
use ChamiloSession as Session;
@ -6150,12 +6151,14 @@ class Exercise
/**
* @param array $user_data result of api_get_user_info()
* @param array $trackExerciseInfo result of get_stat_track_exercise_info
* @param bool $saveUserResult
*
* @return string
*/
public function showExerciseResultHeader(
$user_data,
$trackExerciseInfo
$trackExerciseInfo,
$saveUserResult
) {
if (api_get_configuration_value('hide_user_info_in_quiz_result')) {
return '';
@ -6214,8 +6217,44 @@ class Exercise
$data['title'] = PHP_EOL.$this->exercise.' : '.get_lang('Result');
}
$data['number_of_answers'] = count(explode(',', $trackExerciseInfo['data_tracking']));
$data['number_of_answers_saved'] = $this->countUserAnswersSavedInExercise($trackExerciseInfo['exe_id']);
$questionsCount = count(explode(',', $trackExerciseInfo['data_tracking']));
$savedAnswersCount = $this->countUserAnswersSavedInExercise($trackExerciseInfo['exe_id']);
$data['number_of_answers'] = $questionsCount;
$data['number_of_answers_saved'] = $savedAnswersCount;
if (false !== api_get_configuration_value('quiz_confirm_saved_answers')) {
$em = Database::getManager();
if ($saveUserResult) {
$trackConfirmation = new TrackEExerciseConfirmation();
$trackConfirmation
->setUserId($trackExerciseInfo['exe_user_id'])
->setQuizId($trackExerciseInfo['exe_exo_id'])
->setAttemptId($trackExerciseInfo['exe_id'])
->setQuestionsCount($questionsCount)
->setSavedAnswersCount($savedAnswersCount)
->setCourseId($trackExerciseInfo['c_id'])
->setSessionId($trackExerciseInfo['session_id'])
->setCreatedAt(api_get_utc_datetime(null, false, true));
$em->persist($trackConfirmation);
$em->flush();
} else {
$trackConfirmation = $em
->getRepository('ChamiloCoreBundle:TrackEExerciseConfirmation')
->findOneBy(
[
'attemptId' => $trackExerciseInfo['exe_id'],
'quizId' => $trackExerciseInfo['exe_exo_id'],
'courseId' => $trackExerciseInfo['c_id'],
'sessionId' => $trackExerciseInfo['session_id'],
]
);
}
$data['track_confirmation'] = $trackConfirmation;
}
$tpl = new Template(null, false, false, false, false, false, false);
$tpl->assign('data', $data);

@ -310,7 +310,8 @@ if ($show_results || $show_only_total_score || $showTotalScoreAndUserChoicesInLa
// Shows exercise header
echo $objExercise->showExerciseResultHeader(
$user_info,
$track_exercise_info
$track_exercise_info,
false
);
}
@ -496,7 +497,7 @@ foreach ($questionList as $questionId) {
$(function() {
new HotspotQuestion({
questionId: $questionId,
exerciseId: {$objExercise->id},
exerciseId: {$objExercise->id},
exeId: $id,
selector: '#hotspot-solution-$questionId-$id',
for: 'solution',

@ -1,6 +1,7 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\TrackEExerciseConfirmation;
use ChamiloSession as Session;
/**
@ -848,6 +849,55 @@ switch ($action) {
echo 'ok';
}
break;
case 'quiz_confirm_saved_answers':
if (false === api_get_configuration_value('quiz_confirm_saved_answers')) {
break;
}
$trackConfirmationId = isset($_POST['tc_id']) ? (int) $_POST['tc_id'] : 0;
$cId = api_get_course_int_id();
$sessionId = api_get_session_id();
$userId = api_get_user_id();
$confirmed = !empty($_POST['quiz_confirm_saved_answers_check']);
$em = Database::getManager();
$repo = $em->getRepository('ChamiloCoreBundle:TrackEExerciseConfirmation');
try {
if (!$trackConfirmationId) {
throw new Exception(get_lang('ErrorOccurred'));
}
/** @var TrackEExerciseConfirmation $trackConfirmation */
$trackConfirmation = $repo->findOneBy(
[
'id' => $trackConfirmationId,
'userId' => $userId,
'courseId' => $cId,
'sessionId' => $sessionId,
],
['createdAt' => 'DESC']
);
if (!$trackConfirmation) {
throw new Exception(get_lang('NotFound'));
}
$trackConfirmation
->setConfirmed($confirmed)
->setUpdatedAt(api_get_utc_datetime(null, false, true));
$em->persist($trackConfirmation);
$em->flush();
http_response_code(200);
} catch (Exception $exception) {
http_response_code(500);
echo Display::return_message($exception->getMessage(), 'error');
}
break;
default:
echo '';

@ -4519,15 +4519,19 @@ EOT;
// Shows exercise header.
echo $objExercise->showExerciseResultHeader(
$studentInfo,
$exercise_stat_info
$exercise_stat_info,
$save_user_result
);
}
// Display text when test is finished #4074 and for LP #4227
$endOfMessage = $objExercise->getTextWhenFinished();
if (!empty($endOfMessage)) {
echo Display::return_message($endOfMessage, 'normal', false);
echo "<div class='clear'>&nbsp;</div>";
echo Display::div(
Display::return_message($endOfMessage, 'normal', false),
['id' => 'quiz_end_message']
);
echo "<div class='clearfix'></div>";
}
$question_list_answers = [];

@ -591,6 +591,11 @@ $_configuration['send_all_emails_to'] = [
//$_configuration['quiz_open_question_decimal_score'] = false;
// Add answer-saving procedure check before starting the quiz
//$_configuration['quiz_check_button_enable'] = false;
// Add a checkbox to allow to user confirm the number of answers saved in quiz attempt
// - Requires to edit the src/Chamilo/CoreBundle/Entity/TrackEExerciseConfirmation.php file adding the "@" in the ORM phpdoc block
// - Requires DB changes:
// CREATE TABLE track_e_exercise_confirmation (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, course_id INT NOT NULL, attempt_id INT NOT NULL, quiz_id INT NOT NULL, session_id INT NOT NULL, confirmed TINYINT(1) DEFAULT '0' NOT NULL, questions_count INT NOT NULL, saved_answers_count INT NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
//$_configuration['quiz_confirm_saved_answers'] = false;
// Hide search form in session list
//$_configuration['hide_search_form_in_session_list'] = false;

@ -45,19 +45,83 @@
{% endif %}
</div>
<hr>
<div id="quiz_saved_answers_container">
{% if data.number_of_answers_saved != data.number_of_answers %}
<p class="alert alert-warning"
style="margin-bottom: 0; margin-top: 20px;">
<p class="alert alert-warning">
<strong>{{ 'XAnswersSavedByUsersFromXTotal'|get_lang|format(data.number_of_answers_saved, data.number_of_answers) }}</strong>
</p>
{% else %}
<p class="lead text-success"
style="margin-bottom: 0; margin-top: 20px;">
<p class="lead text-success">
<strong>{{ 'XAnswersSavedByUsersFromXTotal'|get_lang|format(data.number_of_answers_saved, data.number_of_answers) }}</strong>
</p>
{% endif %}
{% if 'quiz_confirm_saved_answers'|api_get_configuration_value %}
{% set enable_form = data.track_confirmation.updatedAt is empty and data.track_confirmation.userId == _u.id %}
<form class="form-horizontal" action="#" id="quiz_confirm_saved_answers_form">
<div class="form-group">
<div class="col-sm-12">
<div class="checkbox">
<label>
<input type="checkbox" name="quiz_confirm_saved_answers_check" {% if not enable_form %}disabled{% endif %} {% if data.track_confirmation.confirmed %}checked{% endif %}>
{{ 'QuizConfirmSavedAnswers'|get_lang }}
</label>
</div>
<span class="help-block">{{ 'QuizConfirmSavedAnswersHelp'|get_lang }}</span>
</div>
</div>
{% if enable_form %}
<div class="form-group">
<div class="col-sm-12">
<input type="hidden" name="tc_id" value="{{ data.track_confirmation.id }}">
<button type="submit" class="btn btn-primary">
<span class="fa fa-save fa-fw" aria-hidden="true"></span> {{ 'Save'|get_lang }}
</button>
</div>
</div>
{% endif %}
</form>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% if 'quiz_confirm_saved_answers'|api_get_configuration_value %}
{% set enable_form = data.track_confirmation.updatedAt is empty and data.track_confirmation.userId == _u.id %}
{% if enable_form %}
<script>
$(function () {
$('#quiz_confirm_saved_answers_form').on('submit', function (e) {
e.preventDefault();
var self = $(this),
checkbox = self.find('[type="checkbox"]'),
button = self.find(':submit'),
xhrData = self.serialize();
button.prop('disabled', true);
checkbox.prop('disabled', true);
$.post(
'{{ _p.web_ajax }}exercise.ajax.php?a=quiz_confirm_saved_answers',
xhrData
).done(function () {
button.parents('.form-group').remove();
$('#quiz_end_message').show();
}).fail(function (response) {
button.replaceWith(response.responseText);
});
})
$('#quiz_end_message').hide();
});
</script>
{% endif %}
{% endif %}

@ -0,0 +1,301 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class TrackEExerciseConfirmation.
*
* Add @ to the next line if api_get_configuration_value('quiz_confirm_saved_answers') is true
* ORM\Table(name="track_e_exercise_confirmation")
* ORM\Entity()
*/
class TrackEExerciseConfirmation
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @var int
*
* @ORM\Column(name="user_id", type="integer")
*/
private $userId;
/**
* @var int
*
* @ORM\Column(name="course_id", type="integer")
*/
private $courseId;
/**
* @var int
*
* @ORM\Column(name="attempt_id", type="integer")
*/
private $attemptId;
/**
* @var int
*
* @ORM\Column(name="quiz_id", type="integer")
*/
private $quizId;
/**
* @var int
*
* @ORM\Column(name="session_id", type="integer")
*/
private $sessionId;
/**
* @var bool
*
* @ORM\Column(name="confirmed", type="boolean", options={"default": false})
*/
private $confirmed;
/**
* @var int
*
* @ORM\Column(name="questions_count", type="integer")
*/
private $questionsCount;
/**
* @var int
*
* @ORM\Column(name="saved_answers_count", type="integer")
*/
private $savedAnswersCount;
/**
* @var \DateTime
*
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @var \DateTime
*
* @ORM\Column(name="updated_at", type="datetime", nullable=true)
*/
private $updatedAt;
/**
* TrackEExerciseConfirmation constructor.
*/
public function __construct()
{
$this->confirmed = false;
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return int
*/
public function getUserId()
{
return $this->userId;
}
/**
* @param int $userId
*
* @return TrackEExerciseConfirmation
*/
public function setUserId($userId)
{
$this->userId = $userId;
return $this;
}
/**
* @return int
*/
public function getCourseId()
{
return $this->courseId;
}
/**
* @param int $courseId
*
* @return TrackEExerciseConfirmation
*/
public function setCourseId($courseId)
{
$this->courseId = $courseId;
return $this;
}
/**
* @return int
*/
public function getAttemptId()
{
return $this->attemptId;
}
/**
* @param int $attemptId
*
* @return TrackEExerciseConfirmation
*/
public function setAttemptId($attemptId)
{
$this->attemptId = $attemptId;
return $this;
}
/**
* @return int
*/
public function getQuizId()
{
return $this->quizId;
}
/**
* @param int $quizId
*
* @return TrackEExerciseConfirmation
*/
public function setQuizId($quizId)
{
$this->quizId = $quizId;
return $this;
}
/**
* @return int
*/
public function getSessionId()
{
return $this->sessionId;
}
/**
* @param int $sessionId
*
* @return TrackEExerciseConfirmation
*/
public function setSessionId($sessionId)
{
$this->sessionId = $sessionId;
return $this;
}
/**
* @return bool
*/
public function isConfirmed()
{
return $this->confirmed;
}
/**
* @param bool $confirmed
*
* @return TrackEExerciseConfirmation
*/
public function setConfirmed($confirmed)
{
$this->confirmed = $confirmed;
return $this;
}
/**
* @return int
*/
public function getQuestionsCount()
{
return $this->questionsCount;
}
/**
* @param int $questionsCount
*
* @return TrackEExerciseConfirmation
*/
public function setQuestionsCount($questionsCount)
{
$this->questionsCount = $questionsCount;
return $this;
}
/**
* @return int
*/
public function getSavedAnswersCount()
{
return $this->savedAnswersCount;
}
/**
* @param int $savedAnswersCount
*
* @return TrackEExerciseConfirmation
*/
public function setSavedAnswersCount($savedAnswersCount)
{
$this->savedAnswersCount = $savedAnswersCount;
return $this;
}
/**
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* @param \DateTime $createdAt
*
* @return TrackEExerciseConfirmation
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* @return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* @param \DateTime $updatedAt
*
* @return TrackEExerciseConfirmation
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
}
Loading…
Cancel
Save