View source
<?php
namespace Drupal\poll\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Form\BaseFormIdInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\poll\PollInterface;
use Symfony\Component\HttpFoundation\Request;
class PollViewForm extends FormBase implements BaseFormIdInterface {
protected $poll;
public function getBaseFormId() {
return 'poll_view_form';
}
public function getFormId() {
return 'poll_view_form_' . $this->poll
->id();
}
public function setPoll(PollInterface $poll) {
$this->poll = $poll;
}
public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL, $view_mode = 'full') {
$form['poll']['#type'] = 'value';
$form['poll']['#value'] = $this->poll;
$form['#view_mode'] = $view_mode;
if ($this
->showResults($this->poll, $form_state)) {
if ($request
->isMethod('POST') && $this->poll
->hasUserVoted()) {
$input = $form_state
->getUserInput();
if (isset($input['op']) && $input['op'] == $this
->t('Vote')) {
$this
->messenger()
->addError($this
->t('Your vote for this poll has already been submitted.'));
$_SESSION['poll_vote'][$this->poll
->id()] = FALSE;
}
}
$form['results'] = $this
->showPollResults($this->poll, $view_mode);
if ($view_mode != 'full' && $view_mode != 'block') {
$form['results']['#show_question'] = TRUE;
}
}
else {
$options = $this->poll
->getOptions();
if ($options) {
$form['choice'] = array(
'#type' => 'radios',
'#title' => t('Choices'),
'#title_display' => 'invisible',
'#options' => $options,
);
}
$form['#theme'] = 'poll_vote';
$form['#entity'] = $this->poll;
$form['#action'] = $this->poll
->toUrl()
->setOption('query', \Drupal::destination()
->getAsArray())
->toString();
$form_state
->set('show_results', FALSE);
if ($view_mode != 'full' && $view_mode != 'block') {
$form['#show_question'] = TRUE;
}
}
$form['actions'] = $this
->actions($form, $form_state, $this->poll);
$form['#cache'] = array(
'tags' => $this->poll
->getCacheTags(),
);
return $form;
}
public function ajaxReplaceForm(array $form, FormStateInterface $form_state) {
$form = [
'messages' => [
'#type' => 'status_messages',
],
] + $form;
$renderer = \Drupal::service('renderer');
$output = $renderer
->renderRoot($form);
$response = new AjaxResponse();
$response
->setAttachments($form['#attached']);
return $response
->addCommand(new ReplaceCommand('.poll-view-form-' . $this->poll
->id(), $output));
}
public function submitForm(array &$form, FormStateInterface $form_state) {
}
public function showResults(PollInterface $poll, FormStateInterface $form_state) {
$account = $this
->currentUser();
switch (TRUE) {
case $form_state
->get('show_results'):
return TRUE;
case $poll
->isClosed():
return TRUE;
case $account
->isAnonymous() && !$poll
->getAnonymousVoteAllow():
return TRUE;
case $poll
->hasUserVoted():
return TRUE;
default:
return FALSE;
}
}
protected function actions(array $form, FormStateInterface $form_state, $poll) {
$actions = [];
$ajax = [
'callback' => '::ajaxReplaceForm',
'url' => $this->poll
->toUrl(),
'options' => [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
'view_mode' => $form['#view_mode'],
],
],
];
if ($this
->showResults($poll, $form_state)) {
if ($this
->isCancelAllowed($poll)) {
$actions['#type'] = 'actions';
$actions['cancel']['#type'] = 'submit';
$actions['cancel']['#button_type'] = 'primary';
$actions['cancel']['#value'] = t('Cancel vote');
$actions['cancel']['#submit'] = array(
'::cancel',
);
$actions['cancel']['#ajax'] = $ajax;
$actions['cancel']['#weight'] = '0';
}
if (!$poll
->hasUserVoted() && $poll
->isOpen() && $poll
->getAnonymousVoteAllow()) {
$actions['#type'] = 'actions';
$actions['back']['#type'] = 'submit';
$actions['back']['#button_type'] = 'primary';
$actions['back']['#value'] = t('View poll');
$actions['back']['#submit'] = array(
'::back',
);
$actions['back']['#ajax'] = $ajax;
$actions['back']['#weight'] = '0';
}
}
else {
$actions['#type'] = 'actions';
$actions['vote']['#type'] = 'submit';
$actions['vote']['#button_type'] = 'primary';
$actions['vote']['#value'] = t('Vote');
$actions['vote']['#validate'] = array(
'::validateVote',
);
$actions['vote']['#submit'] = array(
'::save',
);
$actions['vote']['#ajax'] = $ajax;
$actions['vote']['#weight'] = '0';
if ($poll->result_vote_allow->value || $this
->currentUser()
->hasPermission('view poll results')) {
$actions['result']['#type'] = 'submit';
$actions['result']['#button_type'] = 'primary';
$actions['result']['#value'] = t('View results');
$actions['result']['#submit'] = array(
'::result',
);
$actions['result']['#ajax'] = $ajax;
$actions['result']['#weight'] = '1';
}
}
return $actions;
}
function showPollResults(PollInterface $poll, $view_mode = 'default', $block = FALSE) {
\Drupal::service('page_cache_kill_switch')
->trigger();
$total_votes = 0;
foreach ($poll
->getVotes() as $vote) {
$total_votes += $vote;
}
$options = $poll
->getOptions();
$poll_results = array();
foreach ($poll
->getVotes() as $pid => $vote) {
$percentage = round($vote * 100 / max($total_votes, 1));
$display_votes = !$block ? ' (' . \Drupal::translation()
->formatPlural($vote, '1 vote', '@count votes') . ')' : '';
$poll_results[] = array(
'#theme' => 'poll_meter',
'#choice' => $options[$pid],
'#display_value' => t('@percentage%', array(
'@percentage' => $percentage,
)) . $display_votes,
'#min' => 0,
'#max' => $total_votes,
'#value' => $vote,
'#percentage' => $percentage,
'#attributes' => array(
'class' => array(
'bar',
),
),
'#poll' => $poll,
);
}
$vote_storage = \Drupal::service('poll_vote.storage');
$user_vote = $vote_storage
->getUserVote($poll);
$output = array(
'#theme' => 'poll_results',
'#raw_question' => $poll
->label(),
'#results' => $poll_results,
'#votes' => $total_votes,
'#block' => $block,
'#pid' => $poll
->id(),
'#poll' => $poll,
'#view_mode' => $view_mode,
'#vote' => isset($user_vote['chid']) ? $user_vote['chid'] : NULL,
);
return $output;
}
public function cancel(array $form, FormStateInterface $form_state) {
$vote_storage = \Drupal::service('poll_vote.storage');
$vote_storage
->cancelVote($this->poll, $this
->currentUser());
\Drupal::logger('poll')
->notice('%user\'s vote in Poll #%poll deleted.', array(
'%user' => $this
->currentUser()
->id(),
'%poll' => $this->poll
->id(),
));
$this
->messenger()
->addMessage($this
->t('Your vote was cancelled.'));
if ($this
->getRequest()->query
->get('ajax_form')) {
$form_state
->setRebuild(TRUE);
}
}
public function result(array $form, FormStateInterface $form_state) {
$form_state
->set('show_results', TRUE);
$form_state
->setRebuild(TRUE);
}
public function back(array $form, FormStateInterface $form_state) {
$form_state
->set('show_results', FALSE);
$form_state
->setRebuild(TRUE);
}
public function save(array $form, FormStateInterface $form_state) {
$options = array();
$options['chid'] = $form_state
->getValue('choice');
$options['uid'] = $this
->currentUser()
->id();
$options['pid'] = $form_state
->getValue('poll')
->id();
$options['hostname'] = \Drupal::request()
->getClientIp();
$options['timestamp'] = \Drupal::time()
->getRequestTime();
$vote_storage = \Drupal::service('poll_vote.storage');
$vote_storage
->saveVote($options);
$this
->messenger()
->addMessage($this
->t('Your vote has been recorded.'));
if ($this
->currentUser()
->isAnonymous()) {
$_SESSION['poll_vote'][$form_state
->getValue('poll')
->id()] = $form_state
->getValue('choice');
}
if ($this
->getRequest()->query
->get('ajax_form')) {
$form_state
->setRebuild(TRUE);
}
}
public function validateVote(array &$form, FormStateInterface $form_state) {
if (!$form_state
->hasValue('choice')) {
$form_state
->setErrorByName('choice', $this
->t('Your vote could not be recorded because you did not select any of the choices.'));
}
}
protected function isCancelAllowed(PollInterface $poll) {
return $poll
->hasUserVoted() && $poll
->getCancelVoteAllow() && $this
->currentUser()
->hasPermission('cancel own vote') && (\Drupal::currentUser()
->isAuthenticated() || !empty($_SESSION['poll_vote'][$poll
->id()])) && $poll
->isOpen();
}
}