Add poll 9
Add form and vote handler.
This commit is contained in:
parent
c5e0be935f
commit
def812bf8c
8 changed files with 212 additions and 11 deletions
app
Controllers
Models
lang
templates/layouts
public/style/ForkBB
|
@ -384,6 +384,15 @@ class Routing
|
|||
}
|
||||
|
||||
}
|
||||
// опросы
|
||||
if ($user->usePoll) {
|
||||
$r->add(
|
||||
$r::PST,
|
||||
'/poll/{tid:[1-9]\d*}',
|
||||
'Poll:vote',
|
||||
'Poll'
|
||||
);
|
||||
}
|
||||
// админ и модератор
|
||||
if ($user->isAdmMod) {
|
||||
$r->add(
|
||||
|
|
|
@ -378,6 +378,7 @@ abstract class Page extends Model
|
|||
{
|
||||
$list = [
|
||||
302 => '302 Moved Temporarily',
|
||||
400 => '400 Bad Request',
|
||||
403 => '403 Forbidden',
|
||||
404 => '404 Not Found',
|
||||
405 => '405 Method Not Allowed',
|
||||
|
|
55
app/Models/Pages/Poll.php
Normal file
55
app/Models/Pages/Poll.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
use ForkBB\Models\Page;
|
||||
use ForkBB\Models\Topic\Model as Topic;
|
||||
use ForkBB\Models\Poll\Model as PollModel;
|
||||
use function \ForkBB\__;
|
||||
|
||||
class Poll extends Page
|
||||
{
|
||||
/**
|
||||
* Голосование
|
||||
*/
|
||||
public function vote(array $args, string $method): Page
|
||||
{
|
||||
$tid = (int) $args['tid'];
|
||||
$topic = $this->c->topics->load($tid);
|
||||
|
||||
if (
|
||||
! $topic instanceof Topic
|
||||
|| ! $topic->poll instanceof PollModel
|
||||
) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$this->c->Lang->load('poll');
|
||||
|
||||
$v = $this->c->Validator->reset()
|
||||
->addValidators([
|
||||
])->addRules([
|
||||
'token' => 'token:Poll',
|
||||
'poll_vote.*.*' => 'required|integer',
|
||||
'vote' => 'required|string',
|
||||
])->addAliases([
|
||||
])->addArguments([
|
||||
'token' => $args,
|
||||
])->addMessages([
|
||||
'poll_vote.*.*' => 'The poll structure is broken',
|
||||
]);
|
||||
|
||||
if (! $v->validation($_POST)) {
|
||||
$message = $this->c->Message;
|
||||
$message->fIswev = $v->getErrors();
|
||||
|
||||
return $message->message('', true, 400);
|
||||
} elseif (null !== ($result = $topic->poll->vote($v->poll_vote))) {
|
||||
return $this->c->Message->message($result, true, 400);
|
||||
} else {
|
||||
return $this->c->Redirect->url($topic->link)->message('You voted');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ use function \ForkBB\__;
|
|||
|
||||
class Model extends DataModel
|
||||
{
|
||||
const JSON_OPTIONS = \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR;
|
||||
|
||||
/**
|
||||
* Возвращает родительскую тему
|
||||
*/
|
||||
|
@ -50,6 +52,30 @@ class Model extends DataModel
|
|||
$this->tid = $topic->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ссылка на обработчик опроса
|
||||
*/
|
||||
protected function getlink(): ?string
|
||||
{
|
||||
if ($this->tid > 0) {
|
||||
return $this->c->Router->link('Poll', ['tid' => $this->tid]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Значение токена для формы голосования
|
||||
*/
|
||||
protected function gettoken(): ?string
|
||||
{
|
||||
if ($this->tid > 0) {
|
||||
return $this->c->Csrf->create('Poll', ['tid' => $this->tid]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Статус голосования для текущего пользователя
|
||||
*/
|
||||
|
@ -200,6 +226,9 @@ class Model extends DataModel
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает статус опроса для текущего пользователя или null
|
||||
*/
|
||||
protected function getstatus(): ?string
|
||||
{
|
||||
if ($this->tid < 1) {
|
||||
|
@ -219,4 +248,71 @@ class Model extends DataModel
|
|||
return __('Poll status is undefined');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Голосование
|
||||
* Возвращает текст ошибки или null
|
||||
*/
|
||||
public function vote(array $vote): ?string
|
||||
{
|
||||
if (! $this->canVote) {
|
||||
return __('You cannot vote on this poll');
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (\array_keys($this->question) as $q) {
|
||||
if ($this->type[$q] > 1) {
|
||||
$count = \count($vote[$q]);
|
||||
if (0 == $count) {
|
||||
return __('No vote on question %s', $q);
|
||||
} elseif ($count > $this->type[$q]) {
|
||||
return __('Too many answers selected in question %s', $q);
|
||||
}
|
||||
|
||||
foreach (\array_keys($vote[$q]) as $a) {
|
||||
if (! isset($this->answer[$q][$a])) {
|
||||
return __('The selected answer is not present in question %s', $q);
|
||||
}
|
||||
|
||||
$data[] = [$q, $a];
|
||||
}
|
||||
} else {
|
||||
if (! isset($vote[$q][0])) {
|
||||
return __('No vote on question %s', $q);
|
||||
} elseif (! isset($this->answer[$q][$vote[$q][0]])) {
|
||||
return __('The selected answer is not present in question %s', $q);
|
||||
}
|
||||
|
||||
$data[] = [$q, $vote[$q][0]];
|
||||
}
|
||||
|
||||
$data[] = [$q, 0];
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':tid' => $this->tid,
|
||||
':uid' => $this->c->user->id,
|
||||
':rez' => \json_encode($data, self::JSON_OPTIONS),
|
||||
];
|
||||
$query = 'INSERT INTO ::poll_voted (tid, uid, rez)
|
||||
VALUES (?i:tid, ?i:uid, ?s:rez)';
|
||||
|
||||
$this->c->DB->exec($query, $vars);
|
||||
|
||||
$vars = [
|
||||
':tid' => $this->tid,
|
||||
];
|
||||
$query = 'UPDATE ::poll
|
||||
SET votes=votes+1
|
||||
WHERE tid=?i:tid AND question_id=?i:qid AND field_id=?i:fid';
|
||||
|
||||
foreach ($data as list($vars[':qid'], $vars[':fid'])) {
|
||||
$this->c->DB->exec($query, $vars);
|
||||
}
|
||||
|
||||
$this->c->polls->reset($this->tid);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,16 +73,31 @@ msgid "(%1$s [%2$s%%])"
|
|||
msgstr "(%1$s [%2$s%%])"
|
||||
|
||||
msgid "Poll results are hidden from the guests"
|
||||
msgstr "Poll results are hidden from the guests"
|
||||
msgstr "Poll results are hidden from the guests."
|
||||
|
||||
msgid "This poll is closed"
|
||||
msgstr "This poll is closed"
|
||||
msgstr "This poll is closed."
|
||||
|
||||
msgid "Poll results are hidden up to %s voters"
|
||||
msgstr "Poll results are hidden up to %s voters"
|
||||
msgstr "Poll results are hidden up to %s voters."
|
||||
|
||||
msgid "You voted"
|
||||
msgstr "You voted"
|
||||
msgstr "You voted."
|
||||
|
||||
msgid "Poll status is undefined"
|
||||
msgstr "Статус опроса неопределен"
|
||||
msgstr "Poll status is undefined."
|
||||
|
||||
msgid "Vote"
|
||||
msgstr "Vote"
|
||||
|
||||
msgid "You cannot vote on this poll"
|
||||
msgstr "You cannot vote on this poll."
|
||||
|
||||
msgid "No vote on question %s"
|
||||
msgstr "No vote on question number %s."
|
||||
|
||||
msgid "The selected answer is not present in question %s"
|
||||
msgstr "The selected answer is not present in question number %s."
|
||||
|
||||
msgid "Too many answers selected in question %s"
|
||||
msgstr "Too many answers selected in question number %s."
|
||||
|
|
|
@ -73,16 +73,31 @@ msgid "(%1$s [%2$s%%])"
|
|||
msgstr "(%1$s [%2$s%%])"
|
||||
|
||||
msgid "Poll results are hidden from the guests"
|
||||
msgstr "Результаты опроса скрыты от гостей"
|
||||
msgstr "Результаты опроса скрыты от гостей."
|
||||
|
||||
msgid "This poll is closed"
|
||||
msgstr "Опрос закрыт"
|
||||
msgstr "Опрос закрыт."
|
||||
|
||||
msgid "Poll results are hidden up to %s voters"
|
||||
msgstr "Результаты опроса скрыты до %s проголосовавших"
|
||||
msgstr "Результаты опроса скрыты до %s проголосовавших."
|
||||
|
||||
msgid "You voted"
|
||||
msgstr "Вы проголосовали"
|
||||
msgstr "Вы проголосовали."
|
||||
|
||||
msgid "Poll status is undefined"
|
||||
msgstr "Статус опроса неопределен"
|
||||
msgstr "Статус опроса неопределен."
|
||||
|
||||
msgid "Vote"
|
||||
msgstr "Голосовать"
|
||||
|
||||
msgid "You cannot vote on this poll"
|
||||
msgstr "Вы не можете проголосовать в этом опросе."
|
||||
|
||||
msgid "No vote on question %s"
|
||||
msgstr "Отсутствует голос по %s вопросу."
|
||||
|
||||
msgid "The selected answer is not present in question %s"
|
||||
msgstr "Выбранный вариант ответа отсутствует в вопросе номер %s."
|
||||
|
||||
msgid "Too many answers selected in question %s"
|
||||
msgstr "В вопросе номер %s выбрано много ответов."
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<div class="f-post-poll">
|
||||
@if ($poll->canVote)
|
||||
<form>
|
||||
<form class="f-form" method="post" action="{!! $poll->link !!}">
|
||||
<input type="hidden" name="token" value="{{ $poll->token }}">
|
||||
@endif
|
||||
@foreach ($poll->question as $q => $question)
|
||||
<fieldset id="id-question-{!! $q !!}" class="f-poll-q">
|
||||
|
@ -37,6 +38,9 @@
|
|||
</fieldset>
|
||||
@endforeach
|
||||
@if ($poll->canVote)
|
||||
<p class="f-poll-btns">
|
||||
<button class="f-btn" name="vote" value="{!! __('Vote') !!}" title="{!! __('Vote') !!}"><span>{!! __('Vote') !!}</span></button>
|
||||
</p>
|
||||
</form>
|
||||
@else
|
||||
@if (null !== $poll->status)
|
||||
|
|
|
@ -2014,6 +2014,12 @@ body,
|
|||
padding-top: 0.625rem;
|
||||
}
|
||||
|
||||
#fork .f-poll-btns {
|
||||
text-align: center;
|
||||
border-top: 0.0625rem solid #AA7939;
|
||||
padding-top: 0.625rem;
|
||||
}
|
||||
|
||||
/**********/
|
||||
/* Репорт */
|
||||
/**********/
|
||||
|
|
Loading…
Add table
Reference in a new issue