PluginProbe ʕ •ᴥ•ʔ
WP Popular Posts / 4.1.1
WP Popular Posts v4.1.1
4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 5.0.0 5.0.1 5.0.2 5.1.0 5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.4.0 5.4.1 5.4.2 5.5.0 5.5.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.2.0 6.2.1 6.3.0 6.3.1 6.3.2 6.3.3 6.3.4 6.4.0 6.4.1 6.4.2 7.0.0 7.0.1 7.1.0 7.2.0 7.3.0 7.3.1 7.3.2 7.3.3 7.3.4 7.3.5 7.3.6 7.3.7 7.3.8 7.4.0 trunk 2.3.7 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.2 4.0.3 4.0.5 4.0.6
wordpress-popular-posts / includes / class-wordpress-popular-posts-query.php
wordpress-popular-posts / includes Last commit date
class-wordpress-popular-posts-activator.php 8 years ago class-wordpress-popular-posts-deactivator.php 8 years ago class-wordpress-popular-posts-helper.php 8 years ago class-wordpress-popular-posts-i18n.php 8 years ago class-wordpress-popular-posts-image.php 8 years ago class-wordpress-popular-posts-loader.php 8 years ago class-wordpress-popular-posts-output.php 8 years ago class-wordpress-popular-posts-query.php 8 years ago class-wordpress-popular-posts-rest-controller.php 8 years ago class-wordpress-popular-posts-settings.php 8 years ago class-wordpress-popular-posts-template.php 8 years ago class-wordpress-popular-posts-translate.php 8 years ago class-wordpress-popular-posts-widget.php 8 years ago class-wordpress-popular-posts.php 8 years ago widget-form.php 8 years ago
class-wordpress-popular-posts-query.php
467 lines
1 <?php
2 /**
3 * Queries the database for popular posts.
4 *
5 * To use this class, you must pass it an array of parameters (mostly the same ones used with
6 * the wpp_get_mostpopular() template tag). The very minimum required parameters are 'range', 'order_by'
7 * and 'limit'.
8 *
9 * eg.: $popular_posts = new WPP_Query( array('range' => 'last7days', 'order_by' => 'views', 'limit' => 5) );
10 *
11 * @since 4.0.0
12 * @package WordPressPopularPosts
13 * @subpackage WordPressPopularPosts/includes
14 */
15
16 class WPP_Query {
17
18 /*
19 * Database query string.
20 *
21 * @since 4.0.0
22 * @access private
23 * @var string $query
24 */
25 private $query;
26
27 /*
28 * List of posts.
29 *
30 * @since 4.0.0
31 * @access private
32 * @var array $posts
33 */
34 private $posts = array();
35
36 /*
37 * Plugin options.
38 *
39 * @since 4.0.0
40 * @access private
41 * @var array $options
42 */
43 private $options;
44
45 /*
46 * Constructor.
47 *
48 * @since 4.0.0
49 * @param array $options
50 */
51 public function __construct( array $options = array() ){
52 $this->options = $options;
53 $this->build_query();
54 $this->run_query();
55 }
56
57 /*
58 * Builds the database query.
59 *
60 * @since 4.0.0
61 * @access private
62 */
63 private function build_query(){
64
65 /*
66 * @var wpdb $wpdb
67 */
68 global $wpdb;
69
70 if ( isset($wpdb) ) {
71
72 $this->options = WPP_Helper::merge_array_r(
73 WPP_Settings::$defaults[ 'widget_options' ],
74 (array) $this->options
75 );
76
77 $args = array();
78 $fields = "p.ID AS id, p.post_title AS title, p.post_author AS uid";
79 $table = "";
80 $join = "";
81 $where = "WHERE 1 = 1";
82 $groupby = "";
83 $orderby = "";
84 $limit = "LIMIT " . ( filter_var($this->options['limit'], FILTER_VALIDATE_INT) && $this->options['limit'] > 0 ? $this->options['limit'] : 10 ) . ( isset($this->options['offset']) && filter_var($this->options['offset'], FILTER_VALIDATE_INT) !== false && $this->options['offset'] >= 0 ? " OFFSET {$this->options['offset']}" : "" );
85
86 // Get post date
87 if ( isset($this->options['stats_tag']['date']['active']) && $this->options['stats_tag']['date']['active'] ) {
88 $fields .= ", p.post_date AS date";
89 }
90
91 // Get post excerpt $instance
92 if ( isset($this->options['post-excerpt']['active']) && $this->options['post-excerpt']['active'] ) {
93 $fields .= ", p.post_excerpt AS post_excerpt, p.post_content AS post_content";
94 }
95
96 // Get entries from these post types
97 $post_types = array( 'post', 'page' );
98
99 if ( isset($this->options['post_type']) && !empty($this->options['post_type']) ) {
100
101 $post_types = explode( ",", $this->options['post_type'] );
102 $pt = '';
103 $where .= " AND p.post_type IN(";
104
105 foreach( $post_types as $post_type ) {
106 $pt .= "%s, ";
107 array_push( $args, trim($post_type) );
108 }
109
110 $where .= rtrim($pt, ", ") . ")";
111
112 }
113 else {
114 $where .= " AND p.post_type IN('post', 'page')";
115 }
116
117 // Get entries from these authors
118 if ( isset($this->options['author']) && !empty($this->options['author']) ) {
119
120 $author_IDs = explode( ",", $this->options['author'] );
121 $uid = '';
122 $where .= " AND p.post_author IN(";
123
124 foreach( $author_IDs as $author_ID ) {
125 $uid .= "%d, ";
126 array_push( $args, trim($author_ID) );
127 }
128
129 $where .= rtrim($uid, ", ") . ")";
130
131 }
132
133 // Get / exclude entries from this taxonomy
134 if (
135 ( isset($this->options['cat']) && !empty($this->options['cat']) )
136 || ( isset($this->options['term_id']) && !empty($this->options['term_id']) )
137 ) {
138
139 if ( isset($this->options['taxonomy']) && !empty($this->options['taxonomy']) ) {
140
141 $registered_taxonomies = get_taxonomies( array('public' => true) );
142
143 // Invalid taxonomy, fallback to "category"
144 if ( !isset($registered_taxonomies[$this->options['taxonomy']]) ) {
145 $this->options['taxonomy'] = 'category';
146 }
147
148 } // Default to "category"
149 else {
150 $this->options['taxonomy'] = 'category';
151 }
152
153 if ( isset($this->options['cat']) && !empty($this->options['cat']) ) {
154 $this->options['term_id'] = $this->options['cat'];
155 }
156
157 $term_IDs = explode( ",", $this->options['term_id'] );
158 $in_term_IDs = array();
159 $out_term_IDs = array();
160
161 foreach( $term_IDs as $term_ID ) {
162
163 if ( $term_ID >= 0 )
164 $in_term_IDs[] = trim( $term_ID );
165 else
166 $out_term_IDs[] = trim( $term_ID ) * -1;
167
168 }
169
170 if ( !empty($in_term_IDs) ) {
171
172 $where .= " AND p.ID IN (
173 SELECT object_id
174 FROM `{$wpdb->term_relationships}` AS r
175 JOIN `{$wpdb->term_taxonomy}` AS x ON x.term_taxonomy_id = r.term_taxonomy_id
176 WHERE x.taxonomy = '{$this->options['taxonomy']}'";
177
178 $inTID = '';
179
180 foreach( $in_term_IDs as $in_term_ID ) {
181 $inTID .= "%d, ";
182 array_push( $args, $in_term_ID );
183 }
184
185 $where .= " AND x.term_id IN(" . rtrim($inTID, ", ") . ") )";
186
187 }
188
189 if ( !empty($out_term_IDs) ) {
190
191 $post_ids = get_posts(
192 array(
193 'post_type' => $post_types,
194 'posts_per_page' => -1,
195 'tax_query' => array(
196 array(
197 'taxonomy' => $this->options['taxonomy'],
198 'field' => 'id',
199 'terms' => $out_term_IDs,
200 ),
201 ),
202 'fields' => 'ids'
203 )
204 );
205
206 if ( is_array($post_ids) && !empty($post_ids) ) {
207
208 if ( isset($this->options['pid']) && !empty($this->options['pid']) ) {
209 $this->options['pid'] .= "," . implode( ",", $post_ids );
210 }
211 else {
212 $this->options['pid'] = implode( ",", $post_ids );
213 }
214
215 }
216
217 }
218
219 }
220
221 // Exclude these entries from the listing
222 if ( isset($this->options['pid']) && !empty($this->options['pid']) ) {
223
224 $excluded_post_IDs = explode( ",", $this->options['pid'] );
225 $xpid = '';
226 $where .= " AND p.ID NOT IN(";
227
228 foreach( $excluded_post_IDs as $excluded_post_ID ) {
229 $xpid .= "%d, ";
230 array_push( $args, trim($excluded_post_ID) );
231 }
232
233 $where .= rtrim($xpid, ", ") . ")";
234
235 }
236
237 // All-time range
238 if ( "all" == $this->options['range'] ) {
239
240 // Order by views count
241 if ( "comments" != $this->options['order_by'] ) {
242
243 $table = "`{$wpdb->prefix}popularpostsdata` v";
244 $join = "LEFT JOIN `{$wpdb->posts}` p ON v.postid = p.ID";
245
246 // Order by views
247 if ( "views" == $this->options['order_by'] ) {
248
249 if ( !isset($this->options['stats_tag']['views']) || $this->options['stats_tag']['views'] ) {
250 $fields .= ", v.pageviews";
251 }
252
253 $orderby = "ORDER BY v.pageviews DESC";
254
255 }
256 // Order by average views
257 else {
258
259 $now = current_time( 'mysql' );
260
261 $fields .= ", ( v.pageviews/(IF ( DATEDIFF('{$now}', MIN(v.day)) > 0, DATEDIFF('{$now}', MIN(v.day)), 1) ) ) AS avg_views";
262 $groupby = "GROUP BY v.postid";
263 $orderby = "ORDER BY avg_views DESC";
264
265 }
266
267 // Display comments count, too
268 if ( isset($this->options['stats_tag']['comment_count']) && $this->options['stats_tag']['comment_count'] ) {
269 $fields .= ", p.comment_count";
270 }
271
272 }
273 // Order by comments count
274 else {
275
276 $table = "`{$wpdb->posts}` p";
277 $where .= " AND p.comment_count > 0";
278 $orderby = "ORDER BY p.comment_count DESC";
279
280 // Display comment count
281 if ( isset($this->options['stats_tag']['comment_count']) && $this->options['stats_tag']['comment_count'] ) {
282 $fields .= ", p.comment_count";
283 }
284
285 // Display views count, too
286 if ( isset($this->options['stats_tag']['views']) && $this->options['stats_tag']['views'] ) {
287 $fields .= ", IFNULL(v.pageviews, 0) AS pageviews";
288 $join = "LEFT JOIN `{$wpdb->prefix}popularpostsdata` v ON p.ID = v.postid";
289 }
290
291 }
292
293 }
294 // Custom time range
295 else {
296
297 $now = current_time( 'mysql' );
298
299 // Determine time range
300 switch( $this->options['range'] ){
301 case "last24hours":
302 case "daily":
303 $interval = "24 HOUR";
304 break;
305
306 case "last7days":
307 case "weekly":
308 $interval = "6 DAY";
309 break;
310
311 case "last30days":
312 case "monthly":
313 $interval = "29 DAY";
314 break;
315
316 case "custom":
317 $time_units = array( "MINUTE", "HOUR", "DAY", "WEEK", "MONTH" );
318 $interval = "24 HOUR";
319
320 // Valid time unit
321 if (
322 isset( $this->options['time_unit'] )
323 && in_array( strtoupper( $this->options['time_unit'] ), $time_units )
324 && isset( $this->options['time_quantity'] )
325 && filter_var( $this->options['time_quantity'], FILTER_VALIDATE_INT )
326 && $this->options['time_quantity'] > 0
327 ) {
328 $interval = "{$this->options['time_quantity']} " . strtoupper( $this->options['time_unit'] );
329 }
330
331 break;
332
333 default:
334 $interval = "24 HOUR";
335 break;
336 }
337
338 // Get entries published within the specified time range
339 if ( isset($this->options['freshness']) && $this->options['freshness'] ) {
340 $where .= " AND p.post_date > DATE_SUB('{$now}', INTERVAL {$interval})";
341 }
342
343 // Order by views count
344 if ( "comments" != $this->options['order_by'] ) {
345
346 $table = "`{$wpdb->prefix}popularpostssummary` v";
347 $join = "LEFT JOIN `{$wpdb->posts}` p ON v.postid = p.ID";
348 $where .= " AND v.view_datetime > DATE_SUB('{$now}', INTERVAL {$interval})";
349 $groupby = "GROUP BY v.postid";
350
351 // Order by views
352 if ( "views" == $this->options['order_by'] ) {
353
354 if ( !isset($this->options['stats_tag']['views']) || $this->options['stats_tag']['views'] ) {
355 $fields .= ", SUM(v.pageviews) AS pageviews";
356 $orderby = "ORDER BY pageviews DESC";
357 }
358 else {
359 $orderby = "ORDER BY SUM(v.pageviews) DESC";
360 }
361
362 }
363 // Order by average views
364 else {
365 $fields .= ", ( SUM(v.pageviews)/(IF ( DATEDIFF('{$now}', DATE_SUB('{$now}', INTERVAL {$interval})) > 0, DATEDIFF('{$now}', DATE_SUB('{$now}', INTERVAL {$interval})), 1) ) ) AS avg_views";
366 $orderby = "ORDER BY avg_views DESC";
367 }
368
369 // Display comments count, too
370 if ( isset($this->options['stats_tag']['comment_count']) && $this->options['stats_tag']['comment_count'] ) {
371 $fields .= ", IFNULL(c.comment_count, 0) AS comment_count";
372 $join .= " LEFT JOIN (SELECT comment_post_ID, COUNT(comment_post_ID) AS comment_count FROM `{$wpdb->comments}` WHERE comment_date_gmt > DATE_SUB('{$now}', INTERVAL {$interval}) AND comment_approved = 1 GROUP BY comment_post_ID) c ON p.ID = c.comment_post_ID";
373 }
374
375 }
376 // Order by comments count
377 else {
378
379 $table = "`{$wpdb->comments}` c";
380 $join = "LEFT JOIN {$wpdb->posts} p ON c.comment_post_ID = p.ID";
381 $where .= " AND c.comment_date_gmt > DATE_SUB('{$now}', INTERVAL {$interval}) AND c.comment_approved = 1";
382 $groupby = "GROUP BY c.comment_post_ID";
383
384 // Display comment count
385 if ( isset($this->options['stats_tag']['comment_count']) && $this->options['stats_tag']['comment_count'] ) {
386 $fields .= ", COUNT(c.comment_post_ID) AS comment_count";
387 $orderby = "ORDER BY comment_count DESC";
388 }
389 else {
390 $orderby = "ORDER BY COUNT(c.comment_post_ID) DESC";
391 }
392
393 // Display views count, too
394 if ( isset($this->options['stats_tag']['views']) && $this->options['stats_tag']['views'] ) {
395 $fields .= ", IFNULL(v.pageviews, 0) AS pageviews";
396 $join .= " LEFT JOIN (SELECT postid, SUM(pageviews) AS pageviews FROM `{$wpdb->prefix}popularpostssummary` WHERE view_datetime > DATE_SUB('{$now}', INTERVAL {$interval}) GROUP BY postid) v ON p.ID = v.postid";
397 }
398
399 }
400
401 }
402
403 // List only published, non password-protected posts
404 $where .= " AND p.post_password = '' AND p.post_status = 'publish'";
405
406 if ( !empty($args) ) {
407 $where = $wpdb->prepare( $where, $args );
408 }
409
410 $fields = apply_filters( 'wpp_query_fields', $fields, $this->options );
411 $table = apply_filters( 'wpp_query_table', $table, $this->options );
412 $join = apply_filters( 'wpp_query_join', $join, $this->options );
413 $where = apply_filters( 'wpp_query_where', $where, $this->options );
414 $groupby = apply_filters( 'wpp_query_group_by', $groupby, $this->options );
415 $orderby = apply_filters( 'wpp_query_order_by', $orderby, $this->options );
416 $limit = apply_filters( 'wpp_query_limit', $limit, $this->options );
417
418 // Finally, build the query
419 $query = "SELECT {$fields} FROM {$table} {$join} {$where} {$groupby} {$orderby} {$limit};";
420 //$this->query = ( !empty($args) && !has_filter('wpp_query_where') ) ? $wpdb->prepare( $query, $args ) : $query;
421 $this->query = $query;
422
423 }
424
425 }
426
427 /*
428 * Queries the database.
429 *
430 * @since 4.0.0
431 * @access private
432 */
433 private function run_query(){
434
435 /*
436 * @var wpdb $wpdb
437 */
438 global $wpdb;
439
440 if ( isset($wpdb) && !empty($this->query) && !is_wp_error($this->query) ) {
441 $this->posts = $wpdb->get_results( $this->query );
442 }
443
444 }
445
446 /*
447 * Returns the query string.
448 *
449 * @since 4.0.0
450 * @return WP_Error|string Query string on success, WP_Error on failure
451 */
452 public function get_query(){
453 return $this->query;
454 }
455
456 /*
457 * Returns the list of posts.
458 *
459 * @since 4.0.0
460 * @return array
461 */
462 public function get_posts(){
463 return $this->posts;
464 }
465
466 } // end WPP_Query class
467