1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-06-16 23:00:51 +03:00

Доработка опросов

This commit is contained in:
Mzhelskiy Maxim 2014-02-05 20:06:04 +07:00
parent 7c53f8e62e
commit 0f90d0c726
15 changed files with 305 additions and 427 deletions

View file

@ -50,7 +50,6 @@ class ActionAjax extends Action {
$this->AddEventPreg('/^vote$/i','/^topic$/','EventVoteTopic');
$this->AddEventPreg('/^vote$/i','/^blog$/','EventVoteBlog');
$this->AddEventPreg('/^vote$/i','/^user$/','EventVoteUser');
$this->AddEventPreg('/^vote$/i','/^question$/','EventVoteQuestion');
$this->AddEventPreg('/^vote$/i','/^get$/','/^info$/','/^topic$/','EventVoteGetInfoTopic');
$this->AddEventPreg('/^favourite$/i','/^save-tags/','EventFavouriteSaveTags');
@ -96,6 +95,7 @@ class ActionAjax extends Action {
$this->AddEventPreg('/^poll$/i','/^create$/','/^$/','EventPollCreate');
$this->AddEventPreg('/^poll$/i','/^update$/','/^$/','EventPollUpdate');
$this->AddEventPreg('/^poll$/i','/^remove$/','/^$/','EventPollRemove');
$this->AddEventPreg('/^poll$/i','/^vote$/','/^$/','EventPollVote');
}
@ -104,9 +104,76 @@ class ActionAjax extends Action {
**********************************************************************************
*/
protected function EventPollVote() {
if (!$this->oUserCurrent) {
return $this->EventErrorDebug();
}
if (!$oPoll=$this->Poll_GetPollById(getRequestStr('id'))) {
return $this->EventErrorDebug();
}
/**
* Истекло время голосования?
*/
if (!$oPoll->isAllowVote()) {
$this->Message_AddErrorSingle('В этом опросе уже нельзя голосовать');
return;
}
/**
* Пользователь уже голосовал?
*/
if ($this->Poll_GetVoteByUserIdAndPollId($this->oUserCurrent->getId(),$oPoll->getId())) {
$this->Message_AddErrorSingle('Вы уже голосовали');
return;
}
$aAnswerIds=array();
$aAnswerItems=array();
if (!getRequest('abstain')) {
/**
* Проверяем варианты ответов
*/
if (!$aAnswer=(array)getRequest('answers')) {
$this->Message_AddErrorSingle('Необходимо выбрать вариант');
return;
}
foreach($aAnswer as $iAnswerId) {
if (!is_numeric($iAnswerId)) {
return $this->EventErrorDebug();
}
$aAnswerIds[]=$iAnswerId;
}
/**
* Корректность ID вариантов
*/
$aAnswerItems=$this->Poll_GetAnswerItemsByFilter(array('id in'=>$aAnswerIds,'poll_id'=>$oPoll->getId()));
if (count($aAnswerItems)!=count($aAnswerIds)) {
return $this->EventErrorDebug();
}
}
/**
* Голосуем
*/
$oVote=Engine::GetEntity('ModulePoll_EntityVote');
$oVote->setPollId($oPoll->getId());
$oVote->setPoll($oPoll); // для быстродействия/оптимизации
$oVote->setUserId($this->oUserCurrent->getId());
$oVote->setAnswers($aAnswerIds);
$oVote->setAnswersObject($aAnswerItems); // передаем для быстродействия, чтобы не запрашивать варианты еще раз после сохранения голоса
if ($oVote->Add()) {
$oViewer=$this->Viewer_GetLocalViewer();
$oViewer->Assign('oPoll',$oPoll);
$this->Viewer_AssignAjax('sText',$oViewer->Fetch("polls/poll.result.tpl"));
} else {
return $this->EventErrorDebug();
}
}
protected function EventPollCreate() {
if (!$this->oUserCurrent) {
return parent::EventNotFound();
return $this->EventErrorDebug();
}
/**
* Создаем
@ -134,7 +201,7 @@ class ActionAjax extends Action {
protected function EventPollUpdate() {
if (!$this->oUserCurrent) {
return parent::EventNotFound();
return $this->EventErrorDebug();
}
if (!$oPoll=$this->Poll_GetPollById(getRequestStr('poll_id'))) {
@ -178,7 +245,7 @@ class ActionAjax extends Action {
protected function EventPollRemove() {
if (!$this->oUserCurrent) {
return parent::EventNotFound();
return $this->EventErrorDebug();
}
if (!$oPoll=$this->Poll_GetPollById(getRequestStr('id'))) {
@ -988,73 +1055,6 @@ class ActionAjax extends Action {
return;
}
}
/**
* Голосование за вариант ответа в опросе
*
*/
protected function EventVoteQuestion() {
/**
* Пользователь авторизован?
*/
if (!$this->oUserCurrent) {
$this->Message_AddErrorSingle($this->Lang_Get('need_authorization'),$this->Lang_Get('error'));
return;
}
/**
* Параметры голосования
*/
$idAnswer=getRequestStr('idAnswer',null,'post');
$idTopic=getRequestStr('idTopic',null,'post');
/**
* Топик существует?
*/
if (!($oTopic=$this->Topic_GetTopicById($idTopic))) {
return $this->EventErrorDebug();
}
/**
* Тип топика - опрос?
*/
if ($oTopic->getType()!='question') {
return $this->EventErrorDebug();
}
/**
* Уже голосовал?
*/
if ($oTopicQuestionVote=$this->Topic_GetTopicQuestionVote($oTopic->getId(),$this->oUserCurrent->getId())) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_question_vote_already'),$this->Lang_Get('error'));
return;
}
/**
* Вариант ответа
*/
$aAnswer=$oTopic->getQuestionAnswers();
if (!isset($aAnswer[$idAnswer]) and $idAnswer!=-1) {
return $this->EventErrorDebug();
}
if ($idAnswer==-1) {
$oTopic->setQuestionCountVoteAbstain($oTopic->getQuestionCountVoteAbstain()+1);
} else {
$oTopic->increaseQuestionAnswerVote($idAnswer);
}
$oTopic->setQuestionCountVote($oTopic->getQuestionCountVote()+1);
/**
* Голосуем(отвечаем на опрос)
*/
$oTopicQuestionVote=Engine::GetEntity('Topic_TopicQuestionVote');
$oTopicQuestionVote->setTopicId($oTopic->getId());
$oTopicQuestionVote->setVoterId($this->oUserCurrent->getId());
$oTopicQuestionVote->setAnswer($idAnswer);
if ($this->Topic_AddTopicQuestionVote($oTopicQuestionVote) and $this->Topic_updateTopic($oTopic)) {
$this->Message_AddNoticeSingle($this->Lang_Get('topic_question_vote_ok'),$this->Lang_Get('attention'));
$oViewer=$this->Viewer_GetLocalViewer();
$oViewer->Assign('oTopic',$oTopic);
$this->Viewer_AssignAjax('sText',$oViewer->Fetch("topics/poll_result.tpl"));
} else {
return $this->EventErrorDebug();
}
}
/**
* Сохраняет теги для избранного
*

View file

@ -100,7 +100,6 @@ class ModulePoll extends ModuleORM {
}
return false;
}
/**
* Заменяет временный идентификатор на необходимый ID объекта
*
@ -123,6 +122,29 @@ class ModulePoll extends ModuleORM {
}
}
}
/**
* Возвращает список опросов для объекта
*
* @param string $sTargetType
* @param string $sTargetId
*
* @return mixed
*/
public function GetPollItemsByTarget($sTargetType,$sTargetId) {
$aFilter=array(
'target_type'=>$sTargetType,
'target_id'=>$sTargetId,
'#with'=>array('answers')
);
if ($this->oUserCurrent) {
$aFilter['#with']['vote_current']=array('user_id'=>$this->oUserCurrent->getId(),'#value-default'=>false);
} else {
$aFilter['#with']['vote_current']=array('#value-set'=>false);
}
$aPollItems=$this->Poll_GetPollItemsByFilter($aFilter);
return $aPollItems;
}

View file

@ -32,6 +32,7 @@ class ModulePoll_EntityPoll extends EntityORM {
protected $aRelations=array(
'answers' => array(self::RELATION_TYPE_HAS_MANY,'ModulePoll_EntityAnswer','poll_id'),
'vote_current' => array(self::RELATION_TYPE_HAS_ONE,'ModulePoll_EntityVote','poll_id'),
);
protected function beforeSave() {
@ -199,4 +200,38 @@ class ModulePoll_EntityPoll extends EntityORM {
}
return true;
}
/**
* Проверяет возможность голосования в опросе, не пользователем, а в принципе
* Важно понимать, что здесь нет проверки на права доступа
*
* @return bool
*/
public function isAllowVote() {
$sDateEnd=$this->getDateEnd();
if ($sDateEnd and (time()-strtotime($sDateEnd))>0) {
return false;
}
return true;
}
public function getAnswerPercent($oAnswer) {
$iCountAll=$this->getCountVote();
if ($iCountAll==0) {
return 0;
} else {
return number_format(round($oAnswer->getCountVote()*100/$iCountAll,1), 1, '.', '');
}
}
public function getCountVoteAnswerMax() {
$iMax=0;
$aAnswers=$this->getAnswers();
foreach($aAnswers as $oAnswer) {
if ($oAnswer->getCountVote()>$iMax) {
$iMax=$oAnswer->getCountVote();
}
}
return $iMax;
}
}

View file

@ -26,7 +26,7 @@ class ModulePoll_EntityVote extends EntityORM {
);
protected $aRelations=array(
'poll' => array(self::RELATION_TYPE_BELONGS_TO,'ModulePoll_EntityPoll','poll_id'),
);
protected function beforeSave() {
@ -36,4 +36,44 @@ class ModulePoll_EntityVote extends EntityORM {
return true;
}
protected function afterSave() {
if ($this->_isNew()) {
/**
* Отмечаем факт голосования в опросе и вариантах
*/
$oPoll=$this->getPoll();
$aAnswerItems=$this->getAnswersObject();
if ($aAnswerItems) {
foreach($aAnswerItems as $oAnswer) {
$oAnswer->setCountVote($oAnswer->getCountVote()+1);
$oAnswer->Update();
}
$oPoll->setCountVote($oPoll->getCountVote()+1);
} else {
$oPoll->setCountAbstain($oPoll->getCountAbstain()+1);
}
$oPoll->Update(0);
}
}
/**
* Возвращает список вариантов, за которые голосовали
*
* @return array|mixed
*/
public function getAnswers() {
$aData=@unserialize($this->_getDataOne('answers'));
if (!$aData) {
$aData=array();
}
return $aData;
}
/**
* Устанавливает список вариантов, за которые голосовали
*
* @param $aParams
*/
public function setAnswers($aParams) {
$this->_aData['answers']=@serialize($aParams);
}
}

View file

@ -336,11 +336,32 @@ class ModuleProperty extends ModuleORM {
/**
* Переопределяем метод для возможности цеплять свои кастомные данные при ORM запросах - свойства
*
* @param array $aEntitiesWork
* @param array $aResult
* @param array $aFilter
* @param null|string $sEntityFull
*/
public function RewriteGetItemsByFilter($aEntitiesWork,$aFilter=array(),$sEntityFull=null) {
public function RewriteGetItemsByFilter($aResult,$aFilter=array(),$sEntityFull=null) {
if (!$aResult) {
return;
}
/**
* Список на входе может быть двух видом:
* 1 - одномерный массив
* 2 - двумерный, если применялась группировка (использование '#index-group')
*
* Поэтому сначала сформируем линейный список
*/
if (isset($aFilter['#index-group']) and $aFilter['#index-group']) {
$aEntitiesWork=array();
foreach($aResult as $aItems) {
foreach($aItems as $oItem) {
$aEntitiesWork[]=$oItem;
}
}
} else {
$aEntitiesWork=$aResult;
}
if (!$aEntitiesWork) {
return;
}

View file

@ -114,7 +114,6 @@ class ModuleTopic extends Module {
*/
$aUserId=array();
$aBlogId=array();
$aTopicIdQuestion=array();
foreach ($aTopics as $oTopic) {
if (isset($aAllowData['user'])) {
$aUserId[]=$oTopic->getUserId();
@ -122,22 +121,17 @@ class ModuleTopic extends Module {
if (isset($aAllowData['blog'])) {
$aBlogId[]=$oTopic->getBlogId();
}
if ($oTopic->getType()=='question') {
$aTopicIdQuestion[]=$oTopic->getId();
}
}
/**
* Получаем дополнительные данные
*/
$aTopicsVote=array();
$aFavouriteTopics=array();
$aTopicsQuestionVote=array();
$aTopicsRead=array();
$aUsers=isset($aAllowData['user']) && is_array($aAllowData['user']) ? $this->User_GetUsersAdditionalData($aUserId,$aAllowData['user']) : $this->User_GetUsersAdditionalData($aUserId);
$aBlogs=isset($aAllowData['blog']) && is_array($aAllowData['blog']) ? $this->Blog_GetBlogsAdditionalData($aBlogId,$aAllowData['blog']) : $this->Blog_GetBlogsAdditionalData($aBlogId);
if (isset($aAllowData['vote']) and $this->oUserCurrent) {
$aTopicsVote=$this->Vote_GetVoteByArray($aTopicId,'topic',$this->oUserCurrent->getId());
$aTopicsQuestionVote=$this->GetTopicsQuestionVoteByArray($aTopicIdQuestion,$this->oUserCurrent->getId());
}
if (isset($aAllowData['favourite']) and $this->oUserCurrent) {
$aFavouriteTopics=$this->GetFavouriteTopicsByArray($aTopicId,$this->oUserCurrent->getId());
@ -169,11 +163,6 @@ class ModuleTopic extends Module {
} else {
$oTopic->setFavourite(null);
}
if (isset($aTopicsQuestionVote[$oTopic->getId()])) {
$oTopic->setUserQuestionIsVote(true);
} else {
$oTopic->setUserQuestionIsVote(false);
}
if (isset($aTopicsRead[$oTopic->getId()])) {
$oTopic->setCountCommentNew($oTopic->getCountComment()-$aTopicsRead[$oTopic->getId()]->getCommentCountLast());
$oTopic->setDateRead($aTopicsRead[$oTopic->getId()]->getDateRead());
@ -1365,121 +1354,6 @@ class ModuleTopic extends Module {
}
return $data;
}
/**
* Проверяет голосовал ли юзер за топик-вопрос
*
* @param int $sTopicId ID топика
* @param int $sUserId ID пользователя
* @return ModuleTopic_EntityTopicQuestionVote|null
*/
public function GetTopicQuestionVote($sTopicId,$sUserId) {
$data=$this->GetTopicsQuestionVoteByArray($sTopicId,$sUserId);
if (isset($data[$sTopicId])) {
return $data[$sTopicId];
}
return null;
}
/**
* Получить список голосований в топике-опросе по списку айдишников
*
* @param array $aTopicId Список ID топиков
* @param int $sUserId ID пользователя
* @return array
*/
public function GetTopicsQuestionVoteByArray($aTopicId,$sUserId) {
if (!$aTopicId) {
return array();
}
if (Config::Get('sys.cache.solid')) {
return $this->GetTopicsQuestionVoteByArraySolid($aTopicId,$sUserId);
}
if (!is_array($aTopicId)) {
$aTopicId=array($aTopicId);
}
$aTopicId=array_unique($aTopicId);
$aTopicsQuestionVote=array();
$aTopicIdNotNeedQuery=array();
/**
* Делаем мульти-запрос к кешу
*/
$aCacheKeys=func_build_cache_keys($aTopicId,'topic_question_vote_','_'.$sUserId);
if (false !== ($data = $this->Cache_Get($aCacheKeys))) {
/**
* проверяем что досталось из кеша
*/
foreach ($aCacheKeys as $sValue => $sKey ) {
if (array_key_exists($sKey,$data)) {
if ($data[$sKey]) {
$aTopicsQuestionVote[$data[$sKey]->getTopicId()]=$data[$sKey];
} else {
$aTopicIdNotNeedQuery[]=$sValue;
}
}
}
}
/**
* Смотрим каких топиков не было в кеше и делаем запрос в БД
*/
$aTopicIdNeedQuery=array_diff($aTopicId,array_keys($aTopicsQuestionVote));
$aTopicIdNeedQuery=array_diff($aTopicIdNeedQuery,$aTopicIdNotNeedQuery);
$aTopicIdNeedStore=$aTopicIdNeedQuery;
if ($data = $this->oMapperTopic->GetTopicsQuestionVoteByArray($aTopicIdNeedQuery,$sUserId)) {
foreach ($data as $oTopicVote) {
/**
* Добавляем к результату и сохраняем в кеш
*/
$aTopicsQuestionVote[$oTopicVote->getTopicId()]=$oTopicVote;
$this->Cache_Set($oTopicVote, "topic_question_vote_{$oTopicVote->getTopicId()}_{$oTopicVote->getVoterId()}", array(), 60*60*24*4);
$aTopicIdNeedStore=array_diff($aTopicIdNeedStore,array($oTopicVote->getTopicId()));
}
}
/**
* Сохраняем в кеш запросы не вернувшие результата
*/
foreach ($aTopicIdNeedStore as $sId) {
$this->Cache_Set(null, "topic_question_vote_{$sId}_{$sUserId}", array(), 60*60*24*4);
}
/**
* Сортируем результат согласно входящему массиву
*/
$aTopicsQuestionVote=func_array_sort_by_keys($aTopicsQuestionVote,$aTopicId);
return $aTopicsQuestionVote;
}
/**
* Получить список голосований в топике-опросе по списку айдишников, но используя единый кеш
*
* @param array $aTopicId Список ID топиков
* @param int $sUserId ID пользователя
* @return array
*/
public function GetTopicsQuestionVoteByArraySolid($aTopicId,$sUserId) {
if (!is_array($aTopicId)) {
$aTopicId=array($aTopicId);
}
$aTopicId=array_unique($aTopicId);
$aTopicsQuestionVote=array();
$s=join(',',$aTopicId);
if (false === ($data = $this->Cache_Get("topic_question_vote_{$sUserId}_id_{$s}"))) {
$data = $this->oMapperTopic->GetTopicsQuestionVoteByArray($aTopicId,$sUserId);
foreach ($data as $oTopicVote) {
$aTopicsQuestionVote[$oTopicVote->getTopicId()]=$oTopicVote;
}
$this->Cache_Set($aTopicsQuestionVote, "topic_question_vote_{$sUserId}_id_{$s}", array("topic_question_vote_user_{$sUserId}"), 60*60*24*1);
return $aTopicsQuestionVote;
}
return $data;
}
/**
* Добавляет факт голосования за топик-вопрос
*
* @param ModuleTopic_EntityTopicQuestionVote $oTopicQuestionVote Объект голосования в топике-опросе
* @return bool
*/
public function AddTopicQuestionVote(ModuleTopic_EntityTopicQuestionVote $oTopicQuestionVote) {
$this->Cache_Delete("topic_question_vote_{$oTopicQuestionVote->getTopicId()}_{$oTopicQuestionVote->getVoterId()}");
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,array("topic_question_vote_user_{$oTopicQuestionVote->getVoterId()}"));
return $this->oMapperTopic->AddTopicQuestionVote($oTopicQuestionVote);
}
/**
* Получает топик по уникальному хешу(текст топика)
*

View file

@ -383,14 +383,6 @@ class ModuleTopic_EntityTopic extends Entity {
public function getVote() {
return $this->_getDataOne('vote');
}
/**
* Возвращает статус голосовал ли пользователь в топике-опросе
*
* @return bool|null
*/
public function getUserQuestionIsVote() {
return $this->_getDataOne('user_question_is_vote');
}
/**
* Проверяет находится ли данный топик в избранном у текущего пользователя
*
@ -475,6 +467,18 @@ class ModuleTopic_EntityTopic extends Entity {
return $this->_getDataOne('type_object');
}
/**
* Возвращает список опросов, которые есть у топика
*
* @return array|null
*/
public function getPolls() {
if (!$this->_getDataOne('polls')) {
$this->_aData['polls']=$this->Poll_GetPollItemsByTarget('topic',$this->getId());
}
return $this->_getDataOne('polls');
}
/***************************************************************************************************************************************************
* методы расширения типов топика
***************************************************************************************************************************************************
@ -578,141 +582,6 @@ class ModuleTopic_EntityTopic extends Entity {
$this->setExtraValue('count_jump',$data);
}
/**
* Добавляет вариант ответа в топик-опрос
*
* @param string $data
*/
public function addQuestionAnswer($data) {
if ($this->getType()!='question') {
return;
}
$this->extractExtra();
$this->aExtra['answers'][]=array('text'=>$data,'count'=>0);
$this->setExtra($this->aExtra);
}
/**
* Очищает варианты ответа в топике-опрос
*/
public function clearQuestionAnswer() {
if ($this->getType()!='question') {
return;
}
$this->setExtraValue('answers',array());
}
/**
* Возвращает варианты ответа в топике-опрос
*
* @param bool $bSortVote
* @return array|null
*/
public function getQuestionAnswers($bSortVote=false) {
if ($this->getType()!='question') {
return null;
}
if ($this->getExtraValue('answers')) {
$aAnswers=$this->getExtraValue('answers');
if ($bSortVote) {
uasort($aAnswers, create_function('$a,$b',"if (\$a['count'] == \$b['count']) { return 0; } return (\$a['count'] < \$b['count']) ? 1 : -1;"));
}
return $aAnswers;
}
return array();
}
/**
* Увеличивает количество ответов на данный вариант в топике-опросе
*
* @param int $sIdAnswer ID варианта ответа
*/
public function increaseQuestionAnswerVote($sIdAnswer) {
if ($aAnswers=$this->getQuestionAnswers()) {
if (isset($aAnswers[$sIdAnswer])) {
$aAnswers[$sIdAnswer]['count']++;
$this->aExtra['answers']=$aAnswers;
$this->setExtra($this->aExtra);
}
}
}
/**
* Возвращает максимально количество ответов на вариант в топике-опросе
*
* @return int
*/
public function getQuestionAnswerMax() {
$aAnswers=$this->getQuestionAnswers();
$iMax=0;
foreach ($aAnswers as $aAns) {
if ($aAns['count']>$iMax) {
$iMax=$aAns['count'];
}
}
return $iMax;
}
/**
* Возвращает в процентах количество проголосовавших за конкретный вариант
*
* @param int $sIdAnswer ID варианта
* @return int|string
*/
public function getQuestionAnswerPercent($sIdAnswer) {
if ($aAnswers=$this->getQuestionAnswers()) {
if (isset($aAnswers[$sIdAnswer])) {
$iCountAll=$this->getQuestionCountVote()-$this->getQuestionCountVoteAbstain();
if ($iCountAll==0) {
return 0;
} else {
return number_format(round($aAnswers[$sIdAnswer]['count']*100/$iCountAll,1), 1, '.', '');
}
}
}
}
/**
* Возвращает общее число принявших участие в опросе в топике-опросе
*
* @return int|null
*/
public function getQuestionCountVote() {
if ($this->getType()!='question') {
return null;
}
return (int)$this->getExtraValue('count_vote');
}
/**
* Устанавливает общее число принявших участие в опросе в топике-опросе
*
* @param int $data
*/
public function setQuestionCountVote($data) {
if ($this->getType()!='question') {
return;
}
$this->setExtraValue('count_vote',$data);
}
/**
* Возвращает число воздержавшихся от участия в опросе в топике-опросе
*
* @return int|null
*/
public function getQuestionCountVoteAbstain() {
if ($this->getType()!='question') {
return null;
}
return (int)$this->getExtraValue('count_vote_abstain');
}
/**
* Устанавливает число воздержавшихся от участия в опросе в топике-опросе
*
* @param int $data
* @return mixed
*/
public function setQuestionCountVoteAbstain($data) {
if ($this->getType()!='question') {
return;
}
$this->setExtraValue('count_vote_abstain',$data);
}
//*************************************************************************************************************************************************

View file

@ -692,55 +692,6 @@ class ModuleTopic_MapperTopic extends Mapper {
}
return $aReads;
}
/**
* Добавляет факт голосования за топик-вопрос
*
* @param ModuleTopic_EntityTopicQuestionVote $oTopicQuestionVote Объект голосования в топике-опросе
* @return bool
*/
public function AddTopicQuestionVote(ModuleTopic_EntityTopicQuestionVote $oTopicQuestionVote) {
$sql = "INSERT INTO ".Config::Get('db.table.topic_question_vote')."
(topic_id,
user_voter_id,
answer
)
VALUES(?d, ?d, ?f)
";
if ($this->oDb->query($sql,$oTopicQuestionVote->getTopicId(),$oTopicQuestionVote->getVoterId(),$oTopicQuestionVote->getAnswer())===0)
{
return true;
}
return false;
}
/**
* Получить список голосований в топике-опросе по списку айдишников
*
* @param array $aArrayId Список ID топиков
* @param int $sUserId ID пользователя
* @return array
*/
public function GetTopicsQuestionVoteByArray($aArrayId,$sUserId) {
if (!is_array($aArrayId) or count($aArrayId)==0) {
return array();
}
$sql = "SELECT
v.*
FROM
".Config::Get('db.table.topic_question_vote')." as v
WHERE
v.topic_id IN(?a)
AND
v.user_voter_id = ?d
";
$aVotes=array();
if ($aRows=$this->oDb->select($sql,$aArrayId,$sUserId)) {
foreach ($aRows as $aRow) {
$aVotes[]=Engine::GetEntity('Topic_TopicQuestionVote',$aRow);
}
}
return $aVotes;
}
/**
* Перемещает топики в другой блог
*

View file

@ -271,7 +271,6 @@ $config['db']['table']['talk_user'] = '___db.table.prefix___talk_user'
$config['db']['table']['talk_blacklist'] = '___db.table.prefix___talk_blacklist';
$config['db']['table']['friend'] = '___db.table.prefix___friend';
$config['db']['table']['topic_content'] = '___db.table.prefix___topic_content';
$config['db']['table']['topic_question_vote'] = '___db.table.prefix___topic_question_vote';
$config['db']['table']['user_administrator'] = '___db.table.prefix___user_administrator';
$config['db']['table']['comment_online'] = '___db.table.prefix___comment_online';
$config['db']['table']['invite'] = '___db.table.prefix___invite';
@ -307,6 +306,9 @@ $config['db']['table']['rbac_permission'] = '___db.table.prefix___rbac_permis
$config['db']['table']['rbac_role_permission']= '___db.table.prefix___rbac_role_permission';
$config['db']['table']['rbac_user_role'] = '___db.table.prefix___rbac_user_role';
$config['db']['table']['storage'] = '___db.table.prefix___storage';
$config['db']['table']['poll'] = '___db.table.prefix___poll';
$config['db']['table']['poll_answer'] = '___db.table.prefix___poll_answer';
$config['db']['table']['poll_vote'] = '___db.table.prefix___poll_vote';
$config['db']['tables']['engine'] = 'InnoDB'; // InnoDB или MyISAM

View file

@ -16,7 +16,7 @@ ls.poll = (function ($) {
*/
var defaults = {
// Роутер голосования
sRouterVoteUrl: aRouter['ajax'] + 'vote/question/',
sRouterVoteUrl: aRouter['ajax'] + 'poll/vote/',
// Максимальное кол-во вариантов ответов
iMaxItems: 20,
@ -31,8 +31,6 @@ ls.poll = (function ($) {
// Селекторы опроса
sPollSelector: '.js-poll',
sPollListSelector: '.js-poll-list',
sPollItemSelector: '.js-poll-item',
sPollItemOptionSelector: '.js-poll-item-option',
sPollButtonVoteSelector: '.js-poll-button-vote',
sPollButtonAbstainSelector: '.js-poll-button-abstain',
@ -64,28 +62,23 @@ ls.poll = (function ($) {
this.options = $.extend({}, defaults, options);
// Голосование
$(this.options.sPollSelector).each(function () {
var oPoll = $(this),
iPollId = oPoll.data('poll-id');
// Голосование за вариант
oPoll.find(self.options.sPollButtonVoteSelector).on('click', function () {
var iCheckedItemId = oPoll.find(self.options.sPollItemOptionSelector + ':checked').val();
var form = oPoll.find('form');
if (iCheckedItemId) {
self.vote(iPollId, iCheckedItemId);
} else {
return false;
}
self.vote(form,this);
});
// Воздержаться
oPoll.find(self.options.sPollButtonAbstainSelector).on('click', function () {
self.vote(iPollId, -1);
});
var form = oPoll.find('form');
// Воздержаться
self.vote(form,this,true);
});
// Сортировка
oPoll.on('click', self.options.sPollResultButtonSortSelector, function () {
self.toggleSort(oPoll);
});
@ -219,29 +212,21 @@ ls.poll = (function ($) {
/**
* Голосование в опросе
*
* @param {Number} iPollId ID опроса
* @param {Number} iItemId ID выбранного пункта
* @param {Object} form Форма с данными опроса
* @param {Object} button Копка для анимации загрузки
*/
this.vote = function(iPollId, iItemId) {
var oParams = {
idTopic: iPollId,
idAnswer: iItemId
};
this.vote = function(form,button,abstain) {
form=$(form);
var formData=form.serializeJSON();
ls.hook.marker('voteBefore');
ls.ajax.load(this.options.sRouterVoteUrl, oParams, function(result) {
if (result.bStateError) {
ls.msg.error(null, result.sMsg);
} else {
var oPoll = $('[data-poll-id=' + iPollId + ']');
oPoll.html(result.sText);
ls.ajax.submit(this.options.sRouterVoteUrl, form, function(result){
var oPoll = $('[data-poll-id=' + formData.id + ']');
oPoll.html(result.sText);
ls.msg.notice(null, result.sMsg);
ls.hook.run('ls_pool_vote_after', [iPollId, iItemId, result], oPoll);
}
});
ls.hook.run('ls_pool_vote_after', [form, result], oPoll);
}, { submitButton: $(button), params: { abstain: abstain ? 1 : 0 } });
};
/**

View file

@ -0,0 +1,32 @@
{foreach $aPollItems as $oPollItem}
<div class="poll poll-type-{$oPollItem->getTargetType()} js-poll" data-poll-id="{$oPollItem->getId()}" data-poll-answer-max="{$oPollItem->getCountAnswerMax()}">
{$oPollItem->getTitle()}
{if !$oPollItem->getVoteCurrent()}
<form action="" method="post" onsubmit="return false;">
<ul class="poll-list">
{foreach $oPollItem->getAnswers() as $oAnswer}
<li class="poll-item">
<label>
{if $oPollItem->getCountAnswerMax()>1}
<input type="checkbox" name="answers[]" value="{$oAnswer->getId()}" />
{else}
<input type="radio" name="answers[]" value="{$oAnswer->getId()}" />
{/if}
{$oAnswer->getTitle()}
</label>
</li>
{/foreach}
</ul>
<input type="hidden" name="id" value="{$oPollItem->getId()}">
<button type="submit" class="button button-primary js-poll-button-vote">Голосовать</button>
<button type="submit" class="button js-poll-button-abstain">Воздержаться</button>
</form>
{else}
{include file='polls/poll.result.tpl' oPoll=$oPollItem}
{/if}
</div>
{/foreach}

View file

@ -0,0 +1,35 @@
{**
* Результат опроса
*
* @styles assets/css/poll.css
* @scripts <framework>/js/livestreet/poll.js
*}
{$oPoll->getTitle()}
<ul class="poll-result js-poll-result">
{$aAnswerItems=$oPoll->getAnswers()}
{$iPollItemsCount = count($aAnswerItems)}
{foreach $aAnswerItems as $oAnswer}
<li class="poll-result-item {if $oPoll->getCountVoteAnswerMax() == $oAnswer->getCountVote()}poll-result-item-most{/if} js-poll-result-item"
data-poll-item-count="{$oAnswer->getCountVote()}"
data-poll-item-pos="{$iPollItemsCount - $oAnswer@index - 1}">
<div class="poll-result-item-count">
<strong>{$oPoll->getAnswerPercent($oAnswer)}%</strong>
<span>({$oAnswer->getCountVote()})</span>
</div>
<div class="poll-result-item-chart">
<div class="poll-result-item-label">{$oAnswer->getTitle()}</div>
<div class="poll-result-item-bar" style="width: {$oPoll->getAnswerPercent($oAnswer)}%;" ></div>
</div>
</li>
{/foreach}
</ul>
{* Кнопка сортировки *}
<button class="button button-icon js-poll-result-button-sort" title="Включить\выключить сортировку"><i class="icon-align-left"></i></button>
<span class="poll-result-total">Проголосовало: {$oPoll->getCountVote()} | Воздержалось: {$oPoll->getCountAbstain()}</span>

View file

@ -106,6 +106,13 @@
{/if}
{/block}
{* Опросы *}
{block name='topic_content_polls'}
{if ! $bTopicList}
{include file='polls/poll.list.tpl' aPollItems=$oTopic->getPolls()}
{/if}
{/block}
{hook run='topic_content_end' topic=$oTopic bTopicList=$bTopicList}
</div>
{/block}

@ -1 +1 @@
Subproject commit d4511e586d47416a1ba85222b5771d04fae7f629
Subproject commit 32fbce1287b2ea44617ccc4753b4e1bc1f82e742

View file

@ -478,3 +478,8 @@ ALTER TABLE `prefix_poll_vote`
ADD CONSTRAINT `prefix_poll_vote_ibfk_1` FOREIGN KEY (`poll_id`) REFERENCES `prefix_poll` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `prefix_poll_vote_ibfk_2` FOREIGN KEY (`answer_id`) REFERENCES `prefix_poll_answer` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- 05.02.2014
ALTER TABLE `prefix_poll_vote` DROP FOREIGN KEY `prefix_poll_vote_ibfk_2` ;
ALTER TABLE `prefix_poll_vote` DROP `answer_id` ;
ALTER TABLE `prefix_poll_vote` ADD `answers` VARCHAR( 500 ) NOT NULL AFTER `user_id` ;