0

I have a mess of code that works, however I know its a mess and im sure there is a neater way of doing this.

I am trying to get the child category to display under the parent category and for the post count to also show.

the problem is I only want the category to show if post are in the category and only show categories that have post for the current post type.

My code is working buy is a mess, dose anyone know how to clean this up and make it more efficient ?

        <script>
      
        attrs = $( 'body' ).attr( 'class' ).split( ' ' );
        jQuery( attrs ).each(function() {

            if ( 'post-type-' === this.substr( 0, 10 ) ) {
                postType = this.split( 'post-type-' );
                postType = postType[ postType.length - 1 ];
                return;
            }

        });
        
        postType = postType.replace('archive-', '');
        
    var post_id = postType;

});
  </script>
  <aside class="sidebar">
                 <div class="widget widget-filter">
                     <button class="widget-title">Explore Topics</button>
                     <svg class="separator" viewBox="0 0 238 11" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
                <line opacity="0.3" y1="0.5" x2="101.942" y2="0.5" stroke="#3CD5AF"></line>
                <line opacity="0.3" y1="10.5" x2="237.5" y2="10.5" stroke="#3CD5AF"></line>
              </svg>
<?php


$string = basename($wp->request); ;
$string = str_replace('-', '_', $string);

$new_string = $string;
// echo $new_string;

 $args = array(
                    'post_type'      => $new_string,
                    'post_status'    => 'publish',
                );

    $the_query = new WP_Query( $args );
    $my_categories = array();
    if ( $the_query->have_posts() ) {
        while ( $the_query->have_posts() ) {
            $the_query->the_post();
               $postType = get_queried_object();

            $terms = get_the_terms( get_the_ID(), 'category' );
            if ( $terms && ! is_wp_error( $terms ) ) : 
                foreach ( $terms as $term ) {
                if(!in_array($term->term_id, $my_categories))
                    $my_categories[] = $term->term_id;
                }   
            endif;  
        }
        wp_reset_postdata();
    }

    if(sizeof($my_categories)) { ?>

     <ul class="filter-list">
             <li :class="category == 0 ? 'parent' : ''" ;>
      <a class="" @click="filterPosts">Show All</a>
      
      <?php
 


$args = array(
  'cat' => $category_id,
  'post_type' => $new_string,
);

 
?>
      </li>
      
  
         <?php foreach ($my_categories as $term_id) {
            $category = get_term_by('id', $term_id, 'category');
        
            if($category->slug!="all-articles") {
                if($category->parent != 0){ // If this is a subcategory

$args = array(
    'numberposts' => -1,
    'category' => $category->term_id,
    'post_type' => $new_string,
);
$count_posts = get_posts( $args );
$total_posts_child = count($count_posts);


  ?>
          <li :class="category == <?php echo $category->term_id; ?> ? 'child' : ''" ;>
                     <a class="child" @click="filterPosts(<?= $category->term_id; ?>)"><?= esc_html( $category->name ); echo "". "(" .$total_posts_child . ")"; ?></a>
                </li> <?php
    
    } else {
   
                
                $args = array(
    'numberposts' => -1,
    'category' => $category->term_id,
    'post_type' => $new_string,
);
$count_posts = get_posts( $args );
$total_posts_parent = count($count_posts);

 ?>
      <li :class="category == <?php echo $category->term_id; ?> ? 'parent' : ''" ;>
                     <a class="parent" @click="filterPosts(<?= $category->term_id; ?>)"><?= esc_html( $category->name); echo "". "(" .$total_posts_parent . ")" ?></a>
                </li>   <?php
    }
          
            }
        }
    }
    ?>
    </ul>
 
    </div>
    </aside>
 





     
  
  
 PS reason I am getting post type from html using Jquery is due to the wider project is a ajax project and im unable to get current post type due to the dynamic nature.
  
    
2
  • I asked ChatGPT to clean it up and the results seem promising: chat.openai.com/share/f9a4b4ce-0e86-4cb5-a7ee-55d9e224a121 I can't test it since I don't have a setup like yours, but if you try it and it needs adjustment, feel free to edit your question with more details. Commented Mar 7 at 15:48
  • Thats a good idea, if you post the coce as a answer I can try and let you know
    – Beep
    Commented Mar 7 at 15:49

1 Answer 1

0

I asked ChatGPT to clean up this code and it did a pretty good job. You'll still need to integrate your JavaScript, but this is a good start on optimization.

<?php
// Get the current post type from the request.
$current_post_type = str_replace( '-', '_', basename( $wp->request ) );

// Set up the initial query arguments to get all published posts of the determined post type.
$args = array(
    'post_type'      => $current_post_type,
    'post_status'    => 'publish',
    'posts_per_page' => -1, // Get all posts.
);

// Execute the query.
$the_query = new WP_Query( $args );

// Initialize an array to keep track of categories that have posts.
$categories_with_posts = array();

if ( $the_query->have_posts() ) {
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        
        // Get the categories associated with the current post.
        $terms = get_the_terms( get_the_ID(), 'category' );
        if ( $terms && ! is_wp_error( $terms ) ) {
            foreach ( $terms as $term ) {
                // Check if the term ID is not already in the array to avoid duplicates.
                if ( ! array_key_exists( $term->term_id, $categories_with_posts ) ) {
                    // Store the term object, indexed by term ID for easy lookup.
                    $categories_with_posts[ $term->term_id ] = $term;
                }
            }
        }
    }
    wp_reset_postdata();
}

// Display the categories if there are any with posts.
if ( ! empty( $categories_with_posts ) ) {
    echo '<ul class="filter-list">';
    
    // Iterate over the categories with posts.
    foreach ( $categories_with_posts as $term_id => $category ) {
        // Determine if the category is a parent or child by checking its parent property.
        $class = 0 === $category->parent ? 'parent' : 'child';
        
        // Query to get the post count for the current category and post type.
        $post_count_args = array(
            'post_type'      => $current_post_type,
            'category'       => $category->term_id,
            'posts_per_page' => -1, // Get all posts.
        );
        $post_count_query = new WP_Query( $post_count_args );
        $post_count = $post_count_query->found_posts;

        // Only display categories that are not named "all-articles" and have posts.
        if ( 'all-articles' !== $category->slug && $post_count > 0 ) {
            echo sprintf(
                '<li class="%s"><a class="%s" @click="filterPosts(%d)">%s (%d)</a></li>',
                esc_attr( $class ),
                esc_attr( $class ),
                esc_attr( $category->term_id ),
                esc_html( $category->name ),
                $post_count
            );
        }
    }
    
    echo '</ul>';
}

The code is well-commented, so it should be clear what's going on. More broadly, instead of doing separate queries for parent and child categories, it gets all of them in one query and stores them in an associative array for easier usage.

The logic around display is consolidated into one section and the output is handled methodically with sprintf for easy maintenance.

1
  • sure dose look cleaner but brakes some of the functions, but will look at fixing this soon
    – Beep
    Commented Mar 8 at 11:40

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