WordPress/WooCommerce - remove wp_count_posts call in wp-admin - wordpress

There's a call to wp_count_posts() on every page in wp-admin. I would think it should only happen on the product pages. Is there a way to disable the call on all pages but products? Our site has over 100,000 products, and this call slows down wp-admin pages.
The following is the caller log from Query Monitor
wp_count_posts()
wp-includes/post.php:2859
WC_Install::is_new_install()
wp-content/plugins/woocommerce/includes/class-wc-install.php:399
WC_Admin_Notices::init()
wp-content/plugins/woocommerce/includes/admin/class-wc-admin-notices.php:58
WC_Admin->includes()
wp-content/plugins/woocommerce/includes/admin/class-wc-admin.php:62
do_action('init')
wp-includes/plugin.php:470

Could you try the following. Add following function in your theme functions.php . All credits goes to - wordpress remove post status count from cms
I have edited $post_type where we want all post types and $exclude_post_types changed to product over page post type.
add_filter('bulk_post_updated_messages', 'suppress_counts', 10, 2);
// We need to let the function "pass through" the intended filter content, so accept the variable $bulk_messages
function suppress_counts($bulk_messages) {
// If the GET "post_type" is not set, then it's the "posts" type
$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : '';
// List any post types you would like to KEEP counts for in this array
$exclude_post_types = array('product');
// Global in the variable so we can modify it
global $locked_post_status;
// If the post type is not in the "Exclude" list, then set the $locked variable
if ( ! in_array($post_type, $exclude_post_types)) {
$locked_post_status = TRUE;
}
// Don't forget to return this so the filtered content still displays!
return $bulk_messages;
}

Related

auto generate post title in wordpress like ABC-123456

I want to auto-generate post title like that
Ex : ABC-123456
also i need to let (( ABC- )) fixed and random change the 06 numbers
and to dont change the post title through updating the post
First, to modify WordPress behavior the correct way, you find an appropriate hook. In this case, that would be a filter that allows changing the Post data before it is saved to the db.
The filter 'wp_insert_post_data' is exactly what you need, so you add your filter, and connect it to a function like so:
function zozson_filter_post_title(){
}
add_filter( 'wp_insert_post_data', 'zozson_filter_post_title',50,4);
'wp_insert_post_data' is the name of the filter
'zozson_filter_post_title' is the name you give to your function, to hook to it.
50 is the priority. I chose 50 to run it after most other things. Default is 10
4 is the number of variables that the filter passes to your function.
So now we will add those variables and the logic inside it, to assign these CPT sho7nat those titles on admin saving them.
function zozson_filter_post_title( $data, $postarr, $unsanitized_postarr, $update){
//Then if it is the post type sho7nat
if( $data['post_type'] !== 'sho7nat' ){
return $data;
}
//If there is already a titled saved ($update returns true always)
if( $data['post_title'] !== '' ){
return $data;
}
//Let's build our title
$post_title = ' ABC-';
//What better random number that a unique timestamp?
$random_number = strtotime('now');
//Add the random number to the post title to save. You can do these in 1 line instead of 3
$post_title.= $random_number;
//We now have a post title with ABC- fixed and a random number, tell WordPress to use it as the post title
$data['post_title'] = $post_title;
return $data;
}
add_filter( 'wp_insert_post_data', 'zozson_filter_post_title',50,4);
The title automatically assigned should be like in this example:

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 remove post status count from cms

I want to remove the post status count from WordPress edit.php.
My WordPress CMS have more than 500,000 posts. The publish count is loaded every time you open the page. The following query is fired every time.
This makes my Wordpress CMS loading very slow.
SELECT post_status, COUNT( * ) AS num_posts FROM wp_posts WHERE post_type = 'post' GROUP BY post_status
By tracing the code, I've worked up the only solution that I can see.
The filter bulk_post_updated_messages is ONLY called on the edit.php screen.
The counts are not calculated (in class-wp-posts-list-table.php, get_views method) if the global variable $locked_post_status is not empty.
By gluing these two pieces of information together, I've got a solution that you can use by dropping it into your theme's functions.php file:
// Hook this filter, only called on the `edit.php` screen.
// It's not the "correct" filter, but it's the only one we can leverage
// so we're hijacking it a bit.
add_filter('bulk_post_updated_messages', 'suppress_counts', 10, 2);
// We need to let the function "pass through" the intended filter content, so accept the variable $bulk_messages
function suppress_counts($bulk_messages) {
// If the GET "post_type" is not set, then it's the "posts" type
$post_type = (isset($_GET['post_type'])) ? $_GET['post_type'] : 'post';
// List any post types you would like to KEEP counts for in this array
$exclude_post_types = array('page');
// Global in the variable so we can modify it
global $locked_post_status;
// If the post type is not in the "Exclude" list, then set the $locked variable
if ( ! in_array($post_type, $exclude_post_types)) {
$locked_post_status = TRUE;
}
// Don't forget to return this so the filtered content still displays!
return $bulk_messages;
}
i came up with this solution.
//Disable Article Counter - query runs for about 1-2 seconds
add_filter('admin_init', function () {
foreach (get_post_types() as $type) {
$cache_key = _count_posts_cache_key($type, "readable");
$counts = array_fill_keys(get_post_stati(), 1);
wp_cache_set($cache_key, (object)$counts, 'counts');
}
}, -1);
add_action('admin_head', function () {
$css = '<style>';
$css .= '.subsubsub a .count { display: none; }';
$css .= '</style>';
echo $css;
});
the post counter uses the wp-cache, the idea behind this approach is, to prefill the cache with the "correct" object containing 1's (0 would skip the status from being clickable) - at the earliest moment.
it results in all stati being displayed - with 1's and the query is not run et-all
in addition it returns a css snippet to hide the (1)

Wordpress Private/Public Posts Security.

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

Auto-remove custom field with no value on publish

I got some plugins that auto-generates custom fields. Does anyone know how to automatically remove empty custom fields from post when I press "publish"?
A check I can put in my functions.php that does a check and removes the custom field if there is no value?
Here is the solution:
add_action('save_post','my_cf_check');
function my_cf_check($post_id) {
// verify this is not an auto save routine.
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;
//authentication checks
if (!current_user_can('edit_post', $post_id)) return;
//obtain custom field meta for this post
$custom_fields = get_post_custom($post_id);
if(!$custom_fields) return;
foreach($custom_fields as $key=>$custom_field):
//$custom_field is an array of values associated with $key - even if there is only one value.
//Filter to remove empty values.
//Be warned this will remove anything that casts as false, e.g. 0 or false
//- if you don't want this, specify a callback.
//See php documentation on array_filter
$values = array_filter($custom_field);
//After removing 'empty' fields, is array empty?
if(empty($values)):
delete_post_meta($post_id,$key); //Remove post's custom field
endif;
endforeach;
return;
}
wp_insert_post_data is a hook that happens before a database write in the admin panel. You can probably use that to call a function that checks for data, then strips out any empty custom field entries.
Or, you could use the_content hooks on the front end to strip out empty custom fields before they get displayed to the user.
Or, if you have control of the theme files, you can just test for data in your custom fields before displaying them.

Resources