Wordpress Private/Public Posts Security. - wordpress

I have a quick question to ask.
I've setup a wordpress site with custom theme that has the functionality to set posts "Private/Public" where as you can guess all post marked as private can only be seen by users who are logged in, and public everyone can see.
How I accomplished this was using a custom field "access" and each post can set this custom field to private or public in the edit post screen. Then to display these posts I run a custom loop query with a "is_user_logged_in()" conditional statement. It that statement is true I include all posts with the "access" fields set to both "private/public" and if the statement fails ie the user is not logged in only include posts with "access" set to public. I have used similar loop queries for all single page loops etc.
Now while this works a treat I have concerns over how secure this approach is. Thats were your help comes in. How secure do you think this is? Would it be easy to trick the loop into displaying private post to a user thats not logged in? Can you reccommed a better more secure way of handling private/public posts that can be set by a select number of users on the backend?
ideas much appreciated.
Rob.

maybe I understood all wrong , but -
What You describe is just like the wordpress Default behavior for private posts .
Hence , I do not really understand wh you need a custom field for that .
Custom Fields have the habit of being [ab]used for everything, even if not needed :-)
That being said ,you can use the post_status() function to check for your status
if ( get_post_status ( $ID ) == 'private' )
{
// this is 'private';
}
else
{
// this is public 'public';
}
So you could use
get_post_status ( get_the_ID() )
or if you want to put it at the head of the loop after the the_post() part:
if( get_post_status()=='private' ) continue;
you could wrap it also with is_user_logged_in() if you want .
Point is , there is already a default place in wordpress where "private" is defined . so there is no need to define it elsewhere ( like custom field ).
You can even create your own custom post status with register_post_status() ..
the best way IMHO however , is to filter all the posts on the posts_where
add_filter('posts_where', ' privates_control');
function privates_control($where) {
if( is_admin() ) return $where;
global $wpdb;
return " $where AND {$wpdb->posts}.post_status != 'private' "; // or add your custom status
}
This function simply mofifies the query using the posts_where filter. Codex Link
You can modify it to your needs (add / remove conditions / user levels / user control

Related

Save custom fields to user meta on WooCommerce Checkout for new user who is registering on checkout

I have added several custom fields to my checkout that only appear when a user is checking out as a guest for the first time. My checkout process requires that the user create an account to complete checkout.
I have added four fields using the woocommerce_form_field method and then I have tried modifying the code provided in the answer here to achieve what I want. However, I have tried several checkouts, creating new accounts to check if the custom field values save into the new users' profile, but it doesn't seem to be working.
Here is one example of a solution I tried which did not work:
function reigel_woocommerce_checkout_update_user_meta( $customer_id) {
if ( ! empty( $_POST['practitioner_license_number'] ) ) {
$pln = sanitize_text_field( $_POST['practitioner-license-number'] );
update_user_meta($customer_id, 'practitioner_license_number', $pln);
}
}
add_action('woocommerce_created_customer', 'reigel_woocommerce_checkout_update_user_meta', 10, 2);
practitioner-license-number is my custom field added using the woocommerce_form_field method. I modified the code at the link above, so that the function runs on woocommerce_created_customer and then in update_user_meta I'm trying to pass the customer ID so that it saves the meta to the user profile that is created.
Would appreciate help trying to solve this. Most of the questions/answers on this subject assume that the user is logged in and already has an account, which is not the case here.
From the code you share, I think the problem lies in incorrectly passing to the $_POST,
perhaps practitioner_license_number vs practitioner-license-number.
You can use the code below to see if your hook works, if the value is written in the database you know that the problem is indeed elsewhere.
It might help to share the code you used for the custom fields too?
function action_woocommerce_created_customer( $customer_id, $new_customer_data, $password_generated ) {
$pln = 'test';
update_user_meta( $customer_id, 'practitioner_license_number', $pln);
}
add_action( 'woocommerce_created_customer', 'action_woocommerce_created_customer', 10, 3 );

Id changing variable

I'm working on a project where I upload a file and use its path in a shortcode. Right now I've hard-coded the post's ID into my code but I want to make it dynamic so that new posts automatically get the correct shortcode.
<?php
global $wpdb;
$thepost = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = 5574" ) );
echo do_shortcode ('[sgpx gpx="'.'/wp-content/uploads/' . $thepost->meta_value . '"]');
?>
Going off of what #Damocles said, you are really setting yourself up for trouble with your current path. Instead, there are built-in WordPress functions that abstract away the database and utilize caching that you are strongly encouraged to use.
// Get the current WordPress post
$the_post = get_post();
//If we have a value (there are cases where this will be empty)
if($the_post){
// Get the value from the post meta table by the current post's ID
$the_post_meta = get_post_meta($the_post->ID, 'YOUR_META_KEY_HERE', true);
// Double-check that we have a value
if($the_post_meta) {
// Finally, echo the shortcode
echo do_shortcode ('[sgpx gpx="'.'/wp-content/uploads/' . $the_post_meta . '"]');
}
}
There are several ways to get the current post however get_post() is the most common. If you are in a custom loop, however, you might need to adjust accordingly.
To access the meta, use get_post_meta() which includes some optimizations including use a cache instead of the database.
Although there are definitely exceptions, generally speaking, if you are working with WordPress and you find yourself writing SQL statements, there is almost always a better, safer, faster, etc. way to do it using core functions.

Hide users with a specific role from users list on WordPress admin dashboard

I have two roles called Agent and Subagent.
I want to hide these two specific roles from the admin user list.
I tried using the pre_user_query filter but couldn't get it to work.
Could anyone please suggest a correct way to do it?
Thanks,
Simpler & safer:
add_filter('pre_get_users', function ($user_query) {
// use the sluglike role names, not their "display_name"s
$user_query->set('role__not_in', ['agent', 'subagent']);
});
role__not_in available since WP 4.4.
Caveat: the roles (and their user count) will still show up above the users table.
I found the perfect solution for what I wanted here: https://rudrastyh.com/wordpress/pre_user_query.html
add_action('pre_user_query','hide_all_agents_subagents');
function hide_all_agents_subagents( $u_query ) {
$current_user = wp_get_current_user();
if ( $current_user->roles[0] != 'administrator' ) {
global $wpdb;
$u_query->query_where = str_replace(
'WHERE 1=1',
"WHERE 1=1 AND {$wpdb->users}.ID IN (
SELECT {$wpdb->usermeta}.user_id FROM $wpdb->usermeta
WHERE {$wpdb->usermeta}.meta_key = '{$wpdb->prefix}capabilities'
AND {$wpdb->usermeta}.meta_value NOT LIKE '%agent%' AND {$wpdb->usermeta}.meta_value NOT LIKE '%subagent%')",
$u_query->query_where
);
}
}

