Poll.php
práce s jednou anketou
php
<?php
class Poll
{
/** @var array */
private $data = array();
/** @var bool */
private $exists;
/** @var Database */
private $db;
const COOKIE_VOTE = "devbook_poll_vote";
/**
* @param int|NULL
* @param bool
*/
public function __construct($id = NULL)
{
$this->db = Database::getInstance();
if ($id !== NULL) {
$query = $this->db->prepare("
SELECT `question`
FROM `poll`
WHERE `id` = ?
LIMIT 1
");
$query->execute(array($id));
$data = $query->fetch(PDO::FETCH_ASSOC);
if ($data) {
$data["id"] = $id;
$data["answers"] = array();
$query = $this->db->prepare("
SELECT `id`, `text`, `count`, `color`
FROM `poll_answer`
WHERE `poll_id` = ?
");
$query->execute(array($id));
$answers = $query->fetchAll();
foreach ($answers as $answer) {
$data["answers"][] = array(
"id" => $answer["id"],
"answer" => $answer["text"],
"count" => $answer["count"],
"color" => $answer["color"]
);
}
$this->data = $data;
$this->exists = TRUE;
} else {
$this->exists = FALSE;
}
}
}
/**
* @param string
* @param mixed
* @throws PollException
*/
public function __set($name, $value)
{
throw new PollException("Do třídy 'Poll' nelze ukládat nové hodnoty.");
}
/**
* @param string
* @return mixed
*/
public function __get($key)
{
return $this->data[$key];
}
/**
* @param string
*/
public function __isset($key)
{
return isset($this->data[$key]);
}
/**
* @param string
* @throws PollException
*/
public function __unset($key)
{
throw new PollException("Že třídy 'Poll' nelze mazat žádné hodnoty.");
}
/**
* @return array
*/
public function getData()
{
return $this->data;
}
/**
* @param string
* @param array
* @param array
* @throws PollException
*/
public function create($question, array $answers, array $colors)
{
if ($question === "") {
throw new PollException("Nebyla zadána otázka.");
}
if (count($answers) < 2) {
throw new PollException("Anketa musí mít minimálně dvě odpovědi.");
}
$data = array();
for ($i = 0; $i < count($answers); $i++) {
if (!empty($answers[$i]) && !empty($colors[$i])) {
$data[] = array(
"id" => $answers[$i],
"color" => $colors[$i]
);
}
}
if (count($data) < 2) {
throw new PollException("Anketa musí mít minimálně dvě odpovědi.");
}
$this->db->beginTransaction();
$query = $this->db->prepare("
INSERT INTO `poll` (`id`, `question`)
VALUES (?, ?)
");
$query->execute(array(NULL, $question));
$id = $this->db->lastInsertId();
foreach ($data as $answer) {
$query = $this->db->prepare("
INSERT INTO `poll_answer` (`id`, `poll_id`, `text`, `count`, `color`)
VALUES (?, ?, ?, ?, ?)
");
$query->execute(array(NULL, $id, $answer["id"], 0, $answer["color"]));
}
$this->db->commit();
}
/**
* @return bool
*/
public function exists()
{
return $this->exists;
}
/**
* @param string|NULL
* @param bool
* @return string
*/
public function getForm($action = NULL, $createJS = TRUE)
{
if ($action === NULL) {
$action = $_SERVER["REQUEST_URI"];
}
$return = <<<EOT
<form action="{$action}" method="post">
<table>
<tr><th><label for="add_question">Otázka</label></th></tr>
<tr><td><input type="text" id="add_question" name="question" size="40" required></td></tr>
<tr><td><a href="javascript:addAnswer()">Přidat odpověď</a></td></tr>
<tr><td id="answers"></td></tr>
<tr><td><input type="submit" value="Vytvořit"></td></tr>
</table>
</form>
EOT;
if ($createJS) {
$return .= <<<EOT
<script type="text/javascript">
var numAnswers = 0;
function addAnswer()
{
numAnswers++;
var row = document.getElementById("answers");
var inputAnswer = document.createElement("input");
inputAnswer.type = "text";
inputAnswer.name = "answers[]";
inputAnswer.size = 40;
inputAnswer.required = true;
var inputColor = document.createElement("input");
inputColor.type = "text";
inputColor.name = "colors[]";
inputColor.pattern = "^#[a-zA-Z0-9]{6}$";
inputColor.required = true;
inputColor.size = 7;
inputColor.maxLength = 7;
var answer = document.createElement("span");
answer.innerHTML += numAnswers + ". ";
answer.appendChild(inputAnswer);
answer.innerHTML += " Barva: ";
answer.appendChild(inputColor);
answer.innerHTML += "<br />";
row.appendChild(answer);
}
</script>
EOT;
}
return $return;
}
/**
* @param array
* @return array
*/
private function getAnswersPercentually($answers)
{
$return = array();
$numAnswered = 0;
foreach ($answers as $answer) {
$numAnswered += $answer["count"];
}
foreach ($answers as $answer) {
$percentual = 0;
if ($answer["count"] > 0) {
$percentual = $answer["count"] / $numAnswered * 100;
}
$return[$answer["id"]] = number_format($percentual, 2);
}
return $return;
}
/**
* @param array
* @param int
* @return float
*/
private function getAnswerPercentually($answers, $answerID)
{
foreach ($answers as $_answerID => $answer) {
if ($_answerID == $answerID) { // intentionally ==
return $answer;
}
}
}
/**
* @param int
* @return int
*/
public function getPollIdByAnswer($id)
{
$query = $this->db->prepare("
SELECT `poll_id` FROM `poll_answer`
WHERE `id` = ?
LIMIT 1
");
$query->execute(array($id));
return (int) $query->fetchColumn();
}
/**
* @param int
* @throws PollException
*/
public function vote($answerID)
{
if ($this->userAlreadyVoted($answerID)) {
throw new PollException("V této anketě jste již hlasoval.");
}
$query = $this->db->prepare("
UPDATE `poll_answer`
SET `count` = `count` + 1
WHERE `id` = ?
");
$query->execute(array($answerID));
if ($query->rowCount() === 0) {
throw new PollException("Nebylo možné odeslat hlas.");
}
$cookieName = self::COOKIE_VOTE . "_" . $answerID;
setCookie($cookieName, 1, time() + 60 * 60 * 24 * 30 * 10);
}
/**
* @param int
* @return bool
*/
private function userAlreadyVoted($answerID)
{
$cookieName = self::COOKIE_VOTE . "_" . $answerID;
if (isset($_COOKIE[$cookieName])) {
return TRUE;
}
return FALSE;
}
/**
* @return string
* @throws PollException
*/
public function __toString()
{
if ($this->exists) {
$return = '
<div class="poll" id="poll_' . $this->data["id"] . '">
<div class="question">
' . $this->data["question"] . '
</div>
<div class="answers">
';
$answers = $this->data["answers"];
$percentualAnswers = $this->getAnswersPercentually($answers, $this->data["answers"]);
$userVoted = FALSE;
$voteMessage = "";
foreach ($answers as $answer) {
if ($this->userAlreadyVoted($answer["id"])) {
$userVoted = TRUE;
}
if (isset($_SESSION["poll_answer_" . $answer["id"]])) {
$voteMessage = "<br /><br />" . $_SESSION["poll_answer_" . $answer["id"]];
unset($_SESSION["poll_answer_" . $answer["id"]]);
}
}
$return .= '<table class="answers">';
foreach ($answers as $answer) {
$percent = $this->getAnswerPercentually($percentualAnswers, $answer["id"]);
$answerText = $answer["answer"];
if (!$userVoted) {
$answerText = '<a href="?vote&id=' . $answer["id"] . '">' . $answer["answer"] . '</a>';
}
$return .= '
<tr><td>' . $answerText . '</td><td></td></tr>
<tr>
<td style="width:200px;border:1px solid #000;">
<div style="background-color:' . $answer["color"] . ';width:' . $percent . '%;height:20px;"></div>
</td>
<td class="votes">' . $percent . '% (' . $answer["count"] . ')
</td>
</tr>
';
}
$return .= "
</table>
</div>
" . $voteMessage . "
</div>
";
return $return;
}
return "";
}
}
Neformátovaný
Přidáno: 7.8.2013
Expirace: Neuvedeno