class PollViewForm in Poll 8
Displays banned IP addresses.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\poll\Form\PollViewForm implements BaseFormIdInterface
Expanded class hierarchy of PollViewForm
1 file declares its use of PollViewForm
- PollResultsTest.php in tests/
src/ Kernel/ PollResultsTest.php
File
- src/
Form/ PollViewForm.php, line 17
Namespace
Drupal\poll\FormView source
class PollViewForm extends FormBase implements BaseFormIdInterface {
/**
* The Poll of the form.
*
* @var \Drupal\poll\PollInterface
*/
protected $poll;
/**
* {@inheritdoc}
*/
public function getBaseFormId() {
return 'poll_view_form';
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'poll_view_form_' . $this->poll
->id();
}
/**
* Set the Poll of this form.
*
* @param \Drupal\poll\PollInterface $poll
* The poll that will be set in the form.
*/
public function setPoll(PollInterface $poll) {
$this->poll = $poll;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL, $view_mode = 'full') {
// Add the poll to the form.
$form['poll']['#type'] = 'value';
$form['poll']['#value'] = $this->poll;
$form['#view_mode'] = $view_mode;
if ($this
->showResults($this->poll, $form_state)) {
// Check if the user already voted. The form is still being built but
// the Vote button won't be added so the submit callbacks will not be
// called. Directly check for the request method and use the raw user
// input.
if ($request
->isMethod('POST') && $this->poll
->hasUserVoted()) {
$input = $form_state
->getUserInput();
if (isset($input['op']) && $input['op'] == $this
->t('Vote')) {
// If this happened, then the form submission was likely a cached page.
// Force a session for this user so he can see the results.
$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);
// For all view modes except full and block (as block displays it as the
// block title), display the question.
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();
// Set a flag to hide results which will be removed if we want to view
// results when the form is rebuilt.
$form_state
->set('show_results', FALSE);
// For all view modes except full and block (as block displays it as the
// block title), display the question.
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;
}
/**
* Ajax callback to replace the poll form.
*/
public function ajaxReplaceForm(array $form, FormStateInterface $form_state) {
// Embed status message into the form.
$form = [
'messages' => [
'#type' => 'status_messages',
],
] + $form;
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
// Render the form.
$output = $renderer
->renderRoot($form);
$response = new AjaxResponse();
$response
->setAttachments($form['#attached']);
// Replace the form completely and return it.
return $response
->addCommand(new ReplaceCommand('.poll-view-form-' . $this->poll
->id(), $output));
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
public function showResults(PollInterface $poll, FormStateInterface $form_state) {
$account = $this
->currentUser();
switch (TRUE) {
// The "View results" button, when available, has been clicked.
case $form_state
->get('show_results'):
return TRUE;
// The poll is closed.
case $poll
->isClosed():
return TRUE;
// Anonymous user is trying to view a poll they aren't allowed to vote in.
case $account
->isAnonymous() && !$poll
->getAnonymousVoteAllow():
return TRUE;
// The user has already voted.
case $poll
->hasUserVoted():
return TRUE;
default:
return FALSE;
}
}
protected function actions(array $form, FormStateInterface $form_state, $poll) {
$actions = [];
// Default ajax behavior, use the poll URL for faster submission, this
// requires that we explicitly provide the ajax_form query argument too in
// the separate options key, as that replaces all options of the Url object.
$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)) {
// Allow user to cancel their vote.
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';
// View results before voting.
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;
}
/**
* Display a themed poll results.
*
* @param \Drupal\poll\PollInterface $poll
* The poll entity.
* @param bool $block
* (optional) TRUE if a poll should be displayed in a block. Defaults to
* FALSE.
*
* @return array $output
*/
function showPollResults(PollInterface $poll, $view_mode = 'default', $block = FALSE) {
// Ensure that a page that shows poll results can not be cached.
\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,
);
}
/** @var \Drupal\poll\PollVoteStorageInterface $vote_storage */
$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;
}
/**
* Cancel vote submit function.
*
* @param array $form
* The previous form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
public function cancel(array $form, FormStateInterface $form_state) {
/** @var \Drupal\poll\PollVoteStorageInterface $vote_storage */
$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.'));
// In case of an ajax submission, trigger a form rebuild so that we can
// return an updated form through the ajax callback.
if ($this
->getRequest()->query
->get('ajax_form')) {
$form_state
->setRebuild(TRUE);
}
}
/**
* View vote results submit function.
*
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
public function result(array $form, FormStateInterface $form_state) {
$form_state
->set('show_results', TRUE);
$form_state
->setRebuild(TRUE);
}
/**
* Back to poll view submit function.
*
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
public function back(array $form, FormStateInterface $form_state) {
$form_state
->set('show_results', FALSE);
$form_state
->setRebuild(TRUE);
}
/**
* Save a user's vote submit function.
*
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
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();
// Save vote.
/** @var \Drupal\poll\PollVoteStorage $vote_storage */
$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()) {
// The vote is recorded so the user gets the result view instead of the
// voting form when viewing the poll. Saving a value in $_SESSION has the
// convenient side effect of preventing the user from hitting the page
// cache. When anonymous voting is allowed, the page cache should only
// contain the voting form, not the results.
$_SESSION['poll_vote'][$form_state
->getValue('poll')
->id()] = $form_state
->getValue('choice');
}
// In case of an ajax submission, trigger a form rebuild so that we can
// return an updated form through the ajax callback.
if ($this
->getRequest()->query
->get('ajax_form')) {
$form_state
->setRebuild(TRUE);
}
// No explicit redirect, so that we stay on the current page, which might
// be the poll form or another page that is displaying this poll, for
// example as a block.
}
/**
* Validates the vote action.
*
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
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.'));
}
}
/**
* Checks if the current user is allowed to cancel on the given poll.
*
* @param \Drupal\poll\PollInterface $poll
*
* @return bool
* TRUE if the user can cancel.
*/
protected function isCancelAllowed(PollInterface $poll) {
// Allow access if the user has voted.
return $poll
->hasUserVoted() && $poll
->getCancelVoteAllow() && $this
->currentUser()
->hasPermission('cancel own vote') && (\Drupal::currentUser()
->isAuthenticated() || !empty($_SESSION['poll_vote'][$poll
->id()])) && $poll
->isOpen();
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
public static | function |
Instantiates a new instance of this class. Overrides ContainerInjectionInterface:: |
87 |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
FormBase:: |
public | function |
Form validation handler. Overrides FormInterface:: |
62 |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PollViewForm:: |
protected | property | The Poll of the form. | |
PollViewForm:: |
protected | function | ||
PollViewForm:: |
public | function | Ajax callback to replace the poll form. | |
PollViewForm:: |
public | function | Back to poll view submit function. | |
PollViewForm:: |
public | function |
Form constructor. Overrides FormInterface:: |
|
PollViewForm:: |
public | function | Cancel vote submit function. | |
PollViewForm:: |
public | function |
Returns a string identifying the base form. Overrides BaseFormIdInterface:: |
|
PollViewForm:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
PollViewForm:: |
protected | function | Checks if the current user is allowed to cancel on the given poll. | |
PollViewForm:: |
public | function | View vote results submit function. | |
PollViewForm:: |
public | function | Save a user's vote submit function. | |
PollViewForm:: |
public | function | Set the Poll of this form. | |
PollViewForm:: |
function | Display a themed poll results. | ||
PollViewForm:: |
public | function | ||
PollViewForm:: |
public | function |
Form submission handler. Overrides FormInterface:: |
|
PollViewForm:: |
public | function | Validates the vote action. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |