Problem/Motivation

Currently, the poll module allows only one anonymous vote for a poll per IP address. There are use cases where this restriction isn't desired. For example when a group of people, who are on the same network, are asked to vote on the poll.

Steps to reproduce

  1. Create a poll.
  2. Log out.
  3. Place a vote on the poll.
  4. Open an other browser or go to the poll with an other device.

You see only the poll results and cannot vote again.

Proposed resolution

On the poll creation form, add an option to change the restriction mode for anonymous users.

Allow the following restriction methods:

  • One vote per IP
    This is the default option and follows the current behavior. If an anonymous user places a vote, he/she cannot vote again: not in an other browser, not when clearing cookies and not even on an other device in the same network. He/she can however place another vote when switching his/her device to an other network.
  • One vote per session
    When an anonymous user places a vote, he/she cannot vote again during the current session. He/she can vote again when using an other browser, when clearing cookies or when using an other device in the same network. He/she can't however place another vote when only switching networks.
  • Unlimited votes
    There are no restrictions on how many votes the same anonymous user can place. After voting, he/she can go back to the voting form to place another vote. Can be useful in a situation where a group of people need to place a vote on the same device, for example at a stand in an exhibition hall.
    This option has no effect on authenticated users, they continue to only be able to vote once per poll.

Remaining tasks

  • Fix the test failures for the vote restriction option "unlimited".
  • Review

User interface changes

On the poll creation form, a setting called "Anonymous vote restriction" is added. This setting is only visible when enabling the option "Allow anonymous votes".

API changes

  • Constants are added to PollInterface for each vote restriction.
  • A method called getVoteRestriction() is added to PollInterface.
  • When calling the method saveVote() on PollVoteStorage, the ID of the saved vote gets returned. Previously, the method returned nothing.

Data model changes

  • The table "poll_vote" gets a new column called "id". This also becomes the new primary key. This is needed because multiple votes can now exist per combination of poll ID, user ID and hostname (which previously formed the primary key).
  • The content entity type "poll" gets a new base field called "anonymous_vote_restriction". In this field, the setting for the vote restriction is stored.

Release notes snippet

Follow-up issue

#3517381: Replace the usage of the super global $_SESSION

CommentFileSizeAuthor
#66 poll-unlimited_votes-2909811-66.patch21.16 KBrahulk
#61 poll-unlimited_votes-2909811-61.patch21.82 KBjvandooren
#58 poll-unlimited_votes-2909811-58.patch21.65 KBjvandooren
#54 poll-unlimited_votes-2909811-54.patch22.08 KBcgoffin
#53 poll-unlimited_votes-2909811-53.patch22.08 KBcgoffin
#38 poll-unlimited-votes-2909811-38.patch20.12 KBmegachriz
#35 interdiff-2909811-34-35.txt3.63 KBmegachriz
#35 poll-unlimited-votes-2909811-35.patch21.12 KBmegachriz
#34 poll-error-backtrace-3.txt59.55 KBmegachriz
#34 poll-error-backtrace-2.txt35.23 KBmegachriz
#34 poll-error-backtrace-1.txt14.96 KBmegachriz
#34 interdiff-2909811-31-34.txt20.2 KBmegachriz
#34 poll-unlimited-votes-2909811-34.patch20.91 KBmegachriz
#31 poll_unlimited-votes-2909811-31.patch11.27 KBguptahemant
#30 poll_unlimited-votes-2909811-30.patch10.84 KBguptahemant
#29 poll_unlimited-votes-2909811-29.patch9.37 KBliam mcdermott
#28 interdiff_23-28.txt1.5 KBnitebreed
#28 poll_unlimited-votes-2909811-28.patch9.36 KBnitebreed
#23 interdiff.txt1.49 KBtostinni
#23 poll_unlimited-votes-2909811-23.patch9.79 KBtostinni
#22 poll_multiple-votes-same-ip-2909811-22.patch9.33 KBtostinni
#20 interdiff_5-19.txt2.58 KBakoe
#20 poll_multiple-votes-same-ip-2909811-19.patch8.49 KBakoe
#18 2909811-diff-5-18.txt1.69 KBvijaycs85
#18 2909811-18.patch8.37 KBvijaycs85
#16 interdiff_5-16.txt2.65 KBakoe
#16 poll_multiple-votes-same-ip-2909811-16.patch8.02 KBakoe
#5 poll_multiple-votes-same-ip-2909811-5.patch7.51 KBmatroskeen
#2 pool-2909811-2.patch6.15 KBstomusic

