quiz-6.0.0-alpha4/src/Controller/QuizController.php

src/Controller/QuizController.php
<?php

namespace Drupal\quiz\Controller;

use Drupal\Core\Access\AccessResultReasonInterface;
use Drupal\Core\Entity\Controller\EntityController;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityFormBuilderInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\quiz\Entity\Quiz;
use Drupal\quiz\Entity\QuizResult;
use Drupal\quiz\Form\QuizQuestionsForm;
use Drupal\quiz\Services\QuizSessionInterface;
use Drupal\quiz\Util\QuizUtil;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller for quiz actions.
 */
class QuizController extends EntityController {

  /**
   * Constructs a new EntityController.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation.
   * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
   *   The URL generator.
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   * @param \Drupal\quiz\Services\QuizSessionInterface $quizSession
   *   The quiz session service.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   *   The current user.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
   *   The entity Field manager service.
   * @param \Drupal\Core\Form\FormBuilderInterface $formBuilder
   *   The form builder service.
   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entityFormBuilder
   *   The entity form builder service.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    EntityTypeBundleInfoInterface $entity_type_bundle_info,
    EntityRepositoryInterface $entity_repository,
    RendererInterface $renderer,
    TranslationInterface $string_translation,
    UrlGeneratorInterface $url_generator,
    RouteMatchInterface $route_match,
    protected QuizSessionInterface $quizSession,
    protected MessengerInterface $messenger,
    protected AccountProxyInterface $currentUser,
    protected EntityFieldManagerInterface $entityFieldManager,
    protected FormBuilderInterface $formBuilder,
    protected EntityFormBuilderInterface $entityFormBuilder,
  ) {
    parent::__construct($entity_type_manager, $entity_type_bundle_info, $entity_repository, $renderer, $string_translation, $url_generator, $route_match);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('entity_type.bundle.info'),
      $container->get('entity.repository'),
      $container->get('renderer'),
      $container->get('string_translation'),
      $container->get('url_generator'),
      $container->get('current_route_match'),
      $container->get('quiz.session'),
      $container->get('messenger'),
      $container->get('current_user'),
      $container->get('entity_field.manager'),
      $container->get('form_builder'),
      $container->get('entity.form_builder'),
    );
  }

  /**
   * Take the quiz.
   *
   * @return mixed
   *   Response to the take request.
   */
  public function take(Quiz $quiz) {
    $page = [];
    /** @var \Drupal\Core\Access\AccessResultReasonInterface $result */
    $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.
      $this->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.
        $this->messenger->addStatus($this->t('Resuming a previous @quiz in-progress.', ['@quiz' => QuizUtil::getQuizName()]));
      }
      return $this->redirect('quiz.question.take', [
        'quiz' => $quiz->id(),
        'question_number' => $this->quizSession->getCurrentQuestion($quiz),
      ]);
    }
    else {
      // Create new result.
      if ($success) {
        // Test a build of questions.
        $questions = $quiz->buildLayout();
        if (empty($questions)) {
          $this->messenger->addError($this->t('Not enough questions were found. Please add more questions before trying to take this @quiz.', ['@quiz' => QuizUtil::getQuizName()]));
          return $this->redirect('entity.quiz.canonical', ['quiz' => $quiz->id()]);
        }

        // Create a new Quiz result.
        $quiz_result = QuizResult::create([
          'qid' => $quiz->id(),
          'vid' => $quiz->getRevisionId(),
          'uid' => $this->currentUser->id(),
          'type' => $quiz->get('result_type')->getString(),
        ]);

        $build_on_last = $quiz->get('build_on_last')->getString() != 'fresh' && $quiz_result->findOldResult();
        $instances = $this->entityFieldManager
          ->getFieldDefinitions('quiz_result', $quiz->get('result_type')->getString());
        foreach ($instances as $field_name => $field) {
          if ($build_on_last || (is_a($field, FieldConfig::class) && $field->getThirdPartySetting('quiz', 'show_field'))) {
            // We found a field to be filled out.
            $redirect_url = Url::fromRoute('entity.quiz.take', [
              'quiz' => $quiz_result->getQuiz()->id(),
            ]);
            $form = $this->entityFormBuilder
              ->getForm($quiz_result, 'default', ['redirect' => $redirect_url]);
            return $form;
          }
        }
      }
      else {
        $page['body']['#markup'] = $result['message'];
        return $page;
      }
    }

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

  /**
   * Creates a form for quiz questions.
   *
   * Handles the manage questions tab.
   *
   * @param \Drupal\quiz\Entity\Quiz $quiz
   *   The quiz we are managing questions for.
   *
   * @return array
   *   Array containing the form.
   */
  public function manageQuestions(Quiz $quiz): array {
    if ($quiz->get('randomization')->getString() < 3) {
      return $this->formBuilder->getForm(QuizQuestionsForm::class, $quiz);
    }
    else {
      $form = $this->entityTypeManager
        ->getFormObject('quiz', 'default')
        ->setEntity($quiz);
      $form = $this->formBuilder->getForm($form);
    }

    foreach (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 \Drupal\quiz\Entity\QuizResult|bool
   *   Either the Quiz result or FALSE if not found.
   */
  public function resume($quiz) {
    // Make sure we use the same revision of the quiz throughout the quiz taking
    // session.
    $quiz_result = $this->quizSession->getResult($quiz);
    if ($quiz_result) {
      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() && $this->currentUser->isAuthenticated()) {
        if ($quiz_result = $quiz->getResumeableResult($this->currentUser)) {
          // Put the result in the user's session.
          $this->quizSession->startQuiz($quiz_result);

          // 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.
                $this->quizSession->setCurrentQuestion($quiz, $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;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc