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;
}
}