Issue fork poll-2909811

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

stomusic created an issue. See original summary.

stomusic’s picture

StatusFileSize
new6.15 KB

Here is my solution. I added setting for allow vote anonymous users once per session.

stomusic’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 2: pool-2909811-2.patch, failed testing. View results

matroskeen’s picture

Status: Needs work » Needs review
StatusFileSize
new7.51 KB

I've added another option to restrict votes by cookie value.
Also, I moved these settings to the Poll entity.

Patch is attached.

dvanbrenk’s picture

Hi Matroskeen,

Thanks for the patch, but I'm getting the following error:

Drupal\Core\Entity\EntityStorageException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'anonymous_vote_restrictions' in 'field list': INSERT INTO {poll_field_data} (id, langcode, uid, question, runtime, anonymous_vote_allow, anonymous_vote_restrictions, cancel_vote_allow, result_vote_allow, status, created, default_langcode) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11); Array ( [:db_insert_placeholder_0] => 8 [:db_insert_placeholder_1] => nl [:db_insert_placeholder_2] => 1 [:db_insert_placeholder_3] => test [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => 1 [:db_insert_placeholder_6] => cookie [:db_insert_placeholder_7] => 1 [:db_insert_placeholder_8] => 0 [:db_insert_placeholder_9] => 1 [:db_insert_placeholder_10] => 1514454767 [:db_insert_placeholder_11] => 1 ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (regel 805 van /var/www/vhosts/.../httpdocs/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

Do you maybe have an solution? Thanks in advance.

matroskeen’s picture

Hello @dvanbrenk,

For existing installations, we also need a hook_update_N() that will add anonymous_vote_restrictions base field.

Currently, I don't have enough time to take care of this. Maybe someone else will do.

Another solution is just to uninstall and install the module.

dvanbrenk’s picture

Thanks @matroskeen, works like a charm!

marty2081’s picture

Instead of uninstalling and installing again, you can also use "drush entup".

terranrich’s picture

@Matroskeen, you'll be happy to hear that I applied your patch at #5, and it worked perfectly, at least for cookie-based voting. I reinstalled the Poll module using Devel, and after recreating my poll, I was able to vote on the same poll in multiple browsers from the same IP address.

I have not tested the middle option, "One vote per session", but the third option, "One vote per browser (cookie)", works beautifully.

terranrich’s picture

Status: Needs review » Reviewed & tested by the community

I'd still prefer if somebody else were to verify, though. Maybe I have overlooked something, although I don't think so.

elijah lynn’s picture

2nd RTBC for #5.

It is important to note that I had to do a `drush updatedb` (updb) AND `drush entity-updates` (entup) to get it working (important if you are coming from Drupal 7).

Thanks for working on this everyone, it was the first feature I noticed missing after installing the module that I knew I would need to work on.

elijah lynn’s picture

Actually... I have some more thoughts. I think this is good to get in as is. However, I would like to see the setting to allow voting by IP, Session or Cookie actually moved into config, and not on the instance. I don't think editors need to change that type of setting for every poll, and it will probably confuse the majority.

Would be nice to have in this patch, but I think it could be a follow up, however, that would mean code to migrate that and even then, you couldn't migrate it really because every instance could have a different setting.

So, I actually think we should think about that UX for a bit and see about moving it into config.

elijah lynn’s picture

One more thing would be do be able to choose the default setting in the config.

Tyetho’s picture

With this is there a way to refresh it so that a user can keep voting not just see the results until the window is open and closed again?

akoe’s picture

We have used this patch for quite some time now and can confirm it solves the initial requirement of multiple votes from one IP.
Nevertheless the cookie introduced by the line 360 saved with core function 'user_cookie_save' comes without the secure flag

  user_cookie_save(['poll_voted' => $form_state->getValue('poll')->id()]);

This might be a information leakage issue and with the following patch a cookie including secure flag is created if the user accesses the page via https protocol.

Btw. the cookie itself seems a bit misleading (or at least i didn't understood it correctly) since it stores only the last poll id, which a user voted for (not all polls a visitor has voted for).

vijaycs85’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/src/Form/PollViewForm.php
    @@ -61,10 +61,7 @@
    -
    -          if ($this->poll->getVoteRestrictions() !== 'session') {
    -            $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    -          }
    
    @@ -72,7 +69,10 @@
    -          $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    +
    +          if ($this->poll->getVoteRestrictions() !== 'session') {
    +            $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    +          }
    

    Looks like these changes are reverted by mistake?

  2. +++ b/src/Form/PollViewForm.php
    @@ -359,6 +354,20 @@
    +            setrawcookie('Drupal.visitor.' . $field, rawurlencode($value), REQUEST_TIME + 31536000, '/', '.'.$domain, TRUE,TRUE);
    

    Space missing before/after "." and after ","

vijaycs85’s picture

Status: Needs work » Needs review
StatusFileSize
new8.37 KB
new1.69 KB

Here is a patch addresses my comments in #17 and other improvements on setcookie part.

vijaycs85’s picture

+++ b/src/Form/PollViewForm.php
@@ -348,16 +348,26 @@ class PollViewForm extends FormBase implements BaseFormIdInterface {
+              setrawcookie('Drupal.visitor.poll_voted', $poll_id, \Drupal::time()->getRequestTime() + 31536000, '/', $domain, TRUE,TRUE);

Minor: Looks like I missed one space between "TRUE"s.

akoe’s picture

Thanks @vijaycs85 for cleaning up the patch code style. Just ironed out the space you mentioned in #18.

naheemsays’s picture

Is it useful to store/user the users mac address - so 1 vote per device?

tostinni’s picture

drush entity-updates shouldn't be used anymore (see Support for automatic entity updates has been removed) so I updated the patch to add the field in poll_update_8002().

I also added a setInitialValue('ip') but it doesn't seem to work.
More eyes are welcome here.

tostinni’s picture

StatusFileSize
new9.79 KB
new1.49 KB

I also had the special case to allow unlimited anonymous votes, so here is a patch including this option.

thpoul’s picture

Status: Needs review » Reviewed & tested by the community

Tested on project I have been migrating from Pollim and came across this problem.

Patch #23 works like a charm on 8.7.7. Thank you for this!

Moving to RTBC.

rasikap’s picture

Assigned: Unassigned » rasikap

Patch #23 works for me. Have used this in my project with Drupal version 8.6.16.

Hence moving to RTBC.

Thanks,
Rasika P

berdir’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests
  1. +++ b/poll.install
    @@ -59,9 +66,7 @@ function poll_schema() {
         ),
         'indexes' => array(
    -      'chid' => array('chid'),
    -      'hostname' => array('hostname'),
    -      'uid' => array('uid'),
    +      'id' => array('id'),
         ),
    

    These indexes shouldn't be changed, we already have an index for the id with the primary key.

  2. +++ b/poll.install
    @@ -125,3 +130,40 @@ function poll_update_8001() {
    +
    +/**
    + * Add id - unique key for votes.
    + * Add 'anonymous_vote_restrictions' field to 'poll' entities.
    + */
    +function poll_update_8002() {
    

    Two sentences like that isn't valid coding standard and also looks strange in drush at least. Lets try to make a single sentence of this, it can be less technical: Add unique id to votes and add setting for multiple votes per IP.

  3. +++ b/poll.install
    @@ -125,3 +130,40 @@ function poll_update_8001() {
    +  $schema->dropIndex('poll_vote', 'chid');
    +  $schema->dropIndex('poll_vote', 'hostname');
    +  $schema->dropIndex('poll_vote', 'uid');
    +  $schema->dropPrimaryKey('poll_vote');
    ...
    +  $schema->addIndex('poll_vote', 'id', ['id'], ['fields' => ['id' => $target_id_schema]]);
    

    same here, the index changes are not necessary.

  4. +++ b/poll.install
    @@ -125,3 +130,40 @@ function poll_update_8001() {
    +    ->setLabel(t('Anonymous vote restrictions'))
    +    ->setDescription(t('Enable to allow votes from same IP.'))
    

    the description says "enable", but then it's a list field with several options. Maybe we can just remove the description, the options are pretty self-explaining?

  5. +++ b/src/Entity/Poll.php
    @@ -195,6 +195,14 @@ class Poll extends ContentEntityBase implements PollInterface {
        */
    +  public function getVoteRestrictions() {
    +    $restrictions = $this->get('anonymous_vote_restrictions')->value;
    +    return empty($restrictions) ? 'ip' : $restrictions;
    +  }
    

    If we really need a dynamic fallback then you can write return $this->get(...)->value ?: 'ip'; but not sure we even need that with the update path that sets the default? The field is required, so isn't allowed to be empty.

  6. +++ b/src/Entity/Poll.php
    @@ -305,6 +313,25 @@ class Poll extends ContentEntityBase implements PollInterface {
    +      ->setDescription(t('Enable to allow votes from same IP.'))
    

    remove here too then.

  7. +++ b/src/Entity/Poll.php
    @@ -305,6 +313,25 @@ class Poll extends ContentEntityBase implements PollInterface {
    +      ->setDisplayOptions('form', array(
    +        'type' => 'options_select',
    +        'settings' => array(
    +          'display_label' => TRUE,
    +        ),
    +        'weight' => 1,
    +      ));
    

    we just made all other fields configurable in the UI, so should do that here too. Also, the default weight should be unique.

  8. +++ b/src/Form/PollViewForm.php
    @@ -69,7 +69,10 @@ class PollViewForm extends FormBase implements BaseFormIdInterface {
               drupal_set_message($this->t('Your vote for this poll has already been submitted.'), 'error');
    -          $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    +
    +          if ($this->poll->getVoteRestrictions() !== 'session') {
    +            $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    +          }
             }
           }
    

    Not quite sure yet about the method name/API. It says VoteRestrictionS(), plural, but only returns a string. Also, it has several magic strings that are used in several places, might make sense to either define constants for them. or have dedicated methods for this somehow.

  9. +++ b/src/Form/PollViewForm.php
    @@ -112,6 +115,11 @@ class PollViewForm extends FormBase implements BaseFormIdInterface {
     
    +    // For unlimited votes, unset the session.
    +    if ($this->poll->getVoteRestrictions() == 'unlimited') {
    +      $_SESSION['poll_vote'][$this->poll->id()] = FALSE;
    +    }
    

    I don't really understand why this needs to be unset here, I'd expect we wouldn't set it in the first place instead?

  10. +++ b/src/Form/PollViewForm.php
    @@ -345,12 +353,27 @@ class PollViewForm extends FormBase implements BaseFormIdInterface {
    +      // Set cookie to mark that user already voted.
    +      if ($form_state->getValue('poll')->getVoteRestrictions() === 'cookie') {
    +          // Set secured cookie for HTTPS request.
    +          if ($this->getRequest()->isSecure()) {
    +              $domain = '.' . $this->getRequest()->getHost();
    +              // Set cookie here as user_cookie_save() does not accept
    +              // additional parameters.
    +              setrawcookie('Drupal.visitor.poll_voted', $poll_id, \Drupal::time()->getRequestTime() + 31536000, '/', $domain, TRUE, TRUE);
    +          }
    +          else {
    +            user_cookie_save(['poll_voted' => $poll_id]);
    +          }
    

    i don't really get the cookie option. The session is a cookie too? If you know how to delete that then you can delete the cookie too?

    Looks like the cookie has a much higher expiration time, but it's not actually safe to rely on this anyway.

    And last, this is definitely complex enough to require tests. Right now, only the default option is tested, we basically need to test the main workflow with every option. Would also be useful to expand the issue summary a bit to better explain these different options and what this does.

chemsabd’s picture

I'm not able to get this patch working for 8.x-1.3

nitebreed’s picture

StatusFileSize
new9.36 KB
new1.5 KB

Rerolled the path from #23 to apply to the latest 8.x-1.x dev

liam mcdermott’s picture

StatusFileSize
new9.37 KB

Here's an updated patch taking into account the feedback from points 1-7 of #26, it's WIP so I'll leave the status as Needs Work.

Does anyone object if I just remove the cookie option? It's functionally very similar to the session option, the difference isn't obvious to the user either.

It also doesn't seem useful to allow one person to vote on a poll an unlimited number of times. Does anyone object if I remove that option from the patch?

I'm thinking this patch is more likely to get in if its focus is tight and the amount of change is small.

guptahemant’s picture

Assigned: rasikap » Unassigned
StatusFileSize
new10.84 KB

Adding a new patch here in this refactored code so that vote id will be stored and will be checked from database to render the Poll, Keeping the issue to needs work since we still need the tests.

Please review so that it can be improved and if the direction is correct.

Thanks

guptahemant’s picture

StatusFileSize
new11.27 KB

Updated the patch to delete votes correctly on pressing cancel button. Keeping needs work to address the review points from #26

megachriz’s picture

@Berdir
From #26 (point 8):

Also, it has several magic strings that are used in several places, might make sense to either define constants for them. or have dedicated methods for this somehow.

Do you think it would make sense to use a plugin system for these restrictions?

@others, @Matroskeen

i don't really get the cookie option. The session is a cookie too? If you know how to delete that then you can delete the cookie too?

I don't quite understand the benefit of the cookie option either. @Matroskeen You added that option in #5, can you explain why?

matroskeen’s picture

I would love to, but I can't explain why 🙃
It's been almost 3 years and it was probably one of my first Drupal 8 projects...

Feel free to remove cookie option, I have nothing to say in my defence 🤷‍♂️

Cheers!

megachriz’s picture

I updated the issue summary and I made changes to the patch to address the remaining points of #26.

In this updated patch I've made the following changes:

  • I've added automated tests. These tests cover the cases:
    • Placing a vote as anonymous user for each vote restriction type.
    • Canceling a vote as anonymous user for each vote restriction type.
  • I removed the vote restriction type "cookie". In #26 @Berdir asked why this option was needed and in #33 @Matroskeen - who added that option in #5 - replied that he doesn't remember. I also removed it to reduce complexity.
  • Constants are added to PollInterface for each vote restriction type.
  • The method getVoteRestrictions() is renamed to getVoteRestriction() as per feedback from @Berdir in point 8 of #26.
  • The base field "anonymous_vote_restrictions" is renamed to "anonymous_vote_restriction" for the same reason.
  • To PollViewForm a method called isVotingAllowed() is added in order to deal with the vote restriction type "unlimited". In this scenario, a vote can be recorded but the user still needs to be able to go back the poll form. Previously, the poll results always got shown whenever there existed a vote for the current user.

I've hard time though to get things correct for the vote restriction type "unlimited". During testing I often get an error like the following:

Notice: unserialize(): Error at offset 4353 of 12718 bytes in Drupal\Component\Serialization\PhpSerialize::decode() (line 21 of core/lib/Drupal/Component/Serialization/PhpSerialize.php).

When switching between "View results" and "View poll", the error backtrace becomes longer. See attached file for examples. One of the tests also fail on this error. Leaving to "Needs work" because of this.

megachriz’s picture

StatusFileSize
new21.12 KB
new3.63 KB

In this patch I fixed the following issues that were introduced in the previous patch:

  • An issue where authenticated users would see the poll results first - if they voted as anonymous user first during the same session.
  • Corrected a check in isVotingAllowed(): when checking for the vote restriction "unlimited", it also needs to check if the current user is anonymous.
  • A similar check was added to showResults().
  • Some coding standards.

The serialize issue seems to happen specifically on PHP 7.4. I'm not yet sure how to solve that. I also got this serialization error when switching between viewing the poll results and going back to the poll. So maybe I can write a test to see if that error also happens without this patch.

pdxclankeith’s picture

I'm seeing a strange result after applying the patch in #35, the first time an anonymous user comes to a page, the unique identifier isn't applied to the poll questions, so when they submit the poll, it doesn't show the results (vote is counted). After that, if they use the "View Poll" button, the poll is displayed with the unique id, and voting works where the results are displayed after they vote. This continues until the page is reloaded, then the process starts over again with the id not being applied.

I've tried tracking this down to see if it's a cache issue (doesn't appear to be), but can't figure out what the difference is after the anonymous user votes the first time.

Running on Drupal 8.9.16, and have tried it on a new D8 installation with only the poll module and patch added with same results. I'm happy to try and help debug this, just not sure where I should be looking.

Thanks

sutharsan’s picture

The #35 patch worked on my end (Drupal 9.2.7) for anonymous voters.

For others who upgrade from old (< #34) to new patch: To handle the field name change (anonymous_vote_restrictions to anonymous_vote_restriction), I used the code below. Depending on your use case you need to change the value of ::setInitialValue() or write an update script to migrate the values.

  // Create the new 'anonymous_vote_restriction' field.
  $anonymous_vote_restriction = BaseFieldDefinition::create('list_string')
    ->setLabel(t('Anonymous vote restriction'))
    ->setSetting('allowed_values', [
      'ip' => t('One vote per IP'),
      'session' => t('One vote per session'),
      'unlimited' => t('Unlimited votes'),
    ])
    ->setDefaultValue('ip')
    ->setInitialValue('session')
    ->setRequired(TRUE);
  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('anonymous_vote_restriction', 'poll', 'poll', $anonymous_vote_restriction);

  // Delete the old 'anonymous_vote_restrictions' field.
  $update_manager = \Drupal::entityDefinitionUpdateManager();
  $definition = $update_manager->getFieldStorageDefinition('anonymous_vote_restrictions', 'poll');
  $update_manager->uninstallFieldStorageDefinition($definition);

megachriz’s picture

Status: Needs work » Needs review
StatusFileSize
new20.12 KB

Reroll of the patch in #35.

Note: the changes in PollViewForm::showResults() need to be implemented slightly differently if #3178172: Button "View poll" is missing for authenticated users gets committed (for which I just also rerolled a patch).

The serialize issue noted in #35 seem to have been restricted to Drupal 8 only and no longer an issue in Drupal 9. Therefore, moving the status to "Needs review".

megachriz’s picture

For some reason, the patch in #38 did not apply. I've tried it with an issue branch instead now.

fishfree’s picture

@MegaChriz Thank you very much for your patch. It works! I want to add a new option: One vote per session everyday. I tried adding 2 lines as below:

In file src/Form/PollViewForm.php, public function save(array $form, FormStateInterface $form_state) {
...
// 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'][$poll_id] = $vote_id;
$_SESSION['poll_vote'][$poll_id]['poll_time'] = \Drupal::time()->getRequestTime();
...

In file src/Form/PollViewForm.php, public function getUserVote(PollInterface $poll) {
...
case PollInterface::ANONYMOUS_VOTE_RESTRICT_SESSION_EVERYDAY:
$vote_id = FALSE;
if (!empty($_SESSION['poll_vote'][$poll->id()]) && !empty($_SESSION['poll_vote'][$poll->id()]['poll_time'])) {
if (\Drupal::time()->getRequestTime() - (int)$_SESSION['poll_vote'][$poll->id()]['poll_time'] <= 86400) {
$vote_id = $_SESSION['poll_vote'][$poll->id()];
}
}
if ($vote_id) {
$query = $this->connection->query("SELECT * FROM {poll_vote} WHERE id = :vid", [
':vid' => $vote_id,
]);
}
break;

...

But it doesn't work. I also add the const ANONYMOUS_VOTE_RESTRICT_SESSION_EVERYDAY in the file src\PollInterface.php and the related options in the related file.

skylord’s picture

#40 works great, thanks a lot! I think it's a musthave for any poll module!

fozzieblue’s picture

Version: 8.x-1.x-dev » 8.x-1.6
Category: Task » Bug report

I'm not able to update the poll module to 1.5 or 1.6.

My Drupal site is running the following:
- poll module 8.x-1.4
- Drupal 9.5.8
- I am using patch #35 from this issue.

When I run `composer update drupal/poll` I get the following error:

Could not apply patch! Skipping. The error was: Cannot apply patch https://www.drupal.org/files/issues/2020-10-21/poll-unlimited-votes-2909811-35.patch
[Exception]                                                                                        
Cannot apply patch Anonymous users - Multiple voting from one IP (https://www.drupal.org/files/issues/2020-10-21/poll-unlimited-votes-2909811-35.patch)!  

I removed the patch and was able to update the poll module to 8.x-1.6. But updating with out the patch in #35, the poll module no longer allows multiple votes from the same IP.

Is anyone else able to update poll to 8.x-1.6 and still use patch #35?

I posted above before I tested the patch in #40. I had to remove the patch from #35 and then added the patched referenced in #40. That fixed my issue.

naheemsays’s picture

Can an alternative approach be to differentiate by mac address?

I dont think it is as common for different devices from the same IP address to be shared between multiple users as much as it was say 10 years ago, so if we still want to try and differentiate voters, it may be reasonable to look at distinguishing based on something other than IP address.

bramdriesen’s picture

Version: 8.x-1.6 » 2.0.x-dev
Assigned: Unassigned » bramdriesen

Using this for a long time on a few projects. Would love to incorporate this on the new 2.0.x release.

Re #44: Not sure, I think the main thing used is still IP's. E.g. we still have the IP ban module, CDN's like CloudFlare offer IP bans but not Mac address bans.

bramdriesen’s picture

Ready for review once more.

Also updating credits for everyone who actively (and meaningful) participated on this issue for the last 6 years 🙈.

bramdriesen’s picture

Assigned: bramdriesen » Unassigned
ivnish’s picture

Needs reroll

error: patch failed: src/Form/PollViewForm.php:247
error: src/Form/PollViewForm.php: patch does not apply
error: patch failed: src/Form/PollViewForm.php:204
error: src/Form/PollViewForm.php: patch does not apply

ivnish’s picture

Status: Needs review » Needs work
bramdriesen’s picture

Thanks @Berdir! This also needs a rebase now and a change in ID for the install/update hook

cgoffin made their first commit to this issue’s fork.

cgoffin’s picture

StatusFileSize
new22.08 KB

I rebased the changes from the dev branch. Here also an up to date patch.

cgoffin’s picture

StatusFileSize
new22.08 KB

There was a missing newline at the end of the patch file. Here the new version.

lobodakyrylo’s picture

#54 patch stopped working after last updates on dev branch.

anairamzap made their first commit to this issue’s fork.

bramdriesen’s picture

Priority: Normal » Major
jvandooren’s picture

StatusFileSize
new21.65 KB

Rerolled patch against latest 2.0.x

jvandooren’s picture

The patch in #58 does not work as it adds a 8003 updatehook while in 2.0.x updatehook 8003 already exists for something else... Simply changing the one from the patch to 8007 exposes the problem Bram mentioned above (the updatehook is not idempotent).

jvandooren’s picture

StatusFileSize
new21.82 KB

Reroll against 2.0.x with the idempotent update hook. This should be safe to use if you have already used an earlier version of this patch in your project.

bramdriesen’s picture

drupalite1411’s picture

Used patch #61 on poll 2.0.0-alpha2, it is providing option from UI to select per IP vote,per session vote and unlimited vote.
Select any option out of these three and save the form. When I edit the form the select field "Anonymous vote restriction" does retain it's value.
Moreover, the functionality is not working.
I can't use unlimited vote or per session vote.

drupalite1411’s picture

Updated. In the patch #61, removed this repetitive code from poll.php and vote per session functionality is working fine now. I am still testing

  $fields['anonymous_vote_restriction'] = BaseFieldDefinition::create('list_string')
      ->setLabel(t('Anonymous vote restriction'))
      ->setSetting('allowed_values', [
        'ip' => t('One vote per IP'),
        'session' => t('One vote per session'),
        'unlimited' => t('Unlimited votes'),
      ])
      ->setDefaultValue('ip')
      ->setRequired(TRUE)
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'settings' => [
          'display_label' => TRUE,
        ],
        'weight' => 2,
      ])
      ->setDisplayConfigurable('form', TRUE);

I found it is actually removed from the merge request https://git.drupalcode.org/project/poll/-/merge_requests/30/diffs?commit...

drupalite1411’s picture

While debugging this patch, found that https://www.drupal.org/project/poll/issues/3263876 this issue still exists in vote per IP.
Steps to replicate is mentioned in the issue https://www.drupal.org/project/poll/issues/3263876

rahulk’s picture

StatusFileSize
new21.16 KB

Updated the patch #61 & removed the redundant code from poll.php.

bramdriesen’s picture

Please stop updating and uploading manual patch files. Any work should be done on the issue fork.

bramdriesen’s picture

Issue summary: View changes
bramdriesen’s picture

Status: Needs work » Needs review

I think this is ready for review once more. Preferably also some manual testing as there was one issue the tests didn't catch which I'm still not sure why that test was nog failing (see last commit).

bramdriesen’s picture

Issue summary: View changes
bramdriesen’s picture

ivnish’s picture

Status: Needs review » Needs work

I found some issues.

1) "Anonymous vote restriction" field doesn't save (or doesn't load saved value) when save/edit poll

2) When I uncheck "Allow anonymous votes" I can't save poll because of "Anonymous vote restriction field is required."

bramdriesen’s picture

Status: Needs work » Needs review

1) "Anonymous vote restriction" field doesn't save (or doesn't load saved value) when save/edit poll

I could not replicate. That sounds more like the database schema was not installed/updated correctly?

The required field logic is fixed by using a state.

ivnish’s picture

Status: Needs review » Reviewed & tested by the community

I reinstalled module again and all works fine

I tested a functionality and all works as expected

  • bramdriesen committed 734b68a8 on 2.0.x
    Issue #2909811 by bramdriesen, megachriz, cgoffin, jvandooren, akoe,...
bramdriesen’s picture

Status: Reviewed & tested by the community » Fixed

Thanks everyone who participated on this issue for the past 8 years! Please create a new issue if you encounter any issues with this.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.