You are here

function Quiz::buildLayout in Quiz 6.x

Same name and namespace in other branches
  1. 8.6 src/Entity/Quiz.php \Drupal\quiz\Entity\Quiz::buildLayout()
  2. 8.5 src/Entity/Quiz.php \Drupal\quiz\Entity\Quiz::buildLayout()

Retrieves a list of questions (to be taken) for a given quiz.

If the quiz has random questions this function only returns a random selection of those questions. This function should be used to decide what questions a quiz taker should answer.

This question list is stored in the user's result, and may be different when called multiple times. It should only be used to generate the layout for a quiz attempt and NOT used to do operations on the questions inside of a quiz.

Return value

array Array of question data keyed by the weight of the question. This should be used to create QuizResultAnswer entities.

File

src/Entity/Quiz.php, line 522

Class

Quiz
Defines the Quiz entity class.

Namespace

Drupal\quiz\Entity

Code

function buildLayout() {
  $questions = [];
  if ($this
    ->get('randomization')
    ->getString() == 3) {
    $questions = $this
      ->buildCategorizedQuestionList();
  }
  else {

    // Get required questions first.
    $query = \Drupal::database()
      ->query('SELECT qqr.question_id as qqid, qqr.question_vid as vid, qq.type, qqr.qqr_id, qqr.qqr_pid, qq.title
    FROM {quiz_question_relationship} qqr
    JOIN {quiz_question} qq ON qqr.question_id = qq.qqid
    LEFT JOIN {quiz_question_relationship} qqr2 ON (qqr.qqr_pid = qqr2.qqr_id OR (qqr.qqr_pid IS NULL AND qqr.qqr_id = qqr2.qqr_id))
    WHERE qqr.quiz_vid = :quiz_vid
    AND qqr.question_status = :question_status
    ORDER BY qqr2.weight, qqr.weight', [
      ':quiz_vid' => $this
        ->getRevisionId(),
      ':question_status' => QuizQuestion::QUESTION_ALWAYS,
    ]);
    $i = 0;
    while ($question_node = $query
      ->fetchAssoc()) {

      // Just to make it easier on us, let's use a 1-based index.
      $i++;
      $questions[$i] = $question_node;
    }

    // Get random questions for the remainder.
    if ($this
      ->get('randomization')
      ->getString() == 2) {
      if ($this
        ->get('number_of_random_questions')
        ->getString() > 0) {
        $random_questions = $this
          ->getRandomQuestions();
        $questions = array_merge($questions, $random_questions);
        if ($this
          ->get('number_of_random_questions')
          ->getString() > count($random_questions)) {

          // Unable to find enough requested random questions.
          return FALSE;
        }
      }
    }

    // Shuffle questions if required.
    if ($this
      ->get('randomization')
      ->getString() == '1') {
      $question_to_shuffle = [];
      $mark = NULL;
      foreach ($questions as $qidx => $question) {
        if ($mark) {
          if ($question['type'] == 'page') {

            // Found another page.
            shuffle($question_to_shuffle);
            array_splice($questions, $mark, $qidx - $mark - 1, $question_to_shuffle);
            $mark = 0;
            $question_to_shuffle = [];
          }
          else {
            $question_to_shuffle[] = $question;
          }
        }
        if ($question['type'] == 'page') {
          $mark = $qidx;
        }
      }
      if ($mark) {
        shuffle($question_to_shuffle);
        array_splice($questions, $mark, $qidx - $mark, $question_to_shuffle);
      }
      elseif (is_null($mark)) {
        shuffle($questions);
      }
    }
  }
  $count = 0;
  $display_count = 0;
  $questions_out = [];
  foreach ($questions as &$question) {
    $count++;
    $display_count++;
    $question['number'] = $count;
    if ($question['type'] != 'page') {
      $question['display_number'] = $display_count;
    }
    $questions_out[$count] = $question;
  }
  return $questions_out;
}