query($query, [(int) $quizId]);
if (! $result->numRows()) {
return false;
}
$res = $result->fetchRow();
return $res;
}
public function compute_quiz_stats()
{
$query = "select `quizId` from `tiki_user_quizzes`";
$result = $this->fetchAll($query, []);
$quizStatsSum = $this->table('tiki_quiz_stats_sum');
foreach ($result as $res) {
$quizId = $res["quizId"];
$quizName = $this->getOne("select `name` from `tiki_quizzes` where `quizId`=?", [(int) $quizId]);
$timesTaken = $this->getOne("select count(*) from `tiki_user_quizzes` where `quizId`=?", [(int) $quizId]);
$avgpoints = $this->getOne("select avg(`points`) from `tiki_user_quizzes` where `quizId`=?", [(int) $quizId]);
$maxPoints = $this->getOne("select max(`maxPoints`) from `tiki_user_quizzes` where `quizId`=?", [(int) $quizId]);
$avgavg = ($maxPoints != 0) ? $avgpoints / $maxPoints * 100 : 0.0;
$avgtime = $this->getOne("select avg(`timeTaken`) from `tiki_user_quizzes` where `quizId`=?", [(int) $quizId]);
$quizStatsSum->delete(['quizId' => (int) $quizId,]);
$quizStatsSum->insert(
[
'quizId' => (int) $quizId,
'quizName' => $quizName,
'timesTaken' => (int) $timesTaken,
'avgpoints' => (float) $avgpoints,
'avgtime' => $avgtime,
'avgavg' => $avgavg,
]
);
}
}
/**
* @param $offset
* @param $maxRecords
* @param string $sort_mode
* @param null $find
* @return array
*/
public function list_quizzes($offset, $maxRecords, $sort_mode = 'name_desc', $find = null)
{
$quizzes = $this->table('tiki_quizzes');
$conditions = [];
if (! empty($find)) {
$findesc = '%' . $find . '%';
$conditions['search'] = $quizzes->expr('(`name` like ? or `description` like ?)', [$findesc, $findesc]);
}
$result = $quizzes->fetchColumn('quizId', $conditions);
$res = $ret = $retids = [];
$n = 0;
//FIXME Perm:filter ?
foreach ($result as $res) {
$objperm = Perms::get('quizzes', $res);
if ($objperm->take_quiz) {
if (($maxRecords == -1) || (($n >= $offset) && ($n < ($offset + $maxRecords)))) {
$retids[] = $res;
}
$n++;
}
}
if ($n > 0) {
$result = $quizzes->fetchAll(
$quizzes->all(),
['quizId' => $quizzes->in($retids)],
-1,
-1,
$quizzes->expr($this->convertSortMode($sort_mode))
);
$questions = $this->table('tiki_quiz_questions');
$results = $this->table('tiki_quiz_results');
foreach ($result as $res) {
$res['questions'] = $questions->fetchCount(['quizId' => (int) $res['quizId']]);
$res['results'] = $results->fetchCount(['quizId' => (int) $res['quizId']]);
$ret[] = $res;
}
}
return [
'data' => $ret,
'cant' => $n,
];
}
/**
* @param $userResultId
* @return bool
*/
public function get_user_quiz_result($userResultId)
{
$query = "select * from `tiki_user_quizzes` where `userResultId`=?";
$result = $this->query($query, [$userResultId]);
if (! $result->numRows()) {
return false;
}
$res = $result->fetchRow();
return $res;
}
/**
* @param $quizId
* @param int $offset
* @param $maxRecords
* @param string $sort_mode
* @param string $find
* @return array
*/
public function list_quiz_question_stats($quizId, $offset = 0, $maxRecords = -1, $sort_mode = 'position_asc', $find = '')
{
$query = "select distinct(tqs.`questionId`)"
. " from `tiki_quiz_stats` tqs,`tiki_quiz_questions` tqq"
. " where tqs.`questionId`=tqq.`questionId` and tqs.`quizId` = ? order by "
. $this->convertSortMode($sort_mode);
$result = $this->query($query, [(int) $quizId]);
$ret = [];
while ($res = $result->fetchRow()) {
$question = $this->getOne("select `question` from `tiki_quiz_questions` where `questionId`=?", [(int) $res["questionId"]]);
$total_votes = $this->getOne(
"select sum(`votes`) from `tiki_quiz_stats` where `quizId`=? and `questionId`=?",
[(int) $quizId, (int) $res["questionId"]]
);
$query2 = "select tqq.`optionId`,`votes`,`optionText`"
. " from `tiki_quiz_stats` tqq,`tiki_quiz_question_options` tqo"
. " where tqq.`optionId`=tqo.`optionId` and tqq.`questionId`=?"
;
$result2 = $this->query($query2, [(int) $res["questionId"]]);
$options = [];
while ($res = $result2->fetchRow()) {
$opt = [];
$opt["optionText"] = $res["optionText"];
$opt["votes"] = $res["votes"];
$opt["avg"] = $res["votes"] / $total_votes * 100;
$options[] = $opt;
}
$ques = [];
$ques["options"] = $options;
$ques["question"] = $question;
$ret[] = $ques;
}
return $ret;
}
/**
* @param $answerUploadId
*/
public function download_answer($answerUploadId)
{
$query = "SELECT `filecontent`, `filetype`, `filename`, `filesize` FROM `tiki_user_answers_uploads` WHERE `answerUploadId`=?";
$result = $this->query($query, [(int) $answerUploadId]);
$ret = [];
while ($res = $result->fetchRow()) {
$data = $res['filecontent'];
$name = $res['filename'];
$type = $res['filetype'];
$size = $res['filesize'];
}
$name = htmlspecialchars($name);
header("Content-type: $type");
header("Content-length: $size");
header("Content-Disposition: attachment; filename=\"$name\"");
header("Content-Description: PHP Generated Data");
print $data;
}
/**
* @param $userResultId
* @return array
*/
public function get_user_quiz_questions($userResultId)
{
$query = "select distinct(tqs.`questionId`) from `tiki_user_answers` tqs,`tiki_quiz_questions` tqq"
. " where tqs.`questionId`=tqq.`questionId` and tqs.`userResultId` = ? order by `position` desc";
$result = $this->query($query, [(int) $userResultId]);
$ret = [];
while ($res = $result->fetchRow()) {
$question = $this->getOne("select `question` from `tiki_quiz_questions` where `questionId`=?", [(int) $res["questionId"]]);
$questionId = $res["questionId"];
$query2 = "select tqq.`optionId`,tqo.`points`,`optionText`"
. " from `tiki_user_answers` tqq,`tiki_quiz_question_options` tqo"
. " where tqq.`optionId`=tqo.`optionId` and tqq.`userResultId`=? and tqq.`questionId`=?";
$result2 = $this->query($query2, [(int) $userResultId, (int) $questionId]);
$options = [];
while ($res = $result2->fetchRow()) {
$opt = [];
$opt["optionText"] = $res["optionText"];
$opt["points"] = $res["points"];
$query3 = "select `answerUploadId`, `filename` from `tiki_user_answers_uploads` where `userResultId` = ? and `questionId` = ?";
$result3 = $this->query($query3, [(int) $userResultId, (int) $questionId]);
while ($res2 = $result3->fetchRow()) {
$opt["filename"] = $res2["filename"];
$opt["answerUploadId"] = $res2["answerUploadId"];
}
$options[] = $opt;
}
$ques = [];
$ques["options"] = $options;
$ques["question"] = $question;
$ret[] = $ques;
}
return $ret;
}
/**
* @param $userResultId
*/
public function remove_quiz_stat($userResultId)
{
$query = "select `quizId`,`user` from `tiki_user_quizzes` where `userResultId`=?";
$bindvars = [(int) $userResultId];
$result = $this->query($query, $bindvars);
$res = $result->fetchRow();
$user = $res["user"];
$quizId = $res["quizId"];
$query = "delete from `tiki_user_taken_quizzes` where `user`=? and `quizId`=?";
$result = $this->query($query, [$user, (int) $quizId]);
$query = "delete from `tiki_user_quizzes` where `userResultId`=?";
$result = $this->query($query, $bindvars);
$query = "delete from `tiki_user_answers` where `userResultId`=?";
$result = $this->query($query, $bindvars);
}
/**
* @param $quizId
*/
public function clear_quiz_stats($quizId)
{
$query = "delete from `tiki_user_taken_quizzes` where `quizId`=?";
$bindvars = [(int) $quizId];
$result = $this->query($query, $bindvars);
$query = "delete from `tiki_quiz_stats_sum` where `quizId`=?";
$result = $this->query($query, $bindvars);
$query = "delete from `tiki_quiz_stats` where `quizId`=?";
$result = $this->query($query, $bindvars);
$query = "delete from `tiki_user_quizzes` where `quizId`=?";
$result = $this->query($query, $bindvars);
$query = "delete from `tiki_user_answers` where `quizId`=?";
$result = $this->query($query, $bindvars);
}
/**
* @param $quizId
* @param $offset
* @param $maxRecords
* @param $sort_mode
* @param $find
* @return array
*/
public function list_quiz_stats($quizId, $offset, $maxRecords, $sort_mode, $find)
{
$this->compute_quiz_stats();
$query = "select `passingperct` from `tiki_quizzes` where `quizId` = ?";
$passingperct = $this->getOne($query, [(int) $quizId]);
if ($find) {
//isnt that superflous? hmm.
$findesc = '%' . $find . '%';
}
$mid = " where `quizId`=?";
$bindvars = [(int) $quizId];
$query = "select * from `tiki_user_quizzes` $mid order by " . $this->convertSortMode($sort_mode);
$query_cant = "select count(*) from `tiki_user_quizzes` $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = [];
while ($res = $result->fetchRow()) {
$res["avgavg"] = ($res["maxPoints"] != 0) ? $res["points"] / $res["maxPoints"] * 100 : 0.0;
if (isset($passingperct) && $passingperct > 0) {
$res['ispassing'] = ($res["avgavg"] >= $passingperct) ? true : false;
}
$hasDet = $this->getOne(
"select count(*) from `tiki_user_answers` where `userResultId`=?",
[(int) $res["userResultId"]]
);
if ($hasDet) {
$res["hasDetails"] = 'y';
} else {
$res["hasDetails"] = 'n';
}
$ret[] = $res;
}
$retval = [];
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/**
* @param $offset
* @param $maxRecords
* @param $sort_mode
* @param $find
* @return array
*/
public function list_quiz_sum_stats($offset, $maxRecords, $sort_mode, $find)
{
$this->compute_quiz_stats();
$stats = $this->table('tiki_quiz_stats_sum');
$conditions = [];
if ($find) {
$conditions['quizName'] = $stats->like("%$find%");
}
return [
'data' => $stats->fetchAll($stats->all(), $conditions, $maxRecords, $offset, $stats->expr($this->convertSortMode($sort_mode))),
'cant' => $stats->fetchCount($conditions),
];
}
// Takes a given uploaded answer and inserts it into the DB. - burley
/**
* @param $userResultId
* @param $questionId
* @param $filename
* @param $filetype
* @param $filesize
* @param $tmp_name
*/
public function register_user_quiz_answer_upload($userResultId, $questionId, $filename, $filetype, $filesize, $tmp_name)
{
$data = fread(fopen($tmp_name, "r"), filesize($tmp_name));
$query = "insert into `tiki_user_answers_uploads`"
. "(`userResultId`,`questionId`,`filename`,`filetype`,`filesize`,`filecontent`)"
. " values(?,?,?,?,?,?)";
$result = $this->query($query, [(int) $userResultId, (int) $questionId, $filename, $filetype, $filesize, $data]);
}
/**
* @param $userResultId
* @param $quizId
* @param $questionId
* @param $optionId
*/
public function register_user_quiz_answer($userResultId, $quizId, $questionId, $optionId)
{
$query = "insert into `tiki_user_answers`(`userResultId`,`quizId`,`questionId`,`optionId`) values(?,?,?,?)";
$result = $this->query($query, [(int) $userResultId, (int) $quizId, (int) $questionId, (int) $optionId]);
}
/**
* @param $quizId
* @param $user
* @param $timeTaken
* @param $points
* @param $maxPoints
* @param $resultId
* @return mixed
*/
public function register_quiz_stats($quizId, $user, $timeTaken, $points, $maxPoints, $resultId)
{
// Fix a bug if no result is indicated.
if (! $resultId) {
$resultId = 0;
}
$query = "insert into `tiki_user_quizzes`(`user`,`quizId`,`timestamp`,`timeTaken`,`points`,`maxPoints`,`resultId`) values(?,?,?,?,?,?,?)";
$result = $this->query(
$query,
[
$user,
$quizId,
$this->now,
$timeTaken,
$points,
$maxPoints,
$resultId
]
);
$queryId = $this->getOne(
"select max(`userResultId`) from `tiki_user_quizzes` where `timestamp`=? and `quizId`=?",
[$this->now, (int) $quizId]
);
return $queryId;
}
/**
* @param $quizId
* @param $questionId
* @param $optionId
* @return bool
*/
public function register_quiz_answer($quizId, $questionId, $optionId)
{
$cant = $this->getOne(
"select count(*) from `tiki_quiz_stats` where `quizId`=? and `questionId`=? and `optionId`=?",
[(int) $quizId, (int) $questionId, (int) $optionId]
);
if ($cant) {
$query = "update `tiki_quiz_stats` set `votes`=`votes`+1 where `quizId`=? and `questionId`=? and `optionId`=?";
$bindvars = [(int) $quizId, (int) $questionId, (int) $optionId];
} else {
$query = "insert into `tiki_quiz_stats`(`quizId`,`questionId`,`optionId`,`votes`) values(?,?,?,?)";
$bindvars = [(int) $quizId, (int) $questionId, (int) $optionId,1];
}
$result = $this->query($query, $bindvars);
return true;
}
/**
* @param $quizId
* @param $points
* @return int
*/
public function calculate_quiz_result($quizId, $points)
{
$query = "select * from `tiki_quiz_results` where `fromPoints`<=? and `toPoints`>=? and `quizId`=?";
$result = $this->query($query, [(int) $points, (int) $points, (int) $quizId]);
if (! $result->numRows()) {
return 0;
}
$res = $result->fetchRow();
return $res;
}
/**
* @param $user
* @param $quizId
* @return mixed
*/
public function user_has_taken_quiz($user, $quizId)
{
$cant = $this->getOne("select count(*) from `tiki_user_taken_quizzes` where `user`=? and `quizId`=?", [$user, (int) $quizId]);
return $cant;
}
/**
* @param $user
* @param $quizId
*/
public function user_takes_quiz($user, $quizId)
{
$query = "delete from `tiki_user_taken_quizzes` where `user`=? and `quizId`=?";
$bindvars = [$user,(int) $quizId];
$result = $this->query($query, $bindvars, -1, -1, false);
$query = "insert into `tiki_user_taken_quizzes`(`user`,`quizId`) values(?,?)";
$result = $this->query($query, $bindvars);
}
/**
* @param $resultId
* @param $quizId
* @param $fromPoints
* @param $toPoints
* @param $answer
* @return mixed
*/
public function replace_quiz_result($resultId, $quizId, $fromPoints, $toPoints, $answer)
{
if ($resultId) {
// update an existing quiz
$query = "update `tiki_quiz_results` set `fromPoints` = ?, `toPoints` = ?, `quizId` = ?, `answer` = ? where `resultId` = ?";
$bindvars = [(int) $fromPoints,(int) $toPoints, (int) $quizId, $answer, (int) $resultId];
$result = $this->query($query, $bindvars);
} else {
// insert a new quiz
$query = "insert into `tiki_quiz_results`(`quizId`,`fromPoints`,`toPoints`,`answer`) values(?,?,?,?)";
$bindvars = [(int) $quizId, (int) $fromPoints, (int) $toPoints, $answer];
$result = $this->query($query, $bindvars);
$queryid = "select max(`resultId`) from `tiki_quiz_results` where `fromPoints`=? and `toPoints`=? and `quizId`=?";
$quizId = $this->getOne($queryid, [(int) $fromPoints, (int) $toPoints, $quizId]);
}
return $quizId;
}
/**
* @param $resultId
* @return bool
*/
public function get_quiz_result($resultId)
{
$query = "select * from `tiki_quiz_results` where `resultId`=?";
$result = $this->query($query, [(int) $resultId]);
if (! $result->numRows()) {
return false;
}
$res = $result->fetchRow();
return $res;
}
/**
* @param $resultId
* @return bool
*/
public function remove_quiz_result($resultId)
{
$query = "delete from `tiki_quiz_results` where `resultId`=?";
$result = $this->query($query, [$resultId]);
return true;
}
/**
* @param $quizId
* @param $offset
* @param $maxRecords
* @param $sort_mode
* @param $find
* @return array
*/
public function list_quiz_results($quizId, $offset, $maxRecords, $sort_mode, $find)
{
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where `quizId`=? and `answer` like ? ";
$bindvars = [(int) $quizId, $findesc];
} else {
$mid = " where `quizId`=? ";
$bindvars = [(int) $quizId];
}
$query = "select * from `tiki_quiz_results` $mid order by " . $this->convertSortMode($sort_mode);
$query_cant = "select count(*) from `tiki_quiz_results` $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = [];
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = [];
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
// called by tiki-edit_quiz.php
/**
* @param $quizId
* @param $name
* @param $description
* @param $canRepeat
* @param $storeResults
* @param $immediateFeedback
* @param $showAnswers
* @param $shuffleQuestions
* @param $shuffleAnswers
* @param $questionsPerPage
* @param $timeLimited
* @param $timeLimit
* @param $publishDate
* @param $expireDate
* @param $passingperct
* @return mixed
*/
public function replace_quiz($quizId, $name, $description, $canRepeat, $storeResults, $immediateFeedback, $showAnswers, $shuffleQuestions, $shuffleAnswers, $questionsPerPage, $timeLimited, $timeLimit, $publishDate, $expireDate, $passingperct)
{
if ($quizId) {
// update an existing quiz
$query = "update `tiki_quizzes` set `name` = ?, `description` = ?, `canRepeat` = ?, `storeResults` = ?,";
$query .= "`immediateFeedback` = ?, `showAnswers` = ?, `shuffleQuestions` = ?, `shuffleAnswers` = ?, ";
$query .= "`publishDate` = ?, `expireDate` = ?, ";
$query .= "`questionsPerPage` = ?, `timeLimited` = ?, `timeLimit` =?, `passingperct` = ? where `quizId` = ?";
$bindvars = [$name,
$description,
$canRepeat,
$storeResults,
$immediateFeedback,
$showAnswers,
$shuffleQuestions,
$shuffleAnswers,
$publishDate,
$expireDate,
(int) $questionsPerPage,
$timeLimited,
(int) $timeLimit,
(int) $passingperct,
(int) $quizId
];
$result = $this->query($query, $bindvars);
} else {
// insert a new quiz
$query = "insert into `tiki_quizzes`(`name`,`description`,`canRepeat`,`storeResults`,";
$query .= "`immediateFeedback`, `showAnswers`, `shuffleQuestions`, `shuffleAnswers`,";
$query .= "`publishDate`, `expireDate`,";
$query .= "`questionsPerPage`,`timeLimited`,`timeLimit`,`created`,`taken`,`passingperct`)";
$query .= " values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
$bindvars = [
$name,
$description,
$canRepeat,
$storeResults,
$immediateFeedback,
$showAnswers,
$shuffleQuestions,
$shuffleAnswers,
$publishDate,
$expireDate,
(int) $questionsPerPage,
$timeLimited,
(int) $timeLimit,
(int) $this->now,
0,
(int) $passingperct
];
$result = $this->query($query, $bindvars);
$queryid = "select max(`quizId`) from `tiki_quizzes` where `created`=?";
$quizId = $this->getOne($queryid, [(int) $this->now]);
}
return $quizId;
}
/**
* @param $questionId
* @param $question
* @param $type
* @param $quizId
* @param $position
* @return mixed
*/
public function replace_quiz_question($questionId, $question, $type, $quizId, $position)
{
if ($questionId) {
// update an existing quiz
$query = "update `tiki_quiz_questions` set `type`=?, `position` = ?, `question` = ? where `questionId` = ? and `quizId`=?";
$bindvars = [$type,(int) $position, $question, (int) $questionId, (int) $quizId];
$result = $this->query($query, $bindvars);
} else {
// insert a new quiz
$query = "insert into `tiki_quiz_questions`(`question`,`type`,`quizId`,`position`) values(?,?,?,?)";
$bindvars = [$question, $type, (int) $quizId, (int) $position];
$result = $this->query($query, $bindvars);
$queryid = "select max(`questionId`) from `tiki_quiz_questions` where `question` like ? and `type`=?";
$questionId = $this->getOne($queryid, [substr($question, 0, 200) . "%", $type]);
}
return $questionId;
}
/**
* @param $optionId
* @param $option
* @param $points
* @param $questionId
* @return mixed
*/
public function replace_question_option($optionId, $option, $points, $questionId)
{
// validating the points value
if ((! is_numeric($points)) || ($points == "")) {
$points = 0;
}
if ($optionId) {
$query = "update `tiki_quiz_question_options` set `points`=?, `optionText` = ? where `optionId` = ? and `questionId`=?";
$bindvars = [(int) $points, $option,(int) $optionId, (int) $questionId];
$result = $this->query($query, $bindvars);
} else {
$query = "insert into `tiki_quiz_question_options`(`optionText`,`points`,`questionId`) values(?,?,?)";
$result = $this->query($query, [$option, (int) $points, (int) $questionId]);
$queryid = "select max(`optionId`) from `tiki_quiz_question_options` where `optionText`=? and `questionId`=?";
$optionId = $this->getOne($queryid, [$option, (int) $questionId]);
}
return $optionId;
}
/**
* @param $questionId
* @return bool
*/
public function get_quiz_question($questionId)
{
$query = "select * from `tiki_quiz_questions` where `questionId`=?";
$result = $this->query($query, [(int) $questionId]);
if (! $result->numRows()) {
return false;
}
$res = $result->fetchRow();
return $res;
}
/**
* @param $optionId
* @return bool
*/
public function get_quiz_question_option($optionId)
{
$query = "select * from `tiki_quiz_question_options` where `optionId`=?";
$result = $this->query($query, [(int) $optionId]);
if (! $result->numRows()) {
return false;
}
$res = $result->fetchRow();
return $res;
}
/**
* @param $quizId
* @param $offset
* @param $maxRecords
* @param $sort_mode
* @param $find
* @return array
*/
public function list_quiz_questions($quizId, $offset, $maxRecords, $sort_mode, $find)
{
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where `quizId`=? and `question` like ? ";
$bindvars = [(int) $quizId, $findesc];
} else {
$mid = " where `quizId`=? ";
$bindvars = [(int) $quizId];
}
$query = "select * from `tiki_quiz_questions` $mid order by " . $this->convertSortMode($sort_mode);
$query_cant = "select count(*) from `tiki_quiz_questions` $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = [];
while ($res = $result->fetchRow()) {
$res["options"] = $this->getOne("select count(*) from `tiki_quiz_question_options` where `questionId`=?", [(int) $res["questionId"]]);
$res["maxPoints"] = $this->getOne("select max(`points`) from `tiki_quiz_question_options` where `questionId`=?", [(int) $res["questionId"]]);
$ret[] = $res;
}
$retval = [];
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/**
* @param $offset
* @param $maxRecords
* @param string $sort_mode
* @param $find
* @return array
*/
public function list_all_questions($offset, $maxRecords, $sort_mode, $find)
{
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where `question` like ? ";
$bindvars = [$findesc];
} else {
$mid = " ";
$bindvars = [];
}
$query = "select * from `tiki_quiz_questions` $mid order by " . $this->convertSortMode($sort_mode);
$query_cant = "select count(*) from `tiki_quiz_questions` $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = [];
while ($res = $result->fetchRow()) {
$res["options"]
= $this->getOne("select count(*) from `tiki_quiz_question_options` where `questionId`=?", [(int) $res["questionId"]]);
$ret[] = $res;
}
$retval = [];
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/**
* @param $questionId
* @param $offset
* @param $maxRecords
* @param $sort_mode
* @param $find
* @return array
*/
public function list_quiz_question_options($questionId, $offset, $maxRecords, $sort_mode, $find)
{
if ($find) {
$findesc = '%' . $find . '%';
$mid = " where `questionId`=? and `optionText` like ? ";
$bindvars = [(int) $questionId,$findesc];
} else {
$mid = " where `questionId`=? ";
$bindvars = [(int) $questionId];
}
$query = "select * from `tiki_quiz_question_options` $mid order by " . $this->convertSortMode($sort_mode);
$query_cant = "select count(*) from `tiki_quiz_question_options` $mid";
$result = $this->query($query, $bindvars, $maxRecords, $offset);
$cant = $this->getOne($query_cant, $bindvars);
$ret = [];
while ($res = $result->fetchRow()) {
$ret[] = $res;
}
$retval = [];
$retval["data"] = $ret;
$retval["cant"] = $cant;
return $retval;
}
/**
* @param $questionId
* @return bool
*/
public function remove_quiz_question($questionId)
{
$query = "delete from `tiki_quiz_questions` where `questionId`=?";
$result = $this->query($query, [(int) $questionId]);
// Remove all the options for the question
$query = "delete from `tiki_quiz_question_options` where `questionId`=?";
$result = $this->query($query, [(int) $questionId]);
return true;
}
/**
* @param $optionId
* @return bool
*/
public function remove_quiz_question_option($optionId)
{
$query = "delete from `tiki_quiz_question_options` where `optionId`=?";
$result = $this->query($query, [(int) $optionId]);
return true;
}
/**
* @param $quizId
* @return bool
*/
public function remove_quiz($quizId)
{
$query = "delete from `tiki_quizzes` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$query = "select * from `tiki_quiz_questions` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
// Remove all the options for each question
while ($res = $result->fetchRow()) {
$questionId = $res["questionId"];
$query2 = "delete from `tiki_quiz_question_options` where `questionId`=?";
$result2 = $this->query($query2, [(int) $questionId]);
}
// Remove all the questions
$query = "delete from `tiki_quiz_questions` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$query = "delete from `tiki_quiz_results` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$query = "delete from `tiki_quiz_stats` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$query = "delete from `tiki_user_quizzes` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$query = "delete from `tiki_user_answers` where `quizId`=?";
$result = $this->query($query, [(int) $quizId]);
$this->remove_object('quiz', $quizId);
return true;
}
/**
* @param $id
* @return Quiz
*/
public function quiz_fetch($id)
{
if ($id == 0) {
$quiz = new Quiz();
} else {
echo __FILE__ . " line: " . __LINE__ . " : Need to fetch a quiz from the database" . "
";
}
return $quiz;
}
// $quiz is a quiz object
/**
* @param $quiz
* @return mixed
*/
public function quiz_store($quiz)
{
echo __FILE__ . " line: " . __LINE__ . ": in quizlib->quiz_store
";
echo "Store stuff in the dbFields array.
";
foreach ($quiz->dbFields as $f) {
}
die;
if ($quizId) {
// update an existing quiz
$query = "update `tiki_quizzes` set `name` = ?, `description` = ?, `canRepeat` = ?, `storeResults` = ?,";
$query .= "`immediateFeedback` = ?, `showAnswers` = ?, `shuffleQuestions` = ?, `shuffleAnswers` = ?, ";
$query .= "`publishDate` = ?, `expireDate` = ?, ";
$query .= "`questionsPerPage` = ?, `timeLimited` = ?, `timeLimit` =? where `quizId` = ?";
$bindvars = [
$name,
$description,
$canRepeat,
$storeResults,
$immediateFeedback,
$showAnswers,
$shuffleQuestions,
$shuffleAnswers,
$publishDate,
$expireDate,
(int) $questionsPerPage,
$timeLimited,
(int) $timeLimit,
(int) $quizId
];
$result = $this->query($query, $bindvars);
} else {
// insert a new quiz
$query = "insert into `tiki_quizzes`(`name`,`description`,`canRepeat`,`storeResults`,";
$query .= "`immediateFeedback`, `showAnswers`, `shuffleQuestions`, `shuffleAnswers`,";
$query .= "`publishDate`, `expireDate`,";
$query .= "`questionsPerPage`,`timeLimited`,`timeLimit`,`created`,`taken`) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
$bindvars = [$name,
$description,
$canRepeat,
$storeResults,
$immediateFeedback,
$showAnswers,
$shuffleQuestions,
$shuffleAnswers,
$publishDate,
$expireDate,
(int) $questionsPerPage,
$timeLimited,
(int) $timeLimit,
(int) $this->now,
0
];
$result = $this->query($query, $bindvars);
$queryid = "select max(`quizId`) from `tiki_quizzes` where `created`=?";
$quizId = $this->getOne($queryid, [(int) $this->now]);
}
return $quizId;
}
/**
* @return string
*/
public function get_upload_dir()
{
return "quiz_uploads/";
}
}
// Find the next non-blank or return -1
/**
* @param $text
* @return int
*/
function NextText($text)
{
$found = -1;
for ($i = 0, $icount_text = count($text); $i < $icount_text; $i++) {
if (strlen($text[$i]) > 0) {
$found = $i;
break;
}
}
return $found;
}
// Find the next blank or retrun the last element
/**
* @param $text
* @return int
*/
function NextBlank($text)
{
$found = 0;
for ($i = 0, $icount_text = count($text); $i < $icount_text; $i++) {
$found = $i;
if ($text[$i] == "") {
break;
}
}
return $found;
}
/**
* @param $s
*/
function quizlib_error_exit($s)
{
$smarty = TikiLib::lib('smarty');
$smarty->assign('msg', $s);
$smarty->display("error.tpl");
die;
}
// Called by tiki-edit_quiz_questions.php
// Convert a block of text into an array of question objects.
/**
* @param $text
* @return array
*/
function TextToQuestions($text)
{
$text = preg_replace("/\r\n/", "\n", $text);
$text = preg_replace("/\n\r/", "\n", $text);
$text = preg_replace("/\r/", "\n", $text);
$text = preg_replace("/\t/", " ", $text);
$text = preg_replace("/[ ]+/", " ", $text);
$text = preg_split("/\n/", $text);
if ($text[count($text) - 1] != "") {
$text[] = "";
}
for ($i = 0, $icount_text = count($text); $i < $icount_text; $i++) {
$text[$i] = trim($text[$i]);
if ($text[$i] and ! ctype_print($text[$i])) {
quizlib_error_exit(
"lib/quizzes/quizlib.php line "
. __LINE__
. ": Your text has invalid character(s) near line $i where it says:\n $text[$i]"
);
}
}
$questions = [];
while (NextText($text) != -1) {
$text = array_slice($text, NextText($text));
$lines = array_slice($text, 0, NextBlank($text));
$text = array_slice($text, NextBlank($text));
if (count($lines) > 0) {
$question = new HW_QuizQuestionMultipleChoice($lines);
array_push($questions, $question);
}
}
return $questions;
}
// An abstract class
/**
*
*/
class HW_QuizQuestion
{
public $question;
/**
* @param $lines
*/
public function from_text($lines)
{
// Set the question according to an array of text lines.
}
public function getQuestion()
{
return $this->question;
}
public function to_text()
{
// Export the question to an array of text lines.
}
public function getAnswerCount()
{
// How many possible answers (i.e. choices in a multiple-choice)
}
}
// A multiple-choice quiz question
// e.g.
// $question = "What is your favorite color?";
// $choices = Array(Array('text'=>"Red", 'correct'=>1),
// Array('text'=>"Blue", 'correct'=>1),
// Array('text'=>"Green",'correct'=>1));
// Any of the answers are correct in this example.
/**
*
*/
class HW_QuizQuestionMultipleChoice extends HW_QuizQuestion
{
public $choices = [];
/**
* @param $lines
*/
public function __construct($lines)
{
$this->from_text($lines);
}
// Import from text array
// $lines is in array of text items.
// The 0th line is the question.
// The rest of the lines are answers.
// Correct answers start with a "*"
/**
* @param $lines
*/
public function from_text($lines)
{
$this->question = $lines[0];
$this->choices = [];
$lines = array_slice($lines, 1);
foreach ($lines as $line) {
if (preg_match("/^\*\s*(.*)/", $line, $match)) {
// Ignore spaces after the "*"
$a = ['text' => $match[1],'correct' => 1];
} else {
$a = ['text' => $line,'correct' => 0];
}
array_push($this->choices, $a);
}
}
// Export the question to an array of text lines.
/**
* @param bool $show_answer
* @return array
*/
public function to_text($show_answer = false)
{
$lines = [];
array_push($lines, $this->question);
foreach ($this->choices as $choice) {
if ($show_answer && $choice['correct']) {
array_push($lines, "*" . $choice['text']);
} else {
array_push($lines, " " . $choice['text']);
}
}
return $lines;
}
/**
* @return int
*/
public function getChoiceCount()
{
return count($this->choices);
}
/**
* @param $i
* @return mixed
*/
public function getChoice($i)
{
return $this->choices[$i]['text'];
}
/**
* @param $i
* @return mixed
*/
public function getCorrect($i)
{
return $this->choices[$i]['correct'];
}
public function dump()
{
echo "question = \"" . $this->question . "\"\n";
echo "choices =\n";
foreach ($this->choices as $choice) {
if ($choice['correct']) {
echo "*";
} else {
echo " ";
}
echo $choice['text'] . "\n";
}
}
}
// A Yes-No quiz question
// e.g.
// $question = "Do you wiki?";
// $answer = -1 (unknown), 0 (no), 1 (yes)
/**
*
*/
class HW_QuizQuestionYesNo extends HW_QuizQuestion
{
public $question;
public $answer = -1;
/**
* @param $lines
*/
public function __construct($lines)
{
$this->from_text($lines);
}
// Import from text array
// $lines is in array of text items.
// The 0th line is the question.
// The first line is the answer.
/**
* @param $lines
*/
public function from_text($lines)
{
$this->question = $lines[0];
if (preg_match("/^\s*[Yy][Ee][Ss]\s*$/", $lines[1])) {
// Ignore spaces and case
$this->answer = 1;
} elseif (preg_match("/^\s*[Nn][Oo]\s*$/", $lines[1])) {
// Ignore spaces and case
$this->answer = 0;
} else {
$this->answer = -1;
}
}
/**
* @param bool $show_answer
* @return array
*/
public function to_text($show_answer = false)
{
// Export the question to an array of text lines.
$lines = [];
array_push($lines, $this->question);
if ($this->answer == 1) {
array_push($lines, " Yes");
} elseif ($this->answer == 0) {
array_push($lines, " No");
} else {
array_push($lines, " Unknown");
}
return $lines;
}
public function dump()
{
echo "question = \"" . $this->question . "\"\n";
echo "answer = $this->answer\n";
}
}
/**
*
*/
class Quiz
{
public $id;
public $bDeleted;
public $timestamp;
public $nAuthor;
public $bOnline;
public $nTaken;
public $sName;
public $sDescription;
public $datePub;
public $dateExp;
public $bRandomQuestions;
public $nRandomQuestions;
public $bShuffleQuestions;
public $bShuffleAnswers;
public $bLimitQuestionsPerPage;
public $nLimitQuestionsPerPage;
public $bTimeLimited;
public $nTimeLimit;
public $bMultiSession;
public $bCanRepeat;
public $nCanRepeat;
public $sGradingMethod;
public $sShowScore;
public $sShowCorrectAnswers;
public $sPublishStats;
public $bAdditionalQuestions;
public $bForum;
public $sForum;
public $sPrologue;
public $sData;
public $sEpilogue;
public $dbFields;
public function __construct()
{
global $user;
$userlib = TikiLib::lib('user');
$this->dbFields = [
"id",
"bDeleted",
"timestamp",
"nAuthor",
"bOnline",
"nTaken",
"sName",
"sDescription",
"datePub",
"dateExp",
"bRandomQuestions",
"nRandomQuestions",
"bShuffleQuestions",
"bShuffleAnswers",
"bLimitQuestionsPerPage",
"nLimitQuestionsPerPage",
"bTimeLimited",
"nTimeLimit",
"bMultiSession",
"bCanRepeat",
"nCanRepeat",
"sGradingMethod",
"sShowScore",
"sShowCorrectAnswers",
"sPublishStats",
"bAdditionalQuestions",
"bForum",
"sForum",
"sPrologue",
"sData",
"sEpilogue"
];
$this->id = 0;
$this->bDeleted = 0;
$this->timestamp = $this->now;
$this->nAuthor = $userlib->get_user_id($user);
$this->sAuthor = $user;
$this->bOnline = 'n';
$this->nTaken = 'n';
$this->sName = "";
$this->sDescription = "";
$this->datePub = $this->now;
$this->dateExp = TikiLib::make_time(0, 0, 0, 1, 1, TikiLib::date_format("%Y") + 10);
$this->bRandomQuestions = "y";
$this->nRandomQuestions = 10;
$this->nShuffleQuestions = "y";
$this->bShuffleAnswers = "y";
$this->bLimitQuestionsPerPage = "y";
$this->nLimitQuestionsPerPage = 1;
$this->bTimeLimited = "n";
$this->nTimeLimit = "1";
$this->bMultiSession = "n";
$this->bCanRepeat = "y";
$this->nCanRepeat = "unlimited";
$this->sGradingMethod = "machine";
$this->sShowScore = "immediately";
$this->sShowCorrectAnswers = "immediately";
$this->sPublishStats = "immediately";
$this->bAdditionalQuestions = "n";
$this->forum = "n";
$this->forumName = "";
$this->prologue = "";
$this->epilogue = "";
}
// dump as html text
/**
* @return array
*/
public function show_html()
{
$userlib = TikiLib::lib('user');
$lines = [];
$lines[] = "id = " . $this->id . "
";
$lines[] = "deleted = " . $this->deleted . "
";
$authorInfo = $userlib->get_userid_info($this->author);
$lines[] = "author id = " . $this->author . "; author login = " . $authorInfo["login"] . "
";
$lines[] = "version = " . $this->version . "
";
$lines[] = "timestamp = " . $this->date_format("%a, %e %b %Y %H:%M:%S %O", $this->timestamp) . "
";
$lines[] = "online = " . $this->online . "
";
$lines[] = "studentAttempts = " . $this->studentAttempts . "
";
$lines[] = "name = " . $this->name . "
";
$lines[] = "description = " . $this->description . "
";
$lines[] = "datePub = " . $this->date_format("%a, %e %b %Y %H:%M:%S %O", $this->datePub) . "
";
$lines[] = "dateExp = " . $this->date_format("%a, %e %b %Y %H:%M:%S %O", $this->dateExp) . "
";
$lines[] = "nQuestion = " . $this->nQuestion . "
";
$lines[] = "nQuestions = " . $this->nQuestions . "
";
$lines[] = "shuffleQuestions = " . $this->shuffleQuestions . "
";
$lines[] = "shuffleAnswers = " . $this->shuffleAnswers . "
";
$lines[] = "limitDisplay = " . $this->limitDisplay . "
";
$lines[] = "questionsPerPage = " . $this->questionsPerPage . "
";
$lines[] = "timeLimited = " . $this->timeLimited . "
";
$lines[] = "timeLimit = " . $this->timeLimit . "
";
$lines[] = "multiSession = " . $this->multiSession . "
";
$lines[] = "canRepeat = " . $this->canRepeat . "
";
$lines[] = "repetitions = " . $this->repetitions . "
";
$lines[] = "gradingMethod = " . $this->gradingMethod . "
";
$lines[] = "showScore = " . $this->showScore . "
";
$lines[] = "showCorrectAnswers = " . $this->showCorrectAnswers . "
";
$lines[] = "publishStats = " . $this->publishStats . "
";
$lines[] = "additionalQuestions = " . $this->additionalQuestions . "
";
$lines[] = "forum = " . $this->forum . "
";
$lines[] = "forumName = " . $this->forumName . "
";
$lines[] = "data = " . $this->data . "
";
return $lines;
}
// Use any data in the array to replace the instance data.
/**
* @param $data
*/
public function data_load($data)
{
foreach ($this as $key => $val) {
if (isset($data[$key]) && ($data[$key] != $val)) {
$this->$key = $data[$key];
}
}
}
/**
* @param $quiz
*/
public function compare($quiz)
{
}
public function getAnswerCount()
{
// How many possible answers (i.e. choices in a multiple-choice)
}
}