• Resolved loehoafaq

    (@loehoafaq)


    I’ve figured out how to restrict polls so only logged in users can vote. Is it possible to further restrict them so each user can vote only once? I see that I can impose a ‘vote once’ restriction using IP address or cookie, but that doesn’t prevent a user from voting multiple times from different platforms at different locations, or from using a VPN to change their IP address.

    Thanks!

Viewing 13 replies - 1 through 13 (of 13 total)
  • Plugin Support Williams – WPMU DEV Support

    (@wpmudev-support8)

    Hi @loehoafaq

    I hope you’re well today!

    Currently it’s not possible to restrict this way by user. We do have this feature already planned for future so it will be added with one of future releases but I don’t have version and ETA yet.

    It may possibly be doable with a bit of additional custom code but I need to consult our developers about it so I’d appreciate some patience on it. I have already asked them to check and we’ll update you here once we got response.

    Best regards,
    Adam

    Thread Starter loehoafaq

    (@loehoafaq)

    Thanks, Adam. Look forward to your reply. I’ve set up an Astra child theme in which I’ve already got some custom code, so adding more would be a feasible solution for me.

    Plugin Support Nithin – WPMU DEV Support

    (@wpmudevsupport11)

    Hi @loehoafaq,

    Could you please try this code and see whether it helps?

    <?php
    
    add_filter( 'forminator_poll_handle_form_user_can_vote', 'wmudev_check_user_submission_poll', 10, 2 );
    function wmudev_check_user_submission_poll( $user_can_vote, $module_id ) {
        if ( $module_id != 230 ) { //Please change the poll ID
            return $user_can_vote;
        }
    
        if ( !is_user_logged_in() ) {
            return $user_can_vote;
        }
    
        $user_id = get_current_user_id();
    
        $users_with_vote = get_option( $module_id.'_poll_users', array() );
        if ( ! empty( $users_with_vote ) ) {
            if ( in_array( $user_id, $users_with_vote ) ) {
                $user_can_vote = false;
                throw new Exception( esc_html__( 'You have already submitted a vote to this poll', 'forminator' ) );
            }
        }
    
        return $user_can_vote;
    }
    
    add_action( 'forminator_poll_after_handle_submit', 'wpmudev_record_user_poll_submission', 10, 2 );
    add_action( 'forminator_poll_after_save_entry', 'wpmudev_record_user_poll_submission', 10, 2 );
    function wpmudev_record_user_poll_submission( $module_id, $response ) {
        if ( $module_id != 230 ) { //Please change the poll ID
            return;
        }
    
        if ( is_user_logged_in() ) {
            $user_id = get_current_user_id();
            $option = get_option( $module_id.'_poll_users', array() );
            array_push( $option, $user_id );
            $updated_option = array_unique( $option );
            update_option( $module_id.'_poll_users', $updated_option );
        }
    }

    In the above code, you’ll have to update the number 230 to your Form ID. Suppose your form ID is 123, then the code will change as:

    if ( $module_id != 123 )

    You can apply the code as a mu-plugins. Please check this link on how to implement the above code as a mu-plugins:
    https://wpmudev.com/docs/using-wordpress/installing-wordpress-plugins/#installing-mu-plugins

    Best Regards,

    Nithin

    Thread Starter loehoafaq

    (@loehoafaq)

    I have a couple of questions

    1. Am I correct in thinking module_id is passed in as the id of the current poll by forminator, and if I want every poll to be treated this way I can just remove the check for a specific value [if ( $module_id != 230 )]?
    2. Since I only want logged in users who haven’t previously voted to be able to vote, wouldn’t I want to modify the code as follows to exclude those who are not logged in?
      • if (!is_user_logged_in()) { return false;}
    3. Although I’m a programmer, I’m a rank amateur when it comes to WordPress hooks. Will these functions be automatically called for each poll or must I add something to cause that to happen?
    4. Other than observing the behavior of my polls when I test this, is there any log file I should examine for evidence of what’s happening?

    Thanks very much for your reply and the effort you put into this. I’ll try it tomorrow and let you know how it goes.

    Plugin Support Patrick – WPMU DEV Support

    (@wpmudevsupport12)

    Hi @loehoafaq

    Am I correct in thinking module_id is passed in as the id of the current poll by forminator, and if I want every poll to be treated this way I can just remove the check for a specific value [if ( $module_id != 230 )]?

    Yes, if you don’t want to restrict the IDs you can remove that part.

    Since I only want logged in users who haven’t previously voted to be able to vote, wouldn’t I want to modify the code as follows to exclude those who are not logged in?

    If we are on the same page, any logged out user would be able to vote but logged in could vote only once? If so you need to replace the:

    
    if ( !is_user_logged_in() ) {
            return $user_can_vote;
        }

    to

    if ( is_user_logged_in() ) {
            return $user_can_vote;
        }

    But in case it is a different situation please let us know, the code now will check if user is logged out won’t allow to vote, for logged in users it allow only once.

    Although I’m a programmer, I’m a rank amateur when it comes to WordPress hooks. Will these functions be automatically called for each poll or must I add something to cause that to happen?

    It will be automatically for any Poll this is why we had to implement the ID validation.

    Other than observing the behavior of my polls when I test this, is there any log file I should examine for evidence of what’s happening?

    The best test would be using a Staging site and then trying out the code across different polls, it won’t create any log other than register the new vote or prevent duplicated votes.

    Let us know if you have any additional questions.
    Best Regards
    Patrick Freitas

    Thread Starter loehoafaq

    (@loehoafaq)

    Test Methodology

    1. I created a new poll (forminator_poll id=”260″), verified that it works properly, then duplicated it (forminator_poll id=”266″).
    2. I followed the provided instructions to add the following code to a mu-plugins php file with the correct permissions.
    <?php
    
    add_filter( 'forminator_poll_handle_form_user_can_vote', 'wmudev_check_user_submission_poll', 10, 2 );
    function wmudev_check_user_submission_poll( $user_can_vote, $module_id ) {
    
        if ( $module_id != 266 ) {        // Only apply filter to copy of test poll
            return $user_can_vote;
        }
    
    //    if ( !is_user_logged_in() ) {
    //        return $user_can_vote;
    //    }
    
        if ( !is_user_logged_in() ) {     // only logged-in users can vote
            $user_can_vote = false;
            throw new Exception( esc_html__( 'You must be logged in to vote in this poll', 'forminator' ) );
            return $user_can_vote;
        }
    
        $user_id = get_current_user_id(); // get logged-in user's user_id
    
        $users_with_vote = get_option( $module_id.'_poll_users', array() );   // get list of those who have previously voted in this poll
        if ( ! empty( $users_with_vote ) ) {
            if ( in_array( $user_id, $users_with_vote ) ) {                   // if logged-in user is in that list...
                $user_can_vote = false;                                       //  they can't vote again
                throw new Exception( esc_html__( 'You have already submitted a vote to this poll', 'forminator' ) );
            }
        }
    
        return $user_can_vote;
    }
    
    add_action( 'forminator_poll_after_handle_submit', 'wpmudev_record_user_poll_submission', 10, 2 );
    add_action( 'forminator_poll_after_save_entry', 'wpmudev_record_user_poll_submission', 10, 2 );
    function wpmudev_record_user_poll_submission( $module_id, $response ) {
    //    if ( $module_id != 230 ) { //Please change the poll ID
    //        return;
    //    }
    
        if ( is_user_logged_in() ) {
            $user_id = get_current_user_id();                                 // get user_id
            $option = get_option( $module_id.'_poll_users', array() );        // get array of those who have already voted in this poll
            array_push( $option, $user_id );                                  // add user_id to the array
            $updated_option = array_unique( $option );                        // update the array
            update_option( $module_id.'_poll_users', $updated_option );
        }
    }
    • I then embedded the short codes for the polls in this page:

    https://liveoakestateshoa.com/test-poll-page/

    Neither is rendered correctly.

    If I move my php file out of the mu-plugins directory, both render correctly.

    I’ve left the php file in the mu-plugins directory so you can see what happens.

    What additional information can I provide to help debug this?

    Thanks!

    Plugin Support Williams – WPMU DEV Support

    (@wpmudev-support8)

    Hi @loehoafaq

    Thanks for response!

    I checked the code and there seems to be two issues here:

    1. Apparently there’s small “inconsistency” happening due to the hook priority set so you would need to do a small change and in this line

    add_filter( 'forminator_poll_handle_form_user_can_vote', 'wmudev_check_user_submission_poll', 10, 2 );

    change number 10 to, for example, 99.

    With it the code will work as designed (at least it does in my tests).

    2. But the second issue may be, it seems, a misunderstanding on our end. The way it currently works is that (after above change) it does allow voting to logged-in users only but it does not hide the poll or give error message right away; it will only show it after you attempt to vote:

    – so poll shows up
    – you vote
    – if you are logged-in, your vote is registered or you get “you already voted” error (if you did vote already)
    – if you are not logged-in, after poll submission you get “you must be logged-in” message

    But if I’m getting it correctly, you would want that message to be showing up right away, before user is even able to try to submit the vote, right?

    I think this may require a bit different approach so I’ve asked our developers if they could adjust the code to achieve that and I’m awaiting their response.

    We’ll update you here soon with more information.

    Best regards,
    Adam

    Thread Starter loehoafaq

    (@loehoafaq)

    I can prevent non-registered users from voting by restricting rendering with [um_show_content =’ list of user roles’] as I’m doing on other pages. I didn’t because then you wouldn’t have been able to see it.

    Where in the database can I find the data showing which users have voted in any given poll? Perhaps that would be enlightening?

    Plugin Support Williams – WPMU DEV Support

    (@wpmudev-support8)

    Hi @loehoafaq

    Thanks for response!

    I actually got reply from our developers too already and to make it limited for logged-in users you would need to add following code additionally to the one that you are already using:

    add_filter( 'forminator_render_button_markup', 'wpmudev_change_poll_markup', 10, 2 );
    function wpmudev_change_poll_markup( $html, $button ) {
    
        if ( ! is_user_logged_in() ) {
            $html = '<br/><p>You must be logged in to vote in this poll.</p>';
        }
    
        return $html;
    }

    Simply add it at the end of existing code and it hsould do the trick.

    As for “which users voted”, with the code that you are using already the info about users (user ID) would be stored in the standard _options table of the site, under option name of

    xx_poll_users

    where xx is the number – an ID of the poll.

    Kind regards,
    Adam

    Thread Starter loehoafaq

    (@loehoafaq)

    That’s great. When not logged in, the user sees a message saying “You must be logged in to vote in this poll.” instead of the “Vote” button.

    Logged in users see the “Vote” button. If a user who hasn’t voted before clicks on the “Vote” button their vote is counted and the current results are displayed (which is how I configured this poll). If they have voted before they see instead “You have already submitted a vote to this poll” at the top of the poll.

    This achieves my goal of allowing only logged in users to vote, and then only once. It would be even better if the “You have already submitted a vote to this poll” could be displayed without the user having to make selections and submit the poll. Our website is for a homeowners association, and each household gets one vote on each issue. As a result, user IDs will be shared by spouses. Some of our polls will be quite long; if we told users they’d already vote before they start filling out the poll it could save them both time and annoyance when their spouse has already voted for their household.

    Might that be possible?

    Thread Starter loehoafaq

    (@loehoafaq)

    I found the xx_poll_users records in the wp_options table in the WordPress db. If I wanted to start a poll over, could I do this by deleting the corresponding record? Is there any other cleanup needed? Or can this be done from the WP admin interface?

    Are detailed results available, preferably in an anonymous but per-vote form, so we can export to a spreadsheet and do custom analysis?

    Is the schema for poll data available?

    Plugin Support Williams – WPMU DEV Support

    (@wpmudev-support8)

    Hi @loehoafaq

    Thanks for response and I’m glad it worked for you.

    As for the “You have submitted a vote” information

    It actually should be displayed right away, when the poll displays and it does that in my tests. But please try one thing:

    Previously I suggested changing priority in this part of the code

    add_filter( 'forminator_poll_handle_form_user_can_vote', 'wmudev_check_user_submission_poll', 10, 2 );

    to something like 99 but with the new code added it may no longer be necessary so try lowering it a bit again – test setting it back to 10 or even 9 and see if that sorts the issue.

    As for the xx_poll_users records

    You can delete them and they’ll be recreated. They don’t cary any additional information as they are create by that custom code and the only purpose is to identify if a given logged-in user already voted or not. Adding any additional information to that would require more complex code and, I’m afraid, would be out of scope of this support.

    However, if you have “Data storage” option for you poll set to have “Store Submission in Database” enabled (it’s in “Settings” section of each poll), poll voting would be saved in DB by plugin and you would see those submissions on “Forminator -> Submissions” page after you select relevant poll from the drop-down list on top.

    Once you got that, you can use “Export” option to export voting to CSV file which you can later import e.g. to Google Sheets or any similar software for further analysis.

    It doesn’t contain much information but it does contain dates of when the answers were given and answers themselves.

    Best regards,
    Adam

    Plugin Support Amin – WPMU DEV Support

    (@wpmudev-support2)

    Hello @loehoafaq ,

    We haven’t heard from you for over a week now, so it looks like you don’t have more questions for us.

    Feel free to re-open this topic if needed.

    Kind regards
    Kasia

Viewing 13 replies - 1 through 13 (of 13 total)
  • The topic ‘How can I restrict polls so each logged in user votes only once?’ is closed to new replies.