Widget Woocommerce List Products in Same Category

Widget Woocommerce List Products in Same Category
widget which can show a list of woocommerce products in same category as current product.

<?php
class cmsaddons_woo_products_same_category extends WP_Widget {
  public function __construct() {
    parent::__construct('cmsaddons_woo_products_same_category', 'Products in category');
  }
  public function widget( $args, $instance )
  {
    echo $args['before_widget']; 
    $this->_products($instance);
    echo $args['after_widget']; //end
  }
 
  function update ( $new_instance, $old_instance )
  {
    
    $instance = $old_instance;
    $instance['title'] =  empty($new_instance['title']) ? '' : $new_instance['title'];
    $instance['product_count'] =  empty($new_instance['product_count'])
                                  ? 0
                                  : (int) $new_instance['product_count'];
    return $instance;
  }
  function form ( $instance ) {
    $product_count =  isset($instance['product_count']) ? $instance['product_count'] : 0;
    $title =  isset($instance['title']) ? $instance['title'] : '';
  ?>
    <!-- Widget Title: Text Input -->
      <p>
            <label for="<?= $this->get_field_id( 'product_count' ); ?>">
              Title
            </label>
            <input type="text" name="<?= $this->get_field_name( 'title' ); ?>"
                  value="<?= $title; ?>" class="widefat"
                  id="<?= $this->get_field_id( 'title' ); ?>" />
        </p>
 
    <!-- Widget text: Text Input -->
        <p>
            <label for="<?= $this->get_field_id( 'product_count' ); ?>">
              Number of Products To Show
            </label>
            <input type="text" name="<?= $this->get_field_name( 'product_count' ); ?>"
                  value="<?= $product_count; ?>" class="widefat"
                  id="<?= $this->get_field_id( 'product_count' ); ?>" />
        </p>
  <?php
  }
  private function _products($instance){
         if ( is_singular('product') ) {
            if(isset($instance['product_count'])){
                 $product_count = $instance['product_count'];
             }else{ $product_count = 5; }
           
            global $post;
              $post_ID = $post->ID;
              // get categories
              $terms = wp_get_post_terms( $post->ID, 'product_cat' );
              foreach ( $terms as $term ) $cats_array[] = $term->term_id;
              $query_args = array(
                  // 'post__not_in' => array( $post->ID ),
                  'posts_per_page' => $product_count,
                  'no_found_rows' => 1,
                  'post_status' => 'publish',
                  'orderby' => 'title',
                  'order' => 'ASC',
                  'post_type' => 'product',
                  'tax_query' => array(
                    array(
                      'taxonomy' => 'product_cat',
                      'field' => 'id',
                      'terms' => $cats_array
                )));
              $r = new WP_Query($query_args);
              if ($r->have_posts()) {
            ?>
            <ul class="product_list_widget">
                  <?php while ($r->have_posts()) : $r->the_post(); global $product; ?>
                    <li>
                      <a href="<?php the_permalink() ?>" title="<?php echo esc_attr(get_the_title() ? get_the_title() : get_the_ID()); ?>" class="<?php if(get_the_ID() == $post_ID) echo "active"; ?>">
                          <?php if ( get_the_title() ) the_title(); else the_ID(); ?>
                      </a>
                    </li>
                  <?php endwhile; ?>
                </ul>
                <?php
                // Reset the global $the_post as this query will have stomped on it
                wp_reset_query();
              }
         }
    }
}

function cmsaddons_woo_products_same_category_widget() 
{
	register_widget( 'cmsaddons_woo_products_same_category' );
}
add_action( 'widgets_init', 'cmsaddons_woo_products_same_category_widget' );