Search code examples
phpwordpresscustomization

filter default query to show just selected level of child pages in wordpress


I'm working on a site that has a fairly large page structure a few levels deep - in some sections there are a lot of pages.

So I want to have functionality if user choose on select box level 1 then only pages in level 1 will show in below list of pages.
if he choose level 2 then only level 2 pages, same go to level 3 level 4 level 5 level 6.

it's working for top level parent pages when I set query_vars['post_parent'] = 0; and I want to have same functionality to show list of level 1 child page,level 2 child pages and so on...

I am stuck on it. please I will be great full if anyone can help me for it. Thanks
see screenshot link
https://i.sstatic.net/EKpy6.png

function level_page_admin_posts_filter( $query ) {
  global $pagenow;
  if ( is_admin() && $pagenow == 'edit.php' && !empty($_GET['lavel_pages'])) {
      $level = $_GET['lavel_pages'];
      if($level == 'parent'){
        $query->query_vars['post_parent'] = 0;
      }else 
      if($level == 1){

      }else
      if($level == 2){

      }
  }
}
add_filter( 'parse_query', 'level_page_admin_posts_filter' );

function admin_page_filter_level_pages() {
  global $wpdb;
  if (isset($_GET['post_type']) && $_GET['post_type'] == 'page') {
  
  $select = '
    <select name="lavel_pages">
      <option value="parent">Parent Pages</option>
      <option value="1">Level 1</option>
      <option value="2">Level 2</option>
      <option value="3">Level 3</option>
      <option value="4">Level 4</option>
      ';
  
  $select .= ' </select>';
  echo $select;
} else {
  return;
}
}
add_action( 'restrict_manage_posts', 'admin_page_filter_level_pages' );

Solution

  • It is possible if we get all the pages and work out what level each page is on and then filter the query using "post__in". Try the following:

    //recursive function to get page level, function returns when parent page is zero
    function level_page_admin_get_level($parentIds, $pageId, $level)
    {
      $parentId = $parentIds[$pageId];
      if($parentId>0)
      {
        $level++;
        return level_page_admin_get_level($parentIds, $parentId, $level);
      }
      return $level;
    }
    
    function level_page_admin_posts_filter($query)
    {
      global $pagenow;
      if(is_admin() && $pagenow == 'edit.php' && !empty($_GET['lavel_pages']))
      {
        $level = $_GET['lavel_pages'];
        if($level == 'parent')
        {
          $query->query_vars['post_parent'] = 0;
        }
        else
        {
          //get all the pages
          $pages = get_pages();
    
          //loop all the pages and store the parent id
          $parentIds = array();
          foreach($pages as $page)
          {
            $parentIds[$page->ID] = $page->post_parent;
          }
    
          //second time loop through all the pages this time call recursive function to get level
          foreach($pages as $page)
          {
            if($page->post_parent>0)
            {
              $pageLevels[$page->ID] = level_page_admin_get_level($parentIds, $page->ID, 0);
            }
          }
    
          //build array of only page ids on level
          $pageIds = array();
          foreach($pageLevels as $pageId => $pageLevel)
          {
            if($pageLevel==$level)
            {
              $pageIds[] = $pageId;
            }
          }
    
          if(!empty($pageIds))
          {
            //limit query to those page ids
            $query->query_vars['post__in'] = $pageIds;
          }
        }
      }
    }