closedquestion-8.x-3.x-dev/src/Question/CqUserAnswerDefault.php

src/Question/CqUserAnswerDefault.php
<?php

namespace Drupal\closedquestion\Question;

/**
 * Class CqUserAnswerDefault.
 *
 * CqUserAnswerDefault is the default implementation of CqUserAnswerInterface.
 *
 * It stores data for authenticated users in the database and data for anonymous
 * users in the session of the user.
 *
 * @package Drupal\closedquestion\Question
 */
class CqUserAnswerDefault implements CqUserAnswerInterface {

  /**
   * The answer set by the user.
   *
   * @var mixed
   */
  private $answer;

  /**
   * Closed question answer entity.
   *
   * @var bool|\Drupal\closedquestion\Entity\ClosedQuestionAnswerInterface|null
   */
  private $answerEntity;

  /**
   * Additional data, as key/value pairs.
   *
   * @var array
   */
  private $data;

  /**
   * The number of times the student gave a wrong answer.
   *
   * @var int
   */
  private $tries = 0;

  /**
   * Is the current answer the correct answer?
   *
   * 1: yes
   * 0: no
   * -1: correctness not determined yet.
   *
   * @var int
   */
  private $isCorrect = -1;

  /**
   * Has the student ever answered this question correct?
   *
   * @var int
   */
  private $onceCorrect = 0;

  /**
   * The unserialized version of the previous answer.
   *
   * Used to see if anything changed.
   *
   * @var string
   */
  private $origAnswer;

  /**
   * The unserialized version of the previous data.
   *
   * Used to see if anything changed.
   *
   * @var string
   */
  private $origData;

  /**
   * The serialized version of the previous answer.
   *
   * Used to see if anything changed.
   *
   * @var string
   */
  private $origAnswerSerialized;

  /**
   * The serialized version of the previous data.
   *
   * Used to see if anything changed.
   *
   * @var string
   */
  private $origDataSerialized;

  /**
   * The previous version of the tries parameter.
   *
   * Used to see if anything changed.
   *
   * @var int
   */
  private $origTries;

  /**
   * The previous version of the onceCorrect parameter.
   *
   * Used to see if anything changed.
   *
   * @var int
   */
  private $origOnceCorrect;

  /**
   * The closed_question id of the Drupal node this UserAnswer belongs to.
   *
   * @var int
   */
  private $closedQuestionId;

  /**
   * The user id of the Drupal user.
   *
   * @var int
   */
  private $userId;

  /**
   * Should module save anonymous answers or not.
   *
   * @var bool
   */
  private $anonymousUserSaveAnswer;

