Файл: library/XenForo/Model/Poll.php
Строк: 348
<?php
/**
* Model for polls.
*
* @package XenForo_Poll
*/
class XenForo_Model_Poll extends XenForo_Model
{
/**
* Gets the specified poll.
*
* @param integer $id
*
* @return array|false
*/
public function getPollById($id)
{
return $this->_getDb()->fetchRow('
SELECT *
FROM xf_poll
WHERE poll_id = ?
', $id);
}
/**
* Gets the specified poll by the content it belongs to.
*
* @param string $contentType
* @param integer $contentId
*
* @return array|false
*/
public function getPollByContent($contentType, $contentId)
{
return $this->_getDb()->fetchRow('
SELECT *
FROM xf_poll
WHERE content_type = ?
AND content_id = ?
', array($contentType, $contentId));
}
/**
* Gets poll IDs starting from after the specified start, up to the given limit
*
* @param integer $start
* @param integer $limit
*/
public function getPollIdsInRange($start, $limit)
{
$db = $this->_getDb();
return $db->fetchCol($db->limit('
SELECT poll_id
FROM xf_poll
WHERE poll_id > ?
ORDER BY poll_id
', $limit), $start);
}
/**
* Gets poll response.
*
* @param integer $id
*
* @return array|false
*/
public function getPollResponseById($id)
{
return $this->_getDb()->fetchRow('
SELECT *
FROM xf_poll_response
WHERE poll_response_id = ?
', $id);
}
/**
* Gets all poll responses that belong to the specified poll.
*
* @param $pollId
*
* @return array [poll response id] => info
*/
public function getPollResponsesInPoll($pollId)
{
return $this->fetchAllKeyed('
SELECT *
FROM xf_poll_response
WHERE poll_id = ?
ORDER BY poll_response_id
', 'poll_response_id', $pollId);
}
/**
* Gets poll response cache for use in the poll table.
*
* @param integer $pollId
*
* @return array [poll response id] => [response, response_vote_count, voters]
*/
public function getPollResponseCache($pollId)
{
$responses = $this->getPollResponsesInPoll($pollId);
$output = array();
foreach ($responses AS $response)
{
$output[$response['poll_response_id']] = array(
'response' => $response['response'],
'response_vote_count' => $response['response_vote_count'],
'voters' => unserialize($response['voters'])
);
}
return $output;
}
/**
* Rebuilds the poll response cache in the specified poll.
*
* @param integer $pollId
*
* @return array The response cache
*/
public function rebuildPollResponseCache($pollId)
{
$cache = $this->getPollResponseCache($pollId);
$db = $this->_getDb();
$db->update('xf_poll',
array('responses' => serialize($cache)),
'poll_id = ' . $db->quote($pollId)
);
return $cache;
}
/**
* Prepares the poll responses for viewing from the poll record's response cache.
*
* @param array|string $responses Serialized array or array itself
* @param array|null $viewingUser
*
* @return array|false Responses prepared; false if responses can't be prepared
*/
public function preparePollResponsesFromCache($responses, array $viewingUser = null)
{
$this->standardizeViewingUserReference($viewingUser);
if (!is_array($responses))
{
$responses = unserialize($responses);
}
if (!is_array($responses))
{
return false;
}
foreach ($responses AS &$response)
{
$response['response'] = XenForo_Helper_String::censorString($response['response']);
$response['hasVoted'] = isset($response['voters'][$viewingUser['user_id']]);
}
return $responses;
}
/**
* Prepares the poll for viewing.
*
* @param array $poll
* @param boolean $canVote If user can vote based on content-specified permissions
* @param array|null $viewingUser
*
* @return array
*/
public function preparePoll(array $poll, $canVote, array $viewingUser = null)
{
if (!is_array($poll['responses']))
{
$poll['responses'] = $this->preparePollResponsesFromCache($poll['responses'], $viewingUser);
}
if (!is_array($poll['responses']))
{
$poll['responses'] = $this->preparePollResponsesFromCache(
$this->rebuildPollResponseCache($poll['poll_id']),
$viewingUser
);
}
$poll['hasVoted'] = false;
foreach ($poll['responses'] AS $response)
{
if (!empty($response['hasVoted']))
{
$poll['hasVoted'] = true;
break;
}
}
$poll['open'] = (!$poll['close_date'] || $poll['close_date'] > XenForo_Application::$time);
if (!$canVote || $poll['hasVoted'] || !$poll['open'])
{
$poll['canVote'] = false;
}
else
{
$poll['canVote'] = true;
}
$poll['question'] = XenForo_Helper_String::censorString($poll['question']);
return $poll;
}
/**
* Determines if the viewing user can vote on the poll. This does not take into account
* content-specific permissions.
*
* @param array $poll
* @param string $errorPhraseKey
* @param array|null $viewingUser
*
* @return boolean
*/
public function canVoteOnPoll(array $poll, &$errorPhraseKey = '', array $viewingUser = null)
{
if ($poll['close_date'] && $poll['close_date'] < XenForo_Application::$time)
{
return false;
}
$this->standardizeViewingUserReference($viewingUser);
if (!$viewingUser['user_id'])
{
return false;
}
return ($this->hasVotedOnPoll($poll['poll_id'], $viewingUser['user_id']) ? false : true);
}
/**
* Returns true if the user has voted on this poll.
*
* @param integer $pollId
* @param integer $userId
*/
public function hasVotedOnPoll($pollId, $userId)
{
$voted = $this->_getDb()->fetchRow('
SELECT poll_response_id
FROM xf_poll_vote
WHERE poll_id = ?
AND user_id = ?
', array($pollId, $userId));
return ($voted ? true : false);
}
/**
* Votes on the specified poll.
*
* @param integer $pollId
* @param integer|array $votes One or more poll response IDs to vote on. This does not check if the poll allows multiple votes.
* @param integer|null $userId
* @param integer|null $voteDate
*
* @return boolean
*/
public function voteOnPoll($pollId, $votes, $userId = null, $voteDate = null)
{
if (!is_array($votes))
{
if (!$votes)
{
return false;
}
$votes = array($votes);
}
if (!$votes)
{
return false;
}
if ($userId === null)
{
$userId = XenForo_Visitor::getUserId();
}
if (!$userId)
{
return false;
}
if ($voteDate === null)
{
$voteDate = XenForo_Application::$time;
}
$responses = $this->getPollResponsesInPoll($pollId);
if ($this->hasVotedOnPoll($pollId, $userId))
{
return false;
}
$db = $this->_getDb();
XenForo_Db::beginTransaction($db);
$newVoter = true;
foreach ($votes AS $voteResponseId)
{
if (isset($responses[$voteResponseId]))
{
$res = $db->query('
INSERT IGNORE INTO xf_poll_vote
(user_id, poll_response_id, poll_id, vote_date)
VALUES
(?, ?, ?, ?)
', array($userId, $voteResponseId, $pollId, $voteDate));
if ($res->rowCount())
{
$voterCache = $this->getPollResponseVoterCache($voteResponseId);
$db->query('
UPDATE xf_poll_response SET
response_vote_count = response_vote_count + 1,
voters = ?
WHERE poll_response_id = ?
', array(serialize($voterCache), $voteResponseId));
}
else
{
$newVoter = false;
}
}
}
if ($newVoter)
{
$pollDw = XenForo_DataWriter::create('XenForo_DataWriter_Poll');
$pollDw->setExistingData($pollId);
$pollDw->set('voter_count', $pollDw->get('voter_count') + 1);
$pollDw->save();
}
XenForo_Db::commit($db);
return true;
}
public function getPollResponseVoterCache($pollResponseId)
{
return $this->fetchAllKeyed('
SELECT poll_vote.user_id, user.username
FROM xf_poll_vote AS poll_vote
LEFT JOIN xf_user AS user ON (poll_vote.user_id = user.user_id)
WHERE poll_vote.poll_response_id = ?
', 'user_id', $pollResponseId);
}
public function getPollVoterCount($pollId)
{
return $this->_getDb()->fetchOne('
SELECT COUNT(DISTINCT user_id)
FROM xf_poll_vote
WHERE poll_id = ?
', $pollId);
}
public function rebuildPollData($pollId)
{
$db = $this->_getDb();
$votes = array();
$voters = array();
$results = $db->query('
SELECT poll_vote.poll_response_id, poll_vote.user_id, user.username
FROM xf_poll_vote AS poll_vote
LEFT JOIN xf_user AS user ON (poll_vote.user_id = user.user_id)
WHERE poll_vote.poll_id = ?
', $pollId);
while ($vote = $results->fetch())
{
$votes[$vote['poll_response_id']][$vote['user_id']] = array(
'user_id' => $vote['user_id'],
'username' => $vote['username']
);
$voters[$vote['user_id']] = true;
}
$responses = $this->getPollResponsesInPoll($pollId);
XenForo_Db::beginTransaction($db);
foreach ($responses AS $responseId => $response)
{
if (!isset($votes[$responseId]))
{
$db->update('xf_poll_response', array(
'response_vote_count' => 0,
'voters' => ''
), 'poll_response_id = ' . $db->quote($responseId));
}
else
{
$db->update('xf_poll_response', array(
'response_vote_count' => count($votes[$responseId]),
'voters' => serialize($votes[$responseId])
), 'poll_response_id = ' . $db->quote($responseId));
}
}
$dw = XenForo_DataWriter::create('XenForo_DataWriter_Poll', XenForo_DataWriter::ERROR_SILENT);
if ($dw->setExistingData($pollId))
{
$dw->set('voter_count', count($voters));
$dw->set('responses', serialize($this->getPollResponseCache($pollId)));
$dw->save();
}
XenForo_Db::commit($db);
}
}