stop wordpress search showing a custom post type

I have one custom post type I use for some text blocks on a page built using uncode theme. I need these blocks to be public so they display on the page but I want to stop them appearing in search results.
The search.php isn't like a normal wordpress search file, it is the uncode-theme file and doesn't have normal queries in I don't think so I'm thinking I need a function maybe?
Can anyone please advise how to achieve this?
The CPT is 'staticcontent'
Thanks!
The answer here depends on whether you're creating the CPT via your own code, or if another plugin is creating the CPT. See this link for a great explanation of both approaches:
http://www.webtipblog.com/exclude-custom-post-type-search-wordpress/
The basic gist is this:
If you're creating your own CPT, you can add an argument to the register_post_type() call of 'exclude_from_search' => true
If another plugin / theme is creating the CPT, you need to set this exclude_from_search variable later on, as part of a filter to the CPT, as such:
// functions.php
add_action( 'init', 'update_my_custom_type', 99 );
function update_my_custom_type() {
global $wp_post_types;
if ( post_type_exists( 'staticcontent' ) ) {
// exclude from search results
$wp_post_types['staticcontent']->exclude_from_search = true;
}
}
I don think accepted answer is correct. exclude_from_search prevents all $query = new WP_Query from returning results.
The core says:
...retrieves any type except revisions and types with
'exclude_from_search' set to TRUE)
This is a common problem and mixup with the front end search results page v.s. search posts in the database.
Presenting content using custom queries on front end, needs exclude_from_search = false or use another approach and get the content by id directly.
You need to filter the search front end mechanism instead. This is a true Exclude Post Types From Search, without manually re-build "known" types:
function entex_fn_remove_post_type_from_search_results($query){
/* check is front end main loop content */
if(is_admin() || !$query->is_main_query()) return;
/* check is search result query */
if($query->is_search()){
$post_type_to_remove = 'staticcontent';
/* get all searchable post types */
$searchable_post_types = get_post_types(array('exclude_from_search' => false));
/* make sure you got the proper results, and that your post type is in the results */
if(is_array($searchable_post_types) && in_array($post_type_to_remove, $searchable_post_types)){
/* remove the post type from the array */
unset( $searchable_post_types[ $post_type_to_remove ] );
/* set the query to the remaining searchable post types */
$query->set('post_type', $searchable_post_types);
}
}
}
add_action('pre_get_posts', 'entex_fn_remove_post_type_from_search_results');
And remark $post_type_to_remove = 'staticcontent'; can be changed to fit any other post type.
Please make a comment if Im missing something here, I cant find another way to prevent post type scenarios like this, showing content by query but hide from search/ direct access to front end users.
First of all, the answer by Jonas Lundman is correct and should be the accepted answer.
The exclude_from_search parameter does work incorrectly - it excludes the post type from other queries as well.
There is a ticket on WP issue tracking system, but they have closed it as wontfix because they cannot fix this without breaking the backwards compatibility. See this ticket and this one for more details.
I've added additional checks to the solution proposed by Jonas Lundman, because:
in real setups there can be other plugins trying to modify the search query, so simply replacing the post_type may cause unexpected results.
I think it's more flexible to use an array of post types to exclude.
add_action('pre_get_posts', 'remove_my_cpt_from_search_results');
function remove_my_cpt_from_search_results($query) {
if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
return $query;
}
// can exclude multiple post types, for ex. array('staticcontent', 'cpt2', 'cpt3')
$post_types_to_exclude = array('staticcontent');
if ($query->get('post_type')) {
$query_post_types = $query->get('post_type');
if (is_string($query_post_types)) {
$query_post_types = explode(',', $query_post_types);
}
} else {
$query_post_types = get_post_types(array('exclude_from_search' => false));
}
if (sizeof(array_intersect($query_post_types, $post_types_to_exclude))) {
$query->set('post_type', array_diff($query_post_types, $post_types_to_exclude));
}
return $query;
}

