You are here

class QuizController in Quiz 8.5

Same name and namespace in other branches
  1. 8.6 src/Controller/QuizController.php \Drupal\quiz\Controller\QuizController
  2. 8.4 lib/Drupal/quiz/Controller/QuizController.php \Drupal\quiz\Controller\QuizController
  3. 6.x src/Controller/QuizController.php \Drupal\quiz\Controller\QuizController

Hierarchy

Expanded class hierarchy of QuizController

File

src/Controller/QuizController.php, line 12

Namespace

Drupal\quiz\Controller
View source
class QuizController extends EntityController {

  /**
   * Take the quiz.
   * @return type
   */
  function take(Quiz $quiz) {
    $page = [];
    $page['#cache'] = [
      'max-age' => 0,
    ];

    /* @var $result AccessResultReasonInterface */
    $result = $quiz
      ->access('take', NULL, TRUE);
    $message = '';
    if (is_subclass_of($result, AccessResultReasonInterface::class)) {
      $message = $result
        ->getReason();
    }
    $success = !$result
      ->isForbidden();
    if (!$success) {

      // Not allowed.
      $page['body']['#markup'] = $message;
      return $page;
    }
    elseif ($message) {

      // Allowed, but we have a message.
      \Drupal::messenger()
        ->addMessage($message);
    }
    if ($quiz_result = $this
      ->resume($quiz)) {

      // Resuming attempt.
      if (!empty($quiz_result->resume)) {

        // Show a message if this was reloaded from the database and not just
        // from the session.
        \Drupal::messenger()
          ->addStatus(t('Resuming a previous @quiz in-progress.', array(
          '@quiz' => _quiz_get_quiz_name(),
        )));
      }
      return $this
        ->redirect('quiz.question.take', [
        'quiz' => $quiz
          ->id(),
        'question_number' => $_SESSION['quiz'][$quiz
          ->id()]['current'],
      ]);
    }
    else {

      // Create new result.
      if ($success) {

        // Test a build of questions.
        $questions = $quiz
          ->buildLayout();
        if (empty($questions)) {
          \Drupal::messenger()
            ->addError(t('Not enough questions were found. Please add more questions before trying to take this @quiz.', array(
            '@quiz' => _quiz_get_quiz_name(),
          )));
          return $this
            ->redirect('entity.quiz.canonical', [
            'quiz' => $quiz
              ->id(),
          ]);
        }

        // Creat a new Quiz result.
        $quiz_result = QuizResult::create(array(
          'qid' => $quiz
            ->id(),
          'vid' => $quiz
            ->getRevisionId(),
          'uid' => \Drupal::currentUser()
            ->id(),
          'type' => $quiz
            ->get('result_type')
            ->getString(),
        ));
        $build_on_last = $quiz
          ->get('build_on_last')
          ->getString() != 'fresh' && $quiz_result
          ->findOldResult();
        $instances = Drupal::service('entity_field.manager')
          ->getFieldDefinitions('quiz_result', $quiz
          ->get('result_type')
          ->getString());
        foreach ($instances as $field_name => $field) {
          if ($build_on_last || is_a($field, Drupal\field\Entity\FieldConfig::class) && $field
            ->getThirdPartySetting('quiz', 'show_field')) {

            // We found a field to be filled out.
            $redirect_url = \Drupal\Core\Url::fromRoute('entity.quiz.take', [
              'quiz' => $quiz_result
                ->getQuiz()
                ->id(),
            ]);
            $form = \Drupal::service('entity.form_builder')
              ->getForm($quiz_result, 'default', [
              'redirect' => $redirect_url,
            ]);
            return $form;
          }
        }
      }
      else {
        $page['body']['#markup'] = $result['message'];
        return $page;
      }
    }

    // New attempt.
    $quiz_result
      ->save();
    $_SESSION['quiz'][$quiz
      ->id()]['result_id'] = $quiz_result
      ->id();
    $_SESSION['quiz'][$quiz
      ->id()]['current'] = 1;
    return $this
      ->redirect('quiz.question.take', [
      'quiz' => $quiz
        ->id(),
      'question_number' => 1,
    ]);
  }

