PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/widgets/top-rated.php

https://github.com/scottpoulin/jigoshop
PHP | 234 lines | 110 code | 42 blank | 82 comment | 5 complexity | 57956822a50bc90344d52d8aba083084 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Recent Products Widget
  4. *
  5. * DISCLAIMER
  6. *
  7. * Do not edit or add directly to this file if you wish to upgrade Jigoshop to newer
  8. * versions in the future. If you wish to customise Jigoshop core for your needs,
  9. * please use our GitHub repository to publish essential changes for consideration.
  10. *
  11. * @package Jigoshop
  12. * @category Widgets
  13. * @author Jigoshop
  14. * @copyright Copyright Š 2011-2013 Jigoshop.
  15. * @license http://jigoshop.com/license/commercial-edition
  16. */
  17. class Jigoshop_Widget_Top_Rated extends WP_Widget {
  18. /**
  19. * Constructor
  20. *
  21. * Setup the widget with the available options
  22. * Add actions to clear the cache whenever a post is saved|deleted or a theme is switched
  23. */
  24. public function __construct() {
  25. $options = array(
  26. 'classname' => 'widget_top_rated',
  27. 'description' => __( 'The best of the best on your site', 'jigoshop' )
  28. );
  29. parent::__construct( 'top-rated', __( 'Jigoshop: Top Rated Products', 'jigoshop' ), $options );
  30. // Flush cache after every save
  31. add_action( 'save_post', array( &$this, 'flush_widget_cache' ) );
  32. add_action( 'deleted_post', array( &$this, 'flush_widget_cache' ) );
  33. add_action( 'switch_theme', array( &$this, 'flush_widget_cache' ) );
  34. }
  35. /**
  36. * Widget
  37. *
  38. * Display the widget in the sidebar
  39. * Save output to the cache if empty
  40. *
  41. * @param array sidebar arguments
  42. * @param array instance
  43. */
  44. public function widget( $args, $instance ) {
  45. // Get the most recent products from the cache
  46. $cache = wp_cache_get( 'widget_recent_products', 'widget' );
  47. // If no entry exists use array
  48. if ( ! is_array( $cache ) ) {
  49. $cache = array();
  50. }
  51. // If cached get from the cache
  52. if ( isset( $cache[$args['widget_id']] ) ) {
  53. echo $cache[$args['widget_id']];
  54. return false;
  55. }
  56. // Start buffering
  57. ob_start();
  58. extract( $args );
  59. // Set the widget title
  60. $title = apply_filters(
  61. 'widget_title',
  62. ($instance['title']) ? $instance['title'] : __( 'Top Rated Products', 'jigoshop' ),
  63. $instance,
  64. $this->id_base
  65. );
  66. // Set number of products to fetch
  67. if ( ! $number = absint( $instance['number'] ) ) {
  68. $number = 5;
  69. }
  70. // Set up query
  71. // Filter the $wpdb query
  72. add_filter( 'posts_clauses', array( &$this, 'order_by_rating' ) );
  73. // TODO: Only display products that are in stock
  74. $query_args = array(
  75. 'posts_per_page' => $number,
  76. 'post_type' => 'product',
  77. 'post_status' => 'publish',
  78. 'meta_query' => array(
  79. array(
  80. 'key' => 'visibility',
  81. 'value' => array( 'catalog', 'visible' ),
  82. 'compare' => 'IN',
  83. ),
  84. )
  85. );
  86. // Run the query
  87. $q = new WP_Query( $query_args );
  88. // If there are products
  89. if( $q->have_posts() ) {
  90. // Print the widget wrapper & title
  91. echo $before_widget;
  92. echo $before_title . $title . $after_title;
  93. // Open the list
  94. echo '<ul class="product_list_widget">';
  95. // Print out each product
  96. while( $q->have_posts() ) : $q->the_post(); $_product = new jigoshop_product( $q->post->ID );
  97. echo '<li>';
  98. // Print the title with a link to the permalink
  99. echo '<a href="'.esc_url( get_permalink() ).'" title="'.esc_attr( get_the_title() ).'">';
  100. // Print the product image
  101. echo ( has_post_thumbnail() )
  102. ? the_post_thumbnail( 'shop_tiny' )
  103. : jigoshop_get_image_placeholder( 'shop_tiny' );
  104. echo '<span class="js_widget_product_title">' . get_the_title() . '</span>';
  105. echo '</a>';
  106. // Print the average rating with html wrappers
  107. echo $_product->get_rating_html( 'sidebar' );
  108. // Print the price with html wrappers
  109. echo '<span class="js_widget_product_price">' . $_product->get_price_html() . '</span>';
  110. echo '</li>';
  111. endwhile;
  112. echo '</ul>'; // Close the list
  113. // Print closing widget wrapper
  114. echo $after_widget;
  115. // Reset the global $the_post as this query will have stomped on it
  116. wp_reset_postdata();
  117. remove_filter( 'posts_clauses', array( &$this, 'order_by_rating' ) );
  118. }
  119. // Flush output buffer and save to cache
  120. $cache[$args['widget_id']] = ob_get_flush();
  121. wp_cache_set( 'widget_recent_products', $cache, 'widget' );
  122. }
  123. // Shouldn't we be left joining products onto comments rather than comments onto products?
  124. // Reason: Not all products have comments & its a waste of query time
  125. public function order_by_rating( $clauses ) {
  126. global $wpdb;
  127. $clauses['where'] .= " AND $wpdb->commentmeta.meta_key = 'rating' ";
  128. $clauses['join'] .= "
  129. LEFT JOIN $wpdb->comments ON($wpdb->posts.ID = $wpdb->comments.comment_post_ID)
  130. LEFT JOIN $wpdb->commentmeta ON($wpdb->comments.comment_ID = $wpdb->commentmeta.comment_id)
  131. ";
  132. $clauses['orderby'] = "$wpdb->commentmeta.meta_value DESC";
  133. $clauses['groupby'] = "$wpdb->posts.ID";
  134. return $clauses;
  135. }
  136. /**
  137. * Update
  138. *
  139. * Handles the processing of information entered in the wordpress admin
  140. * Flushes the cache & removes entry from options array
  141. *
  142. * @param array new instance
  143. * @param array old instance
  144. * @return array instance
  145. */
  146. public function update( $new_instance, $old_instance ) {
  147. $instance = $old_instance;
  148. // Save the new values
  149. $instance['title'] = strip_tags( $new_instance['title'] );
  150. $instance['number'] = absint( $new_instance['number'] );
  151. // Flush the cache
  152. $this->flush_widget_cache();
  153. // Remove the cache entry from the options array
  154. $alloptions = wp_cache_get( 'alloptions', 'options' );
  155. if ( isset( $alloptions['widget_top_rated'] ) ) {
  156. delete_option( 'widget_top_rated' );
  157. }
  158. return $instance;
  159. }
  160. /**
  161. * Flush Widget Cache
  162. *
  163. * Used to flush the cached output
  164. */
  165. public function flush_widget_cache() {
  166. wp_cache_delete( 'widget_top_rated', 'widget' );
  167. }
  168. /**
  169. * Form
  170. *
  171. * Displays the form for the wordpress admin
  172. *
  173. * @param array instance
  174. */
  175. public function form( $instance ) {
  176. // Get instance data
  177. $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : null;
  178. $number = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
  179. // Widget Title
  180. echo "
  181. <p>
  182. <label for='{$this->get_field_id( 'title' )}'>" . __( 'Title:', 'jigoshop' ) . "</label>
  183. <input class='widefat' id='{$this->get_field_id( 'title' )}' name='{$this->get_field_name( 'title' )}' type='text' value='{$title}' />
  184. </p>";
  185. // Number of posts to fetch
  186. echo "
  187. <p>
  188. <label for='{$this->get_field_id( 'number' )}'>" . __( 'Number of products to show:', 'jigoshop' ) . "</label>
  189. <input id='{$this->get_field_id( 'number' )}' name='{$this->get_field_name( 'number' )}' type='number' value='{$number}' />
  190. </p>";
  191. }
  192. }