I'm currently trying my hands on WordPress plugind developement for an exercise and came across some little snag.
The plugin is designed to display a simple poll in a widget on the front page. Once the visitor has voted, I use setcookie to drop a cookie containing his vote for 30 days, and some simple code to change the widget so that it shows the results and the user cannot vote again until a new poll is proposed. The problem is, voting is still possible, the results are never shown. Looking at the logs with the developer's tools, I found that the cookie is deleted the second it lands on the client browser. Does anybody know why, and how I can correct that?
Here's the code. First, the action hook:
public function __construct()
{
parent::__construct('poll_plugin', __('Polls', 'poll_plugin'), array('description' => __('Simple poll widget', 'poll_plugin')));
add_action('init', array($this, 'save_votes'));
}
Then, the actual action:
public function save_votes()
{
global $wpdb;
/*Cookie setting, 30 days expiration */
if ( isset($_POST['option']) && !isset($_COOKIE['Poll_Votes']))
{
unset($_COOKIE['Poll_Votes']);
setcookie('Poll_Votes', $choix, 30 * DAYS_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN);
$choix = $_POST['option'];
$id_choix = $wpdb->get_var("SELECT id FROM {$wpdb->prefix}poll_options WHERE label = '$choix'");
$wpdb->query("UPDATE {$wpdb->prefix}poll_results SET total = total+1 WHERE option_id = '$id_choix'");
};
/*Testing the presence of a new poll */
$vote = $_COOKIE['Poll_Votes'];
/*If the cookie's value isn't found in the db, the poll's changed, so we reset the cookie*/
if (is_null($wpdb->get_var("SELECT * FROM {$wpdb->prefix}poll_options WHERE label = '$vote'")))
{
setcookie('Poll_Votes', '', time()-3600);
}
}
Quick note here, I already tried commenting the line designed to unset the cookie, it changed nothing.
The only other time where the cookie is mentioned is via the $_COOKIE global, in a isset().
And lastly, please forgive my english, I'm french :)
Related
i want to set a cookie if a specified form (Contact Form 7) was sent.
If is write the code into the init-call it works:
function process_post() {
if( isset( $_POST['kampagne'] ) ) {
setcookie('cid', get_option( 'cf7-counter', 0) + 1 , time()+3600, '/');
}
}
add_action( 'init', 'process_post' );
But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.
So I want to set the cookie in the "wpcf7_before_send_mail" hook. But within that the cookie will not generate.
function wpcf7_do_something($WPCF7_ContactForm)
{
$submission = WPCF7_Submission :: get_instance();
if ( $submission ){
$posted_data = $submission->get_posted_data();
if ( empty( $posted_data ) ){ return; }
$changed_name = get_option( 'cf7-counter', 0) + 1;
update_option('cf7-counter', $changed_name);
$mail = $WPCF7_ContactForm->prop( 'mail' );
$new_mail = str_replace( '[cf7-counter]', '00'. $changed_name .'', $mail );
$WPCF7_ContactForm->set_properties( array( 'mail' => $new_mail ) );
return $WPCF7_ContactForm;
}
}
add_action("wpcf7_before_send_mail", "wpcf7_do_something");
I hope you can help me.
Thank you very much!
Best regards.
But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.
So what you need is the ID that will be stored into the database when creating the cookie.
Create it
if( isset( $_POST['kampagne'] ) ) {
$cookie = 'cid';
$id = uniqid("cid:", true);
setcookie($cookie, $id, $_SERVER['REQUEST_TIME'] + HOUR_IN_SECONDS, '/', ini_get('session.cookie_domain'), (bool)ini_get('session.cookie_secure'), (bool)ini_get('session.cookie_httponly'));
$_COOKIE[$cookie] = $id;
}
; and store it
$cookie = 'cid';
$WPCF7_ContactForm->set_properties(
[
'mail' => $new_mail,
'cid' => $_COOKIE[$cookie],
]
);
.
The contact form transaction now has the id that is in the cookie.
It is independent to get_option( 'cf7-counter', 0) by binding the submission to its own identifier - like the cookie is not the cf7-counter option.
Take note on explicitly setting $_COOKIE[$cookie] = $id;, always. This is to have the ID in the request itself.
Take double note on this action, as the code does set the cookie with a new ID even if it was already set. If that is not your intention, check if the cookie is unset beforehand (later references on setting a cookie in Wordpress have it, too).
It is now more eventually consistent, up to the level of uniqueness of the uniquid() function (study it if you want to make use of it), which is an improvement over the situation where the chance of being inconsistent was much higher (that is when using the cf7-counter option).
An insecure random-unique ID normally is enough for short term transaction tagging, e.g. having it for an hour in the cookie.
Which is something you may want to put more of your attention to. And the example is less Wordpress specific, there is more to get from in Wordpress like nonces, keys, salts, cookie-paths, user-level cookies etc. pp. to adhere to that system specifically.
It requires you to study Wordpress first, which I can't take of your shoulders, and there is even more to learn first, like how cookies work. Perhaps ask the more general questions first that you have to close such gaps.
Another answer I was thinking about first is to take a more fitting action so that you have the id the moment you can do both: setting the cookie and storing to the database.
As it has been commented, such a solution would need to find the right place in time. But that is merely how cookies work.
(And not specifically Wordpress.)
As you have already seen yourself, the action you wanted to use did not work.
And even if you would find such another action, this is still Wordpress, and it would be unpredictable that it would suffice: The cookie might be set in your tests, but not when a user visits the site (or any site that is out there with Contact Form 7 which this answer should answer if it is worth it).
To set a cookie in Wordpress, there is no free choice of the action to do it in, but it first of all needs to set the cookie for which the action is invariant:
How to set a cookie in Wordpress
Setting a redirect cookie in wordpress
As the action is set in stone to set a cookie, this goes back to the answer above.
However this is not Wordpress SE, but Stackoverflow so I've put the focus more on the PHP code itself where it relates to the PHP configuration and only HOUR_IN_SECONDS is a constant from Wordpress in it. See as well my comment on it about more specific Wordpress features you may want to add to it.
It hopefully answers your question to the level you need it.
I have adopted a CakePhp 2 project. We get to the project from another project, linking to the CakePhp project with a "token" and a conference ID as a parameter in the URL. Using that token, we authorize the user, and using the conference ID get the information from the database. The session value "auth" is set to true.
We have it running on 2 "platforms" locally on my system using a vagrant machine, and on a production server. Locally the session value dies really quick and at random times. On the production server not as often, but the issues we have where Ajax calls don't seem to do what are expected, we believe are being caused by a similar issue. We have many different projects, all Laravel, with zero issues where the session values clear. This issue is strictly with the CakePhp project.
All the authentication magic happens in the beforeFilter method. The code:
public function beforeFilter() {
$session = new CakeSession();
/**
*
* We will check if the current user is authorized here!
*
*/
// If the visitor is coming for the first time, there should be a parameter in
// the URL that is the auth code to check against the database.
if ( ( isset($_GET['conf']) && is_numeric($_GET['conf']) ) && isset($_GET['token']) ) {
$getConference = ClassRegistry::init('Conference')->find('first', ["conditions" => ["conference_id"=>$_GET['conf'] ]]);
$checkToken = ClassRegistry::init('User')->find('first', ["conditions" => ["remember_token"=>$_GET['token'] ]]);
if ($getConference && $checkToken) {
$checkToken['User']['remember_token'] = $this->generateToken();
if ( ClassRegistry::init('User')->save( $checkToken ) ) {
$session->write('auth', true);
$session->write('conferenceId', $_GET['conf']);
$this->redirect('/');
}
}
else {
$session->write('auth', false);
$session->write('conferenceId', null);
}
}
if (! $session->read('auth') || $session->read('conferenceId') == null ) {
echo "No permission!";
exit;
}
}
At the top of the controller:
App::uses('CakeSession', 'Model/Datasource');
When the URL parameters are present, it traps them, does the work, and redirects to the home route without the parameters.
$this->generateToken();
Creates a new token, and overwrites the old one in the database.
There are 2 main controllers. The controller with this code is the main projects controller. The only time it is really hit is the first time you go to the project, and we hit the index method. From there everything else is AJAX calls to the other controller. There is one link, a "home" type link that will hit that index method.
Sometimes these Ajax calls stop working, and clicking that home link will output "No Permission" instead of the expected html in the container the Ajax call outputs too.
Steps to troubleshoot led me to putting this beforeFilter method on the top of the second controller. Now, randomly I'll get no permission. Sometimes, when I'm on the main project that links to this CakePhp project, I click that link, I get no permission right off the bat.
I found this page: cakephp takes me to login page on multiple request and have tried to set the session details like this:
Configure::write('Session', array(
'defaults' => 'php',
'timeout' => '300' // <- added this element
));
And I have tried:
Configure::write('Session.timeout', '300');
Additionally, I have tried cookieTimeout in both of those cases.
I've also tried
Configure::write('Security.level', 'low');
and included
Configure::write('Session.autoRegenerate', true);
In any order, any of these cause the session to bomb out immediately. I get "No permission on page load, and never get anywhere.
The code for this project is honestly crap. The developer who wrote it had mistakes and errors all over the place. On top of that, we are a Laravel shop. We are just trying to keep the project limping along until sometime in the future when we can nuke it from orbit. So we just need to get this working. Any thoughts on what could be causing this? Any other details I am forgetting to include that would help troubleshoot this issue?
Thanks
Reading & writing session data
You can read values from the session using Set::classicExtract() compatible syntax:
CakeSession::read('Config.language');
$key should be the dot separated path you wish to write $value to:
CakeSession::write('Config.language', 'eng');
When you need to delete data from the session, you can use delete:
CakeSession::delete('Config.language');
You should also see the documentation on Sessions and SessionHelper for how to access Session data in the controller and view.
I have a social networking site built on a PHP framework. I'm using a plugin to award members points when they update their profile. Right now, whenever a member clicks on 'Save' it triggers the profileupdate event, and that event triggers the points being awarded. But, even if the profile fields are all empty, the event is still triggered and they still get points… so, my clever users are gaming the system to get points without really updating their profile :\
I want to add a function that checks that the profile fields aren't empty -- or, ideally, checks that a significant amount of changes have been made to at least 1 of the profile fields, but I'm not sure how to do that.
I'm still pretty new to PHP (about 1 year experience), so if anyone could help both with explaining what the checking process should be and the specifics on the code to execute the checking function, I'd really appreciate it!
Here are the current events and functions:
When the owner of the page clicks on 'Save', this is the event in the core of the PHP framework that gets triggered to notify the user of the update:
$owner->save();
trigger_event('profileupdate', $owner->type, $owner);
system_message(echo("profile:saved"));
This is the function in the points plugin that checks to see if the plugin is configured to award points based on a profile update, and then calls the points_add function to add points to the user:
function points_profile($event, $type, $object) {
if ($points = get_plugin_setting('profileupdate')) {
if (function_exists('points_add')) {
points_add(get_logged_in_user_guid(), $points, $event, $type, $object->entity_guid);
}
}
return(true);
}
This is an example of how the individual profile fields are defined/labelled -- ie, "admin_defined_profile_1"
if (save_config("admin_defined_profile_$id", $label) &&
save_config("admin_defined_profile_type_$id", $type) &&
save_config('profile_custom_fields', $fieldlist))
look on rowcount() http://www.php.net/manual/en/pdostatement.rowcount.php
it will -on single UPDATE -return 1 if anything was actually changed and 0 if nothing was changed.
Hi I am pretty new to wordpress,php and all this editing thing. I want to add a new cookie to wordpress upon authentication with name "xxx" and value "(currentusername)". I already read http://wptheming.com/2011/04/set-a-cookie-in-wordpress/ . I add the required code to the functions.php of my code however I don't know how to invoke it such that the currentusername logginned is added to the cookie.
Thanks in advance
Here is the code on the other website which I inserted in my functions.php
function set_newuser_cookie() {
if (!isset($_COOKIE['sitename_newvisitor'])) {
setcookie('sitename_newvisitor', 1, time()+1209600, COOKIEPATH, COOKIE_DOMAIN, false);
}
}
add_action( 'init', 'set_newuser_cookie');
Bumped into this one - I recommend against adding a new cookie, instead I would hijack (take advantage of) the current cookie and let WP manage it for you. Additionally the hooks available in WP allow very clean and tight code using WP features - try the snippet below - I put in comments and tried to be verbose :
function custom_set_newuser_cookie() {
// re: http://codex.wordpress.org/Function_Reference/get_currentuserinfo
if(!isset($_COOKIE)){ // cookie should be set, make sure
return false;
}
global $current_user; // gain scope
get_currentuserinfo(); // get info on the user
if (!$current_user->user_login){ // validate
return false;
}
setcookie('sitename_newvisitor', $current_user->user_login, time()+1209600, COOKIEPATH, COOKIE_DOMAIN, false); // change as needed
}
// http://codex.wordpress.org/Plugin_API/Action_Reference/wp_login
add_action('wp_login', 'custom_set_newuser_cookie'); // will trigger on login w/creation of auth cookie
/**
To print this out
if (isset($_COOKIE['sitename_newvisitor'])) echo 'Hello '.$_COOKIE['sitename_newvisitor'].', how are you?';
*/
And yes, use functions.php for this code. Good luck.
I am trying to set a custom cookie when a visitor submits a comment, but I can not seem to get this working. Here's what I have in functions.php:
add_action('comment_post', 'ipro_set_comment_cookie');
function ipro_set_comment_cookie($comment) {
setcookie("visitor_name", $comment->comment_author, time()+86400);
setcookie("visitor_email", $comment->comment_author_email, time()+86400);
}
I've also tried changing comment_post to wp_insert_comment- neither have seemed to work. I am working off of WP's action references:
http://codex.wordpress.org/Plugin_API/Action_Reference#Comment.2C_Ping.2C_and_Trackback_Actions
...any ideas?
Check out the Database writes in the Filter Reference
Try something like comment_save_pre
applied to the comment data just prior to updating/editing comment data. Function arguments: comment data array, with indices "comment_post_ID", "comment_author", "comment_author_email", "comment_author_url", "comment_content", "comment_type", and "user_ID".
That way it sets on submit (so it calls after your error handling kicks in)
If I understand your question correctly, this should work:
add_action('comment_save_pre', 'ipro_set_comment_cookie');
function ipro_set_comment_cookie($comment) {
setcookie("visitor_name", $comment->comment_author, time()+86400);
setcookie("visitor_email", $comment->comment_author_email, time()+86400);
}