I know this question is frequently asked on this forum, but none of the proposed solutions has worked for me, basically, I am a WordPress plugin developer and developing a plugin whose session starts in the init file but close when the client closes his/her browser, and it is necessary to keep the session open. In this case, how can I get rid of this warning? Maybe I should use something other than the session or what you suggest.
Till now there are different proposed solutions like Use
if ( !session_id() ) {
session_start( [
'read_and_close' => true,
] );
}
but with this technique, I can never be able to use sessions in my plugin, and the whole functionality goes on the ground.
Any help in this regard would be much appreciated.
thanks
WordPress plugin or theme developers cannot use php's session subsystem as you have discovered.
If you need to save some kind of global context for your plugin to work, use WordPress's add_option() function to save it at the end of each operation. You can retrieve your context using get_option().
If you need per-user context, use add_user_meta() to save it and get_user_meta() to retrieve it. Like this:
$id = get_current_user_id();
$myContext = get_user_meta( $id, 'my_plugins_meta_tag_name' );
...
add_user_meta( $id, 'my_plugins_meta_tag_name', $myContext);
WordPress uses a database table to store these sorts of options. Some sites put an object cache in front of the table. But these APIs are how you do what you want to do.
In your plugin's deactivation hook, please consider calling delete_option() to clean up that storage. And, if you use per-user context, please consider using delete_user_meta() to remove your user_meta item from all of them.
$users = get_users( array( 'fields' => array( 'ID' ) ) );
foreach($users as $user){
delete_user_meta ( $user->ID, 'my_plugins_meta_tag_name' );
}
As for sensitive information, WordPress offers no other place to put it. And, if you were using sessions, php would need to put it somewhere as well. By default, php puts session data in the filesystem of the server. That's why WordPress hashes user passwords before storing them.
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 am looking for some help concerning WordPress plugin development. My plugin queries an API which requires an Authentication Token, that token is fetched via a Token delivery APi. The token expire every 3600 seconds.
I would like to store the Token, in a persistent way (for all sessions , like server side caching) and update it only when needed. Multiple Api call could be done with the same token. The problem is, if I store the token in a global variable, it gets reset each time a user reload a page which uses my plugin.
https://wordpress.stackexchange.com/questions/89263/how-to-set-and-use-global-variables-or-why-not-to-use-them-at-all
After looking for answer I found:
-WP_CACHE , but it is not persistent.
-I know I can store the token in the Database, but a Token in Database is not a use case I found elegant
-Tool such as Redis Object Cache for PHP but I found it to be really complicated , installing etc...
Is there any good practice or easy way of doing this? I only need to keep a string for an hour and access it within the plugin in PHP.
Thank you.
https://wordpress.stackexchange.com/questions/89263/how-to-set-and-use-global-variables-or-why-not-to-use-them-at-all
In this case, I would work with WordPress transients:
https://developer.wordpress.org/reference/functions/set_transient/
https://developer.wordpress.org/reference/functions/get_transient/
To set a transient, you can use this code:
$transient = 'your_token_name';
$value = 'your_token'
$expiration = 3600
set_transient( $transient, $value, $expiration );
To receive the value of your transient again, you can use:
$token = get_transient( $transient );
Using these methods is better than update_option or get_option since WordPress manages the expiration (deletion) of transients completely, so you don't have to implement your own logic for this.
Before you pass the value to the transient method, you can encrypt and decrypt it by storing a salt/key in your wp-config.php. You can find more infos about this topic here:
http://php.net/manual/es/function.openssl-encrypt.php
http://php.net/manual/es/function.openssl-decrypt.php
To define a constant in WordPress you need to go to your wp-config.php file and add it between the "you can edit" words:
define( 'YOUR_SALT', '12345678' );
You can read it again as a normal constant in WordPress:
$salt = YOUR_SALT;
I have a need to change a plugin that creates/edits entries to the wp_posts table. Currently, it is lacking in that it cannot target some specific fields. I am endeavoring to edit the plugin so I can change these fields as well with the plugin. Specifics below.
How would I generally target this table then create/edit entries?
I have in mind something like this, which was copied from here.:
$my_post = array(
'post_title' => '#Enter the title#',
'post_content' => '#Enter the Content#',
'post_status' => 'publish',
'post_author' => 1
);
wp_insert_post( $my_post );
I assume this is possible because the plugin I'm hoping to change already makes changes to the wp_posts table. How do I do this? I have programming experience in C#, but my PHP and WP knowledge is severely lacking. I assume there's a few WordPress key functions that I'm looking for, but I simply don't know what they are or how to find them (I might be searching for the wrong terms). wp_insert_post() looks very promising, but the documentation seems to imply that it won't work for my specific needs.
Specifics
I'm using a great plugin called Really Simple CSV importer (RSC), which allows you to create/update posts with a csv. It seems to be able to target nearly every field (e.g. post_title, post_id, post_parent, post_content, _wp_page_template, etc.). This is quite a boon if you have to create hundreds of pages regularly (which I do).
The problem is that it won't target two specific fields, which are titled group_access and tag_list. I put those fields as columns in my csv, but they are not added to the mySQL database, and thus are not changed on the site. I believe these fields are specific to a plugin called iMember360, which is a plugin that ties into an InfusionSoft account.
Naturally, I've tried contacting RSC support, but have received no replies at all. I've spoken to iMember360 support at length, and the best they can give me without doing the work themselves is that they use the action hook import_end to make changes to the table, so if RSC is not using it, then it won't affect those fields. They also say that iMember360 has an import/export function, but it is only for the plugin's specific features, and ties in with the WordPress XML import/export feature. Clearly, this RSC plugin does not do that.
Regardless of these limitations, it seems to me like if the field exists in the table, then you should be able to edit it, so I tend to think that the RSC plugin is simply lacking in this functionality, probably only targeting WP default fields only.
What I've tried:
I have tried editing the plugin PHP directly, with the assumption that the plugin simply does not have an entry for the group_access and tag_list fields.
One of the PHP files contained:
// (string, comma separated) name of post tags
$post_tags = $h->get_data($this,$data,'post_tags');
if ($post_tags) {
$post['post_tags'] = $post_tags;
}
I simply copied and pasted it right above it and changed post_tags to group_access. It didn't work.
I also found, and added to:
$attachment = array(
'post_mime_type' => $mime_type ,
'post_parent' => $this->postid ,
'post_author' => $this->post->post_author ,
'post_title' => $title ,
'post_content' => $content ,
'post_excerpt' => $excerpt ,
'post_status' => 'inherit',
'menu_order' => $this->media_count + 1,
////////// added
'group_access' => $group_access ,
'tag_list' => $tag_list ,
//////
);
That didn't do anything either.
There are two ways to edit the wp_posts table that I know of. The first is with the wp_update_post() and wp_insert_post() functions. These are typical WP functions that are used like any others. You just have to pass the correct parameters. For example:
$my_post = array(
'ID' => $updatePostID, // User defined variable; the post id you want to update.
'post_title' => 'Update Title',
'post_content' => 'Update Content',
);
// Update the post into the database
$post_id = wp_update_post( $my_post, true ); // Returns 0 if no error; returns post id if there was an error.
// Check if table was updated without error. For debugging. Remove from your code if it all works, before publishing.
if (is_wp_error($post_id)) {
$errors = $post_id->get_error_messages();
foreach ($errors as $error) {
echo $error;
}
}
Simply pass an array with the predefined field names to the functions and they will then run correctly. The update function is for updates, naturally, and the insert function creates new table entries (rows). There is a limitation, however. These two functions will only operate on the WP predefined fields. So, if your table contains some custom fields, then you will have to use the $wpdb class.
The other way to update your mySQL tables from WordPress is to use the $wpdb class directly. This class is far more expansive than the wp_update_post() and wp_insert_post() functions. The first difference is that it can edit many other mySQL tables, not just the wp_posts table. It can also edit non-WP fields. For example:
global $wpdb; // This calls the use of the class. I actually do not think this is necessary, but I do it anyway.
$dbresult = $wpdb->update($wpdb->posts, // Returns 0 if no errors. Post ID if errors occurred.
// Notice posts instead of wp-posts. Prefixes are not necessary with this class.
['post_title' => 'Update Title',
'post_content' => 'Update Content',
'custom_field' => $customField, ], // User defined table column and variable.
['ID' => $updatePostID, ]); // User defined variable; the post id.
if (false === $dbresult) {
echo 'An error occurred while updating...';
$errors = $post_id->get_error_messages();
}
I'm not very familiar with either of these options, but there seems to a massive difference in the width of functionality, so there may be considerations you should take before using one over the other. I've asked a question to that end: https://wordpress.stackexchange.com/q/259043/38365 One reply says:
Downsides of $wpdb are that you do need to know SQL and you need to be conscious of normal data sanitization and when to use prepare() and what functions already prepare your statement which are hardly downsides at all. The $wpdb Class is by nature more powerful than any of the default WordPress functions because you have access to all the data, custom or not, assuming you know the proper SQL to get, modify, or remove it.
TL;DR $wpdb is more powerful but less friendly and forgiving.
That makes sense to me. Basically, don't fiddle with $wpdb unless you know what you are doing or absolutely have to.
I'm currently trying to get a custom component working to log a user into the backend given their username and password. I realize the inherent security problems this may present, but I would really like an answer to this problem I've been struggling with. Here is the code in my controller.php:
function execute() {
$credentials = array( 'username' => $this->username,
'password' => $this->password );
$options = array();
$options['group'] = 'Public Backend';
$options['autoregister'] = false;
$options['action'] = 'core.login.admin';
$app =& JFactory::getApplication('administrator');
$result = $app->login($credentials, $options);
echo $result;
}
All the documentation that I've read says that this should work (even though it is not exactly kosher to perform admin tasks--like logging into the backend--from a non-admin context). Any idea on what I'm not getting?
EDIT: I forgot to mention which Joomla version I'm using: 2.5.14
I think you need to pay attention to the Joomla authentication/login/authorization flow and user flow which are managed via user and authentication plugins. From what you say it sounds like you will still be using the Joomla user table, is that right? So in that case the Joomla user plugin should work.
Assuming that is true you want to make an authentication plugin. This plugin will be checked along with the joomla authentication plugin and any other authentication plugins you may have running (e.g. remember me/cookie login).
I don't totally understand what you are trying to do (and you haven't said what version of Joomla you are on, which makes a difference in this case), for example do you really want to login to the full back end or do you just want to show some screens the way the insert image plugin does? If on Joomla 3 you might want to look at the Google Summer of Code project for bringing some admin to the front end (called com_services for now). That student also has an http login plugin you could look at. https://github.com/Buddhima/Joomla-HttpLogin-plugin
I am trying to develop a small web shop with CodeIgniter. To store the items, I use the Cart library. Most of the time, everything works great. However, sometimes the content of the cart gets lost after a redirect.
I found a couple of fixes on the web, but none of them works in my case. Here is my setup:
I use the DB for storing sessions
I don't use AJAX
There is no underscore in the name of the session cookie
Here is an example of a refresh:
public function add_item() {
$item_id = $this->input->post('item');
// Query database
$item = $this->model->find_item($item_id);
// Rewrite model info
...
$data = array(
'id' => 'item-' . $item['id'] . '-size-' . $item['sizes'][$i]['id'],
'qty' => $qty,
'price' => $item['sizes'][$i]['price'],
'name' => $item['name'],
'options' => array('short_name' => $item['short_name'])
);
$this->cart->insert($data);
usleep(10000);
redirect('shop');
}
I finally found an answer to my problem, thanks to this question: CodeIgniter Cart and Session lost when refresh page
The problem was that the data stored in the session got too big. CodeIgniter stores all the data in a cookie, which is limited to 4kB. My mistake was to think that, if I used the DB to store my sessions, I could avoid that limit. Apparently, CodeIgniter saves sessions in the database "only" for security reasons. There is still a lot of data in the cookie.
Now, I use a library called Native session. I found it here: https://github.com/EllisLab/CodeIgniter/wiki/Native-session
I just put the file in 'application/libraries', renamed the first function to '__construct()', added it to autoimport and replaced all the 'session' tags with 'native_session' in my code. I also had to change the Cart class because it was using CodeIgniter's original session.