Wordpress: Change user role conditionally

I am creating a Wordpress website for multi author and want to set user role as per article submission. Means if any user have 0-10 article they will go to Contributor role, if 11-30 will go to Author role if 31-100 will go to Editor role.
Also I want to make registration system where default registration group will be Subscriber. They will get a link into verification email like
If you want to become a Contributor please click on below link. (To submit an article you must have at least Contributor permission)
http:// link will be here ... this link automatically change user role from Subscriber to Contributor.
Hope I will get solution from you expert. I am posting this issue with lots of hope from you friends.
What you want to do is when they post their submission check to see how many posts they have authored and then change the role. So in your theme's functions.php file you'd need a hook that is like this.
add_action('publish_post', 'update_roles');
and then a function to update the roles.
function update_roles()
{
global $wpdb;
// Get the author
$author = wp_get_current_user();
// Not sure if $author and $u are the same object I suspect they are.
// so this may not be necessary, but I found this code elsewhere.
// You may be able to do without this and just replace $u with $author later in the code.
// Get post by author
$posts = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_author = " . $author->ID );
$numPost = count($posts);
// Do the checks to see if they have the roles and if not update them.
if($numPost > 0 && $numposts <= 10 && current_user_can('subscriber'))
{
// Remove role
$author->remove_role( 'subscriber' );
// Add role
$author->add_role( 'contributor' );
}
...... other conditions .......
}
Using SQL statements (Database Queries) to get at Wordpress data is not in accordance with Wordpress coding standards . See Wordpress Handbook
It would be better to use count_user_posts function
See Function on the codex

Resources