  /**
   * Creates a form for quiz questions.
   *
   * Handles the manage questions tab.
   *
   * @param $node
   *   The quiz node we are managing questions for.
   * @return ???
   *   String containing the form.
   */
  function manageQuestions(Quiz $quiz) {
    if ($quiz
      ->get('randomization')
      ->getString() < 3) {
      $manage_questions = Drupal::formBuilder()
        ->getForm(\Drupal\quiz\Form\QuizQuestionsForm::class, $quiz);
      return $manage_questions;
      $question_bank = Views::getView('quiz_question_bank')
        ->preview();

      // Insert into vert tabs.
      $form['vert_tabs'] = array(
        '#type' => 'x',
        // @todo wtf?
        '#weight' => 0,
        '#default_tab' => 'edit-questions',
      );
      $form['vert_tabs']['questions'] = array(
        '#type' => 'details',
        '#title' => t('Manage questions'),
        '#group' => 'vert_tabs',
        'questions' => $manage_questions,
      );
      $form['vert_tabs']['bank'] = array(
        '#type' => 'details',
        '#title' => t('Question bank'),
        '#group' => 'vert_tabs',
        'bank' => $question_bank,
      );
      return $manage_questions;
    }
    else {
      $form = \Drupal::service('entity.manager')
        ->getFormObject('quiz', 'default')
        ->setEntity($quiz);
      $form = \Drupal::formBuilder()
        ->getForm($form);
    }
    foreach (\Drupal\Core\Render\Element::children($form) as $key) {
      if (in_array($key, array_keys($quiz
        ->getFieldDefinitions())) || $form[$key]['#type'] == 'details') {
        if (!in_array($key, [
          'quiz_terms',
          'random',
          'quiz',
        ])) {
          $form[$key]['#access'] = FALSE;
        }
      }
    }
    return $form;
  }

  /**
   * Resume a quiz.
   *
   * Search the database for an in progress attempt, and put it back into the
   * session if allowed.
   *
   * @return QuizResult
   */
  function resume($quiz) {
    $user = \Drupal::currentUser();

    // Make sure we use the same revision of the quiz throughout the quiz taking
    // session.
    $result_id = !empty($_SESSION['quiz'][$quiz
      ->id()]['result_id']) ? $_SESSION['quiz'][$quiz
      ->id()]['result_id'] : NULL;
    if ($result_id && ($quiz_result = QuizResult::load($result_id))) {
      return $quiz_result;
    }
    else {

      // User doesn't have attempt in session. If we allow resuming we can load it
      // from the database.
      if ($quiz
        ->get('allow_resume')
        ->getString() && $user
        ->isAuthenticated()) {
        if ($quiz_result = $quiz
          ->getResumeableResult($user)) {

          // Put the result in the user's session.
          $_SESSION['quiz'][$quiz
            ->id()]['result_id'] = $quiz_result
            ->id();
          $_SESSION['quiz'][$quiz
            ->id()]['current'] = 1;

          // Now advance the user to after the last answered question.
          $prev = NULL;
          foreach ($quiz_result
            ->getLayout() as $qra) {
            if ($prev) {
              if ($qra
                ->get('answer_timestamp')
                ->isEmpty() && !$prev
                ->get('answer_timestamp')
                ->isEmpty()) {

                // This question has not been answered, but the previous
                // question has.
                $_SESSION['quiz'][$quiz
                  ->id()]['current'] = $qra
                  ->get('number')
                  ->getString();
              }
            }
            $prev = clone $qra;
          }

          // Mark this quiz as being resumed from the database.
          $quiz_result->resume = TRUE;
          return $quiz_result;
        }
      }
    }
    return FALSE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
EntityController::$entityRepository protected property The entity repository.
EntityController::$entityTypeBundleInfo protected property The entity type bundle info.
EntityController::$entityTypeManager protected property The entity manager.
EntityController::$renderer protected property The renderer.
EntityController::addBundleTitle public function Provides a generic add title callback for entities with bundles.
EntityController::addPage public function Displays add links for the available bundles.
EntityController::addTitle public function Provides a generic add title callback for an entity type.
EntityController::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create
EntityController::deleteTitle public function Provides a generic delete title callback.
EntityController::doGetEntity protected function Determines the entity.
EntityController::editTitle public function Provides a generic edit title callback.
EntityController::loadBundleDescriptions protected function Expands the bundle information with descriptions, if known.
EntityController::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
EntityController::title public function Provides a generic title callback for a single entity.
EntityController::__construct public function Constructs a new EntityController.
QuizController::manageQuestions function Creates a form for quiz questions.
QuizController::resume function Resume a quiz.
QuizController::take function Take the quiz.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.