You are here

MatchingQuestion.php in Quiz 8.5

Matching classes.

This module uses the question interface to define the matching question type.

A Matching node defines a series of questions and answers and requires the userto associate each answer with a question.

File

question_types/quiz_matching/src/Plugin/quiz/QuizQuestion/MatchingQuestion.php
View source
<?php

namespace Drupal\quiz_matching\Plugin\quiz\QuizQuestion;

use Drupal;
use Drupal\Core\Form\FormStateInterface;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\quiz\Entity\QuizQuestion;
use Drupal\quiz\Entity\QuizResultAnswer;
use function db_delete;
use function db_insert;
use function db_merge;
use function db_update;

/**
 * @file
 * Matching classes.
 *
 * This module uses the question interface to define the matching question type.
 *
 * A Matching node defines a series of questions and answers and requires the
 * userto associate each answer with a question.
 */

/**
 * @QuizQuestion (
 *   id = "matching",
 *   label = @Translation("Matching question"),
 *   handlers = {
 *     "response" = "\Drupal\quiz_matching\Plugin\quiz\QuizQuestion\MatchingResponse"
 *   }
 * )
 */
class MatchingQuestion extends QuizQuestion {

  /**
   * Implementation of getAnsweringForm().
   *
   * @see QuizQuestion::getAnsweringForm()
   */
  public function getAnsweringForm(FormStateInterface $form_state, QuizResultAnswer $quizQuestionResultAnswer) {
    $form = parent::getAnsweringForm($form_state, $quizQuestionResultAnswer);
    $answers[''] = '';
    foreach ($this
      ->get('quiz_matching')
      ->referencedEntities() as $alternative) {

      /* @var $alternative Paragraph */
      $questions[$alternative
        ->id()] = $alternative
        ->get('matching_question')
        ->getString();
      $answers[$alternative
        ->id()] = $alternative
        ->get('matching_answer')
        ->getString();
    }
    foreach ($questions as $id => $question) {

      // Build options list.
      $form['user_answer'][$id] = [
        '#title' => $question,
        '#type' => 'select',
        '#options' => $answers,
      ];
    }
    if ($paragraphs = $quizQuestionResultAnswer
      ->getResponse()) {

      // If this question already has been answered.
      foreach ($paragraphs as $paragraph) {
        if ($paragraph
          ->get('matching_user_answer')
          ->referencedEntities()) {
          $form['user_answer'][$paragraph
            ->get('matching_user_question')
            ->referencedEntities()[0]
            ->id()]['#default_value'] = $paragraph
            ->get('matching_user_answer')
            ->referencedEntities()[0]
            ->id();
        }
      }
    }
    if (Drupal::config('quiz.settings')
      ->get('matching_shuffle_options', TRUE)) {
      $form = $this
        ->customShuffle($form);
    }
    $form['scoring_info'] = array(
      '#access' => !empty($this
        ->get('choice_penalty')
        ->getString()),
      '#markup' => '<p><em>' . t('You lose points by selecting incorrect options. You may leave an option blank to avoid losing points.') . '</em></p>',
    );
    return $form;
  }

  /**
   * Question response validator.
   */
  public static function getAnsweringFormValidate(array &$element, Drupal\Core\Form\FormStateInterface $form_state) {
    $values = $form_state
      ->getValues();
    $id = $element['#quiz_result_answer']
      ->getQuizQuestion()
      ->id();
    if (!array_filter($values['question'][$id]['answer']['user_answer'])) {
      $form_state
        ->setError($element, t('You need to match at least one of the items.'));
    }
  }

  /**
   * Shuffles an array, but keep the keys.
   *
   * @param array $array
   *   Array to be shuffled
   * @return array
   *   A shuffled version of the array with keys preserved.
   */
  private function customShuffle(array $array = array()) {
    $new_array = array();
    while (count($array)) {
      $element = array_rand($array);
      $new_array[$element] = $array[$element];
      unset($array[$element]);
    }
    return $new_array;
  }

  /**
   * {@inheritdoc}
   */
  public function getMaximumScore() {
    return count($this
      ->get('quiz_matching')
      ->referencedEntities());
  }

  /**
   * Get the correct answers for this question.
   *
   * @return array
   *  Array of correct answers
   */
  public function getCorrectAnswer() {
    $correct_answers = [];
    foreach ($this
      ->get('quiz_matching')
      ->referencedEntities() as $entity) {
      $correct_answers[$entity
        ->getRevisionId()] = $entity;
    }
    return $correct_answers;
  }

}

Classes

Namesort descending Description
MatchingQuestion @QuizQuestion ( id = "matching", label = Plugin annotation @Translation("Matching question"), handlers = { "response" = "\Drupal\quiz_matching\Plugin\quiz\QuizQuestion\MatchingResponse" } )