  /**
   * Closed question answer storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private $closedQuestionAnswerStorage;

  /**
   * Closed question answer log storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  private $closedQuestionAnswerLogStorage;

  /**
   * Constructs a new CqUserAnswerDefault.
   *
   * @param int $cqid
   *   The closed_question id this answer belongs to.
   * @param int $uid
   *   The user id of the user this answer belongs to.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct($cqid, $uid) {
    $this->closedQuestionId = (int) $cqid;
    $this->userId = (int) $uid;
    $closedQuestionAnswer = FALSE;
    $this->anonymousUserSaveAnswer = \Drupal::config('closedquestion.settings')->get('anonymous_answer');
    $entityTypeManager = \Drupal::entityTypeManager();
    $this->closedQuestionAnswerStorage = $entityTypeManager->getStorage('closedquestion_answer');
    $this->closedQuestionAnswerLogStorage = $entityTypeManager->getStorage('closedquestion_log');

    if ($this->userId > 0 && $this->closedQuestionId > 0) {
      $closedQuestionAnswer = $this->fetchFromDatabase();
    }
    elseif ($this->closedQuestionId > 0) {
      if (isset($_SESSION['cq']['answers'][$cqid]) && $this->anonymousUserSaveAnswer) {
        $closedQuestionAnswer = $_SESSION['cq']['answers'][$cqid];
      }
    }

    if ($closedQuestionAnswer) {
      $this->answerEntity = $closedQuestionAnswer;
      $this->origAnswerSerialized = $this->answerEntity->get('answer')->value;
      $this->origDataSerialized = $this->answerEntity->get('data')->value;
      $this->origData = unserialize($this->origDataSerialized);
      $this->origAnswer = unserialize($this->origAnswerSerialized);
      $this->onceCorrect = $this->answerEntity->get('correct_past')->value;
      $this->origOnceCorrect = $this->onceCorrect;
      $this->origTries = $this->answerEntity->get('tries')->value;
      $this->answer = $this->origAnswer;
      $this->data = $this->origData;
      $this->tries = $this->origTries;
    }
    else {
      $this->answerEntity = $this->closedQuestionAnswerStorage->create();
      $this->answerEntity->set('uid', $uid);
      $this->answerEntity->set('qid', $cqid);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function store() {
    $answerSerialized = serialize($this->answer);
    $dataSerialized = serialize($this->data);
    if ($dataSerialized != $this->origDataSerialized ||
        $answerSerialized != $this->origAnswerSerialized ||
        $this->origTries != $this->tries ||
        $this->origOnceCorrect != $this->onceCorrect) {

      // Store the answer.
      if ($this->userId > 0 && $this->closedQuestionId > 0) {
        $this->answerEntity->set('answer', $answerSerialized);
        $this->answerEntity->set('data', $dataSerialized);
        $this->answerEntity->set('correct_past', $this->onceCorrect);
        $this->answerEntity->set('correct', $this->isCorrect);
        $this->answerEntity->set('tries', $this->tries);
        $this->answerEntity->save();

        /** @var \Drupal\closedquestion\Entity\ClosedQuestionLogInterface $log */
        $log = $this->closedQuestionAnswerLogStorage->create();
        $log->set('answer', $answerSerialized);
        $log->set('correct_past', $this->onceCorrect);
        $log->set('correct', $this->isCorrect);
        $log->set('tries', $this->tries);
        $log->set('uid', $this->userId);
        $log->set('qid', $this->closedQuestionId);
        $log->save();
      }
      elseif ($this->closedQuestionId > 0 && $this->anonymousUserSaveAnswer) {
        $_SESSION['cq']['answers'][$this->closedQuestionId] = $this->answerEntity;
      }

      $this->origAnswer = $this->answer;
      $this->origData = $this->data;
      $this->origTries = $this->tries;
      $this->origOnceCorrect = $this->onceCorrect;
    }
  }

  /**
   * Fetch the answer for this UserAnswer from the database.
   *
   * @return \Drupal\closedquestion\Entity\ClosedQuestionAnswerInterface|null
   *   An array containing the db results or FALSE when there are no results.
   */
  private function fetchFromDatabase() {
    $answer = $this->closedQuestionAnswerStorage->loadByProperties([
      'uid' => $this->userId,
      'qid' => $this->closedQuestionId,
    ]);

    return $answer ? reset($answer) : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getAnswer() {
    return $this->answer;
  }

  /**
   * {@inheritdoc}
   */
  public function setAnswer($newAnswer) {
    $this->answer = $newAnswer;
  }

  /**
   * {@inheritdoc}
   */
  public function reset() {
    // Reset the answer.
    if ($this->userId > 0 && $this->closedQuestionId > 0) {
      $this->closedQuestionAnswerStorage->delete([$this->answerEntity]);
      $this->answerEntity = NULL;

      /** @var \Drupal\closedquestion\Entity\ClosedQuestionLogInterface $log */
      $log = $this->closedQuestionAnswerLogStorage->create();
      $log->set('answer', serialize('Reset'));
      $log->set('correct_past', FALSE);
      $log->set('correct', FALSE);
      $log->set('tries', 0);
      $log->set('uid', $this->userId);
      $log->set('qid', $this->closedQuestionId);
      $log->save();

      $this->answer = NULL;
      $this->tries = 0;
      $this->isCorrect = -1;
      $this->onceCorrect = 0;
      $this->origData = '';
      $this->origTries = -1;
    }
    elseif ($this->closedQuestionId > 0) {
      if (isset($_SESSION['cq']['answers'][$this->closedQuestionId])) {
        unset($_SESSION['cq']['answers'][$this->closedQuestionId]);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function answerHasChanged() {
    return (serialize($this->answer) != $this->origAnswerSerialized);
  }

  /**
   * {@inheritdoc}
   */
  public function getTries() {
    return $this->tries;
  }

  /**
   * {@inheritdoc}
   */
  public function setTries($tries) {
    $this->tries = $tries;
  }

  /**
   * {@inheritdoc}
   */
  public function increaseTries() {
    $this->tries++;
  }

  /**
   * {@inheritdoc}
   */
  public function isCorrect() {
    return $this->isCorrect;
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    return mb_strlen((string) $this->answer) <= 0;
  }

  /**
   * {@inheritdoc}
   */
  public function onceCorrect() {
    return $this->onceCorrect;
  }

  /**
   * {@inheritdoc}
   */
  public function setCorrect($correct) {
    $this->isCorrect = (int) $correct;
    if ($correct && !$this->onceCorrect) {
      $this->onceCorrect = $this->tries + 1;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCorrect() {
    return $this->isCorrect;
  }

  /**
   * {@inheritdoc}
   */
  public function getData($key) {
    if ($this->data !== NULL && array_key_exists($key, $this->data)) {
      return $this->data[$key];
    }
    return NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function setData($key, $value) {
    if ($this->data === NULL) {
      $this->data = array();
    }
    $this->data[$key] = $value;
  }

  /**
   * {@inheritdoc}
   */
  public function getUserId() {
    return $this->userId;
  }

}

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

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