Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I hidden some pages using 'parse_query' hook, but the count for 'Published' pages didn't changed... Where I should hook to change it?

Update the page status count in admin

My code so far:

$query->query_vars['post__not_in'] = array(4);
share|improve this question
1  
Can you please throw some more explanation please? At least for other members of the site! –  sri Apr 1 at 9:19
    
As you can see there are 16 pages, published 15 and private 1. oi57.tinypic.com/2enw30h.jpg I hidden some pages but this counter is the same, it should be published 14 pages, because I hidden one page with ID 4. –  user1139767 Apr 1 at 9:42

2 Answers 2

up vote 1 down vote accepted

Yes, the count for pages in various statuses that you see above the list table is obtained running wp_count_posts but the pages in the table are obtained running a WP_Query and the 2 things are completely unrelated.

If you want to also modify the count, you have to filter also the output of wp_count_posts using the 'wp_count_posts' filter hook.

Also you should check the status of the page(s) you want to exclude from edit, because wp_count_posts count all the statuses separately.

So we have 2 tasks:

  • remove the pages from the query
  • remove the pages from the count

I'll write 2 functions, for the 2 tasks, and in both I need to check if we are in admin and if the current user has the needed capability and finally if the current screen is the right one. I'll write an addtional function that does these checks, to avoid writing same code 2 times:

function in_pages_edit() {
  if ( ! is_admin() || ! current_user_can( 'edit_pages' ) ) return FALSE; 
  $s = get_current_screen();
  return ( $s instanceof WP_Screen && $s->id === 'edit-page' );
}

Now we can add the 2 hooks for out 2 tasks, I'll add these 2 hooks inside a 'load-edit.php' action:

function go_exclude_pages_from_edit() {
  if ( ! in_pages_edit() ) return;
  global $exclude_pages_from_edit;
  $exclude_pages_from_edit = array( 662 ); // <-- set here the page ids to exclude
  add_filter( 'wp_count_posts', 'change_pages_count', 10, 3 );
  add_action( 'pre_get_posts', 'exclude_pages_from_edit' );
}

add_action( 'load-edit.php', 'go_exclude_pages_from_edit' );

Now we can remove the pages from being queried:

function exclude_pages_from_edit( $query ) {
  if ( ! in_pages_edit() || ! $query->is_main_query() ) return;
  global $exclude_pages_from_edit;
  if ( ! empty($exclude_pages_from_edit) ) {
    $query->set( 'post__not_in', $exclude_pages_from_edit );
  }
}

and adjust the counts (see inline comments for explaination):

function get_valid_page_from_post( $p ) {
  if ( $p instanceof WP_Post &&  $p->post_type === 'page' ) return $p;
}

function change_pages_count( $counts, $type, $perm  ) {
  // do nothing if not on right page
  if ( ! in_pages_edit() || $type !== 'page' ) return $counts;
  // do the work only once
  static $new_counts;
  if ( ! is_null( $new_counts ) ) return $new_counts;
  global $exclude_pages_from_edit;
  // get the pages objects and be sure they are valid pages
  $excluded = array_filter(
    array_map( 'get_post', $exclude_pages_from_edit ), 'get_valid_page_from_post'
  );
  // if no page object obtained do nothing
  if ( empty( $excluded ) ) return $counts;
  // count the statuses of the page objectt
  $statuses_excluded = array_count_values ( wp_list_pluck( $excluded, 'post_status' ) );
  // subtract from each status count the excluded pages status count
  foreach ( $statuses_excluded as $status => $num ) {
    if ( isset( $counts->$status ) ) {
      $counts->$status = (string) $counts->$status - $num;
    }       
  }
  // save the ajusted count for next running and return
  $new_counts = $counts;
  return $counts;
}
share|improve this answer
    
I got error: Parse error: syntax error, unexpected T_FUNCTION in this line: $excluded = array_filter( array_map( 'get_post', $exclude_pages_from_edit ), function($p){ if ( ! empty($p) && $p->post_type === 'page' ) return $p; } ); –  user1139767 Apr 1 at 10:34
    
Thank you G.M what would be changes for being 5.2 compatible? Because I dont have permissions to update php ... –  user1139767 Apr 1 at 10:41
1  
@user1139767 I've updated the answer, now is 5.2 compatible. –  G. M. Apr 1 at 10:42
    
Thank you it worked like a charm! –  user1139767 Apr 1 at 10:48

The post count uses the wp_count_posts() function, which ignores any query filters. You'll need to tweak it manually with the use of the wp_count_posts filter:

function wpse_139851_count_posts( $counts, $type ) {
    if ( $type === 'page' && ! empty( $counts->publish ) )
        $counts->publish--; // Decrease by 1
    return $counts; 
}

add_filter( 'wp_count_posts', 'wpse_139851_count_posts', 10, 2 );
share|improve this answer
    
Thanks for fast reply. But I tried and got error: Fatal error: Cannot use object of type stdClass as array in –  user1139767 Apr 1 at 10:38
1  
@user1139767 My bad - $counts is an object not an array. –  TheDeadMedic Apr 1 at 10:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.