View source
<?php
namespace Drupal\quiz\Form;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\quiz\Entity\QuizResult;
class QuizQuestionAnsweringForm extends FormBase {
public function buildForm(array $form, FormStateInterface $form_state) : array {
$questions = $form_state
->getBuildInfo()['args'][0];
$quiz_session = \Drupal::service('quiz.session');
$quiz_result = $form_state
->getBuildInfo()['args'][1];
$quiz = \Drupal::entityTypeManager()
->getStorage('quiz')
->loadRevision($quiz_result
->get('vid')
->getString());
$form['#quiz'] = $quiz;
$form['#quiz_result'] = $quiz_result;
if (!is_array($questions)) {
if ($questions
->bundle() == 'page') {
foreach ($quiz_result
->getLayout() as $qra) {
if ($qra
->get('question_id')
->getString() == $questions
->id()) {
$questions = [
$questions,
];
foreach ($quiz_result
->getLayout() as $qra2) {
if ($qra2->qqr_pid == $qra->qqr_id) {
$questions[] = $qra2
->getQuizQuestion();
}
}
break;
}
}
unset($qra, $qra2);
}
else {
$questions = [
$questions
->id() => $questions,
];
}
}
$form['#attributes']['class'] = [
'answering-form',
];
$form['#tree'] = TRUE;
$quiz_result
->setQuestion(reset($questions)
->getResponse($quiz_result)
->get('number')->value);
foreach ($questions as $question) {
$class = Html::getClass('quiz-question-' . $question
->bundle());
$qra = $question
->getResponse($quiz_result);
$element = $question
->getAnsweringForm($form_state, $qra);
$build = \Drupal::entityTypeManager()
->getViewBuilder('quiz_question')
->view($question, 'question');
$header_markup = NULL;
if (!$qra
->get('display_number')
->isEmpty()) {
$header_markup = [
'#markup' => "<h2>" . t("Question @question", [
'@question' => $qra
->get('display_number')
->getString(),
]) . "</h2>",
];
}
$form['question'][$question
->id()] = [
'#attributes' => [
'class' => [
$class,
],
],
'#type' => 'container',
'header' => $header_markup,
'question' => $build,
'answer' => $element,
];
$form['question'][$question
->id()]['answer']['#quiz_result_answer'] = $qra;
$blank_and_change = $qra
->get('is_skipped')
->getString() && $quiz
->get('allow_change_blank')
->getString();
if (!$quiz
->get('allow_change')
->getString() && !$qra
->get('answer_timestamp')
->isEmpty()) {
if ($blank_and_change) {
}
else {
$form['question'][$question
->id()]['#disabled'] = TRUE;
if (empty($form_state
->getUserInput())) {
\Drupal::messenger()
->addWarning(t('Changing answers is disabled.'));
}
}
}
if ($quiz
->get('mark_doubtful')
->getString() && $question
->isQuestion()) {
$form['question'][$question
->id()]['is_doubtful'] = [
'#type' => 'checkbox',
'#title' => t('Doubtful?'),
'#default_value' => $qra
->get('is_doubtful')
->getString(),
];
}
}
$is_last = $quiz
->isLastQuestion();
$form['navigation']['#type'] = 'actions';
$form['navigation']['submit_hidden'] = [
'#weight' => -9999,
'#type' => 'submit',
'#value' => $is_last ? t('Finish') : t('Next'),
'#attributes' => [
'style' => 'display: none',
],
];
if ($quiz
->get('backwards_navigation')
->getString() && $quiz_session
->getCurrentQuestion($quiz) != 1) {
$form['navigation']['back'] = [
'#weight' => 10,
'#type' => 'submit',
'#value' => t('Back'),
'#submit' => [
'::submitBack',
],
'#limit_validation_errors' => [],
];
if ($is_last) {
$form['navigation']['#last'] = TRUE;
$form['navigation']['last_text'] = [
'#weight' => 0,
'#markup' => '<p><em>' . t('This is the last question. Press Finish to deliver your answers') . '</em></p>',
];
}
}
$form['navigation']['submit'] = [
'#weight' => 30,
'#type' => 'submit',
'#value' => $is_last ? t('Finish') : t('Next'),
'#ajax' => [],
];
if ($is_last && $quiz
->get('backwards_navigation')
->getString() && !$quiz
->get('repeat_until_correct')
->getString()) {
$form['#attributes']['class'][] = 'quiz-answer-confirm';
$form['#attributes']['data-confirm-message'] = t("By proceeding you won't be able to go back and edit your answers.");
$form['#attached']['library'][] = 'quiz/confirm';
}
if ($quiz
->get('allow_skipping')
->getString()) {
$form['navigation']['skip'] = [
'#weight' => 20,
'#type' => 'submit',
'#value' => $is_last ? t('Leave blank and finish') : t('Leave blank'),
'#access' => $question
->isGraded(),
'#submit' => [
'::submitBlank',
],
'#limit_validation_errors' => [],
];
}
return $form;
}
public function getFormId() {
return 'quiz_question_answering_form';
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$config = $this
->config('quiz.settings');
$quiz_session = \Drupal::service('quiz.session');
$quiz_result = $form_state
->getBuildInfo()['args'][1];
$feedback_count = 0;
$quiz = \Drupal::entityTypeManager()
->getStorage('quiz')
->loadRevision($quiz_result
->get('vid')
->getString());
$time_reached = $quiz_result
->isTimeReached();
$layout = $quiz_result
->getLayout();
if ($time_reached) {
\Drupal::messenger()
->addError(t('The last answer was not submitted, as the time ran out.'));
}
else {
$submitted = $form_state
->getValue('question');
foreach ($layout as $qra) {
if (isset($submitted[$qra
->get('question_id')
->getString()])) {
$qqid = $qra
->get('question_id')
->getString();
$qra
->set('answer_timestamp', \Drupal::time()
->getRequestTime());
$qra
->set('points_awarded', $qra
->score($form_state
->getValues()['question'][$qqid]) * $qra
->getWeightedRatio());
$qra
->set('is_skipped', FALSE);
$qra
->set('is_doubtful', !empty($form_state
->getValues()['question'][$qqid]['is_doubtful']) ? 1 : 0);
$qra
->set('is_correct', $qra
->isCorrect());
$qra
->save();
$feedback_count += $qra
->getQuizQuestion()
->hasFeedback();
$quiz_result
->setQuestion($qra
->get('number')
->getString() + 1);
}
}
}
$next_number = $quiz_session
->getCurrentQuestion($quiz);
if ($time_reached || !isset($layout[$next_number])) {
$this
->submitFinalize($form, $form_state);
}
else {
$form_state
->setRedirect('quiz.question.take', [
'quiz' => $quiz
->id(),
'question_number' => $next_number,
]);
}
$review_options = $quiz
->get('review_options')
->get(0);
if ($review_options && !empty($review_options
->getValue()['question']) && array_filter($review_options
->getValue()['question']) && $feedback_count) {
$form_state
->setRedirect('quiz.question.feedback', [
'quiz' => $quiz
->id(),
'question_number' => $next_number - 1,
]);
$form_state
->set('feedback', TRUE);
}
}
public function submitBlank(array $form, FormStateInterface $form_state) {
$quiz_result = $form_state
->getBuildInfo()['args'][1];
$quiz_session = \Drupal::service('quiz.session');
$quiz = \Drupal::entityTypeManager()
->getStorage('quiz')
->loadRevision($quiz_result
->get('vid')
->getString());
if (!empty($form_state
->getUserInput()['question'])) {
foreach (array_keys($form_state
->getUserInput()['question']) as $qqid) {
foreach ($quiz_result
->getLayout() as $idx => $qra) {
if ($qra
->get('question_id')
->getString() == $qqid) {
$qra
->set('is_skipped', TRUE);
$qra
->set('is_correct', NULL);
$qra
->set('points_awarded', FALSE);
$qra
->set('answer_timestamp', \Drupal::time()
->getRequestTime());
$qra
->save();
}
}
$quiz_result
->setQuestion($quiz_session
->getCurrentQuestion($quiz) + 1);
}
}
else {
$quiz_result
->setQuestion($quiz, $quiz_session
->getCurrentQuestion($quiz) + 1);
}
$form_state
->setRedirect('quiz.question.take', [
'quiz' => $quiz
->id(),
'question_number' => $quiz_session
->getCurrentQuestion($quiz),
]);
$layout = $quiz_result
->getLayout();
if (!isset($layout[$quiz_session
->getCurrentQuestion($quiz)])) {
$this
->submitFinalize($form, $form_state);
}
}
function submitFinalize(array $form, FormStateInterface $form_state) {
$quiz_result = $form_state
->getBuildInfo()['args'][1];
$quiz = \Drupal::entityTypeManager()
->getStorage('quiz')
->loadRevision($quiz_result
->get('vid')
->getString());
$quiz_session = \Drupal::service('quiz.session');
$quiz_result
->finalize();
if (empty($quiz->review_options['question']) || !array_filter($quiz->review_options['question']) || empty($form_state['feedback'])) {
$form_state
->setRedirect('entity.quiz_result.canonical', [
'quiz' => $quiz
->id(),
'quiz_result' => $quiz_result
->id(),
]);
}
$quiz_session
->setTemporaryResult($quiz_result);
$quiz_session
->removeQuiz($quiz);
}
function submitBack(&$form, FormStateInterface $form_state) {
$quiz_session = \Drupal::service('quiz.session');
$quiz = $form['#quiz'];
$quiz_result = $quiz_session
->getResult($quiz);
$quiz_result
->setQuestion($quiz_session
->getCurrentQuestion($quiz) - 1);
$layout = $quiz_result
->getLayout();
$question = $layout[$quiz_session
->getCurrentQuestion($quiz)];
if (!empty($question->qqr_pid)) {
foreach ($layout as $question2) {
if ($question2->qqr_id == $question->qqr_pid) {
$quiz_result
->setQuestion($question2
->get('number')->value);
}
}
}
$form_state
->setRedirect('quiz.question.take', [
'quiz' => $quiz
->id(),
'question_number' => $quiz_session
->getCurrentQuestion($quiz),
]);
}
public function validateForm(array &$form, FormStateInterface $form_state) {
$quiz_result = $form_state
->getBuildInfo()['args'][1];
$time_reached = $quiz_result
->isTimeReached();
if ($time_reached) {
return;
}
}
}