PluginProbe ʕ •ᴥ•ʔ
Post Views Counter / 1.3.8
Post Views Counter v1.3.8
1.7.13 1.7.12 1.7.11 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.2 1.3.2.1 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9
post-views-counter / includes / class-query.php
post-views-counter / includes Last commit date
ajax.php 7 years ago class-admin.php 4 years ago class-columns.php 4 years ago class-counter.php 4 years ago class-crawler-detect.php 4 years ago class-cron.php 4 years ago class-dashboard.php 4 years ago class-frontend.php 4 years ago class-functions.php 4 years ago class-query.php 4 years ago class-settings-api.php 4 years ago class-settings.php 4 years ago class-update.php 4 years ago class-widgets.php 4 years ago columns.php 6 years ago counter.php 6 years ago crawler-detect.php 6 years ago cron.php 6 years ago dashboard.php 6 years ago frontend.php 6 years ago functions.php 4 years ago query.php 6 years ago settings.php 6 years ago update.php 6 years ago widgets.php 6 years ago
class-query.php
379 lines
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Post_Views_Counter_Query class.
8 *
9 * @class Post_Views_Counter_Query
10 */
11 class Post_Views_Counter_Query {
12
13 /**
14 * Class constructor.
15 *
16 * @return void
17 */
18 public function __construct() {
19 // actions
20 add_action( 'pre_get_posts', [ $this, 'extend_pre_query' ], 1 );
21
22 // filters
23 add_filter( 'query_vars', [ $this, 'query_vars' ] );
24 add_filter( 'posts_join', [ $this, 'posts_join' ], 10, 2 );
25 add_filter( 'posts_groupby', [ $this, 'posts_groupby' ], 10, 2 );
26 add_filter( 'posts_orderby', [ $this, 'posts_orderby' ], 10, 2 );
27 add_filter( 'posts_fields', [ $this, 'posts_fields' ], 10, 2 );
28 add_filter( 'the_posts', [ $this, 'the_posts' ], 10, 2 );
29 }
30
31 /**
32 * Register views_query var.
33 *
34 * @param array $query_vars
35 * @return array
36 */
37 public function query_vars( $query_vars ) {
38 $query_vars[] = 'views_query';
39
40 return $query_vars;
41 }
42
43 /**
44 * Extend query with post_views orderby parameter.
45 *
46 * @param object $query
47 * @return void
48 */
49 public function extend_pre_query( $query ) {
50 if ( isset( $query->query_vars['orderby'] ) && $query->query_vars['orderby'] === 'post_views' )
51 $query->pvc_orderby = true;
52 }
53
54 /**
55 * Modify the database query to use post_views parameter.
56 *
57 * @global object $wpdb
58 * @param string $join
59 * @param object $query
60 * @return string
61 */
62 public function posts_join( $join, $query ) {
63 $sql = '';
64 $query_chunks = [];
65
66 // views query?
67 if ( ! empty( $query->query['views_query'] ) ) {
68 if ( isset( $query->query['views_query']['inclusive'] ) )
69 $query->query['views_query']['inclusive'] = (bool) $query->query['views_query']['inclusive'];
70 else
71 $query->query['views_query']['inclusive'] = true;
72
73 // check after and before dates
74 foreach ( [ 'after' => '>', 'before' => '<' ] as $date => $type ) {
75 $year_ = null;
76 $month_ = null;
77 $week_ = null;
78 $day_ = null;
79
80 // check views query date
81 if ( ! empty( $query->query['views_query'][$date] ) ) {
82 // is it a date array?
83 if ( is_array( $query->query['views_query'][$date] ) ) {
84 // check views query $date date year
85 if ( ! empty( $query->query['views_query'][$date]['year'] ) )
86 $year_ = str_pad( (int) $query->query['views_query'][$date]['year'], 4, 0, STR_PAD_LEFT );
87
88 // check views query date month
89 if ( ! empty( $query->query['views_query'][$date]['month'] ) )
90 $month_ = str_pad( (int) $query->query['views_query'][$date]['month'], 2, 0, STR_PAD_LEFT );
91
92 // check views query date week
93 if ( ! empty( $query->query['views_query'][$date]['week'] ) )
94 $week_ = str_pad( (int) $query->query['views_query'][$date]['week'], 2, 0, STR_PAD_LEFT );
95
96 // check views query date day
97 if ( ! empty( $query->query['views_query'][$date]['day'] ) )
98 $day_ = str_pad( (int) $query->query['views_query'][$date]['day'], 2, 0, STR_PAD_LEFT );
99 // is it a date string?
100 } elseif ( is_string( $query->query['views_query'][$date] ) ) {
101 $time_ = strtotime( $query->query['views_query'][$date] );
102
103 // valid datetime?
104 if ( $time_ !== false ) {
105 // week does not exists here, string dates are always treated as year + month + day
106 list( $day_, $month_, $year_ ) = explode( ' ', date( "d m Y", $time_ ) );
107 }
108 }
109
110 // valid date?
111 if ( ! ( $year_ === null && $month_ === null && $week_ === null && $day_ === null ) ) {
112 $query_chunks[] = [
113 'year' => $year_,
114 'month' => $month_,
115 'day' => $day_,
116 'week' => $week_,
117 'type' => $type . ( $query->query['views_query']['inclusive'] ? '=' : '' )
118 ];
119 }
120 }
121 }
122
123 // any after, before query chunks?
124 if ( ! empty( $query_chunks ) ) {
125 $valid_dates = true;
126
127 // check only if both dates are in query
128 if ( count( $query_chunks ) === 2 ) {
129 // before and after dates should be the same
130 foreach ( [ 'year', 'month', 'day', 'week' ] as $date_type ) {
131 if ( ! ( ( $query_chunks[0][$date_type] !== null && $query_chunks[1][$date_type] !== null ) || ( $query_chunks[0][$date_type] === null && $query_chunks[1][$date_type] === null ) ) )
132 $valid_dates = false;
133 }
134 }
135
136 // after and before dates should be
137 if ( $valid_dates ) {
138 foreach ( $query_chunks as $chunk ) {
139 // year
140 if ( isset( $chunk['year'] ) ) {
141 // year, week
142 if ( isset( $chunk['week'] ) )
143 $sql .= " AND pvc.type = 1 AND pvc.period " . $chunk['type'] . " '" . $chunk['year'] . $chunk['week'] . "'";
144 // year, month
145 elseif ( isset( $chunk['month'] ) ) {
146 // year, month, day
147 if ( isset( $chunk['day'] ) )
148 $sql .= " AND pvc.type = 0 AND pvc.period " . $chunk['type'] . " '" . $chunk['year'] . $chunk['month'] . $chunk['day'] . "'";
149 // year, month
150 else
151 $sql .= " AND pvc.type = 2 AND pvc.period " . $chunk['type'] . " '" . $chunk['year'] . $chunk['month'] . "'";
152 // year
153 } else
154 $sql .= " AND pvc.type = 3 AND pvc.period " . $chunk['type'] . " '" . $chunk['year'] . "'";
155 // month
156 } elseif ( isset( $chunk['month'] ) ) {
157 // month, day
158 if ( isset( $chunk['day'] ) )
159 $sql .= " AND pvc.type = 0 AND RIGHT( pvc.period, 4 ) " . $chunk['type'] . " '" . $chunk['month'] . $chunk['day'] . "'";
160 // month
161 else
162 $sql .= " AND pvc.type = 2 AND RIGHT( pvc.period, 2 ) " . $chunk['type'] . " '" . $chunk['month'] . "'";
163 // week
164 } elseif ( isset( $chunk['week'] ) )
165 $sql .= " AND pvc.type = 1 AND RIGHT( pvc.period, 2 ) " . $chunk['type'] . " '" . $chunk['week'] . "'";
166 // day
167 elseif ( isset( $chunk['day'] ) )
168 $sql .= " AND pvc.type = 0 AND RIGHT( pvc.period, 2 ) " . $chunk['type'] . " '" . $chunk['day'] . "'";
169 }
170 }
171 }
172
173 // standard query
174 if ( $sql === '' ) {
175 // check year
176 if ( isset( $query->query['views_query']['year'] ) )
177 $year = (int) $query->query['views_query']['year'];
178
179 // check month
180 if ( isset( $query->query['views_query']['month'] ) )
181 $month = (int) $query->query['views_query']['month'];
182
183 // check week
184 if ( isset( $query->query['views_query']['week'] ) )
185 $week = (int) $query->query['views_query']['week'];
186
187 // check day
188 if ( isset( $query->query['views_query']['day'] ) )
189 $day = (int) $query->query['views_query']['day'];
190
191 // year
192 if ( isset( $year ) ) {
193 // year, week
194 if ( isset( $week ) && $this->is_date_valid( 'yw', $year, 0, 0, $week ) )
195 $sql = " AND pvc.type = 1 AND pvc.period = '" . str_pad( $year, 4, 0, STR_PAD_LEFT ) . str_pad( $week, 2, 0, STR_PAD_LEFT ) . "'";
196 // year, month
197 elseif ( isset( $month ) ) {
198 // year, month, day
199 if ( isset( $day ) && $this->is_date_valid( 'ymd', $year, $month, $day ) )
200 $sql = " AND pvc.type = 0 AND pvc.period = '" . str_pad( $year, 4, 0, STR_PAD_LEFT ) . str_pad( $month, 2, 0, STR_PAD_LEFT ) . str_pad( $day, 2, 0, STR_PAD_LEFT ) . "'";
201 // year, month
202 elseif ( $this->is_date_valid( 'ym', $year, $month ) )
203 $sql = " AND pvc.type = 2 AND pvc.period = '" . str_pad( $year, 4, 0, STR_PAD_LEFT ) . str_pad( $month, 2, 0, STR_PAD_LEFT ) . "'";
204 // year
205 } elseif ( $this->is_date_valid( 'y', $year ) )
206 $sql = " AND pvc.type = 3 AND pvc.period = '" . str_pad( $year, 4, 0, STR_PAD_LEFT ) . "'";
207 // month
208 } elseif ( isset( $month ) ) {
209 // month, day
210 if ( isset( $day ) && $this->is_date_valid( 'md', 0, $month, $day ) ) {
211 $sql = " AND pvc.type = 0 AND RIGHT( pvc.period, 4 ) = '" . str_pad( $month, 2, 0, STR_PAD_LEFT ) . str_pad( $day, 2, 0, STR_PAD_LEFT ) . "'";
212 // month
213 } elseif ( $this->is_date_valid( 'm', 0, $month ) )
214 $sql = " AND pvc.type = 2 AND RIGHT( pvc.period, 2 ) = '" . str_pad( $month, 2, 0, STR_PAD_LEFT ) . "'";
215 // week
216 } elseif ( isset( $week ) && $this->is_date_valid( 'w', 0, 0, 0, $week ) )
217 $sql = " AND pvc.type = 1 AND RIGHT( pvc.period, 2 ) = '" . str_pad( $week, 2, 0, STR_PAD_LEFT ) . "'";
218 // day
219 elseif ( isset( $day ) && $this->is_date_valid( 'd', 0, 0, $day ) )
220 $sql = " AND pvc.type = 0 AND RIGHT( pvc.period, 2 ) = '" . str_pad( $day, 2, 0, STR_PAD_LEFT ) . "'";
221 }
222
223 if ( $sql !== '' )
224 $query->pvc_query = true;
225 }
226
227 // is it sorted by post views?
228 if ( ( $sql === '' && isset( $query->pvc_orderby ) && $query->pvc_orderby ) || apply_filters( 'pvc_extend_post_object', false, $query ) === true )
229 $sql = ' AND pvc.type = 4';
230
231 // add date range
232 if ( $sql !== '' ) {
233 global $wpdb;
234
235 $join .= " LEFT JOIN " . $wpdb->prefix . "post_views pvc ON pvc.id = " . $wpdb->prefix . "posts.ID" . $sql;
236 }
237
238 return $join;
239 }
240
241 /**
242 * Group posts using the post ID.
243 *
244 * @global object $wpdb
245 * @param string $groupby
246 * @param object $query
247 * @return string
248 */
249 public function posts_groupby( $groupby, $query ) {
250 // is it sorted by post views or views_query is used?
251 if ( ( isset( $query->pvc_orderby ) && $query->pvc_orderby ) || ( isset( $query->pvc_query ) && $query->pvc_query ) || apply_filters( 'pvc_extend_post_object', false, $query ) === true ) {
252 global $pagenow;
253
254 // needed only for sorting
255 if ( $pagenow === 'upload.php' || $pagenow === 'edit.php' )
256 $query->query['views_query']['hide_empty'] = false;
257
258 global $wpdb;
259
260 $groupby = trim( $groupby );
261
262 if ( strpos( $groupby, $wpdb->prefix . 'posts.ID' ) === false )
263 $groupby = ( $groupby !== '' ? $groupby . ', ' : '') . $wpdb->prefix . 'posts.ID';
264
265 if ( ! isset( $query->query['views_query']['hide_empty'] ) || $query->query['views_query']['hide_empty'] === true )
266 $groupby .= ' HAVING post_views > 0';
267 }
268
269 return $groupby;
270 }
271
272 /**
273 * Order posts by post views.
274 *
275 * @global object $wpdb
276 * @param string $orderby
277 * @param object $query
278 * @return string
279 */
280 public function posts_orderby( $orderby, $query ) {
281 // is it sorted by post views?
282 if ( ( isset( $query->pvc_orderby ) && $query->pvc_orderby ) ) {
283 global $wpdb;
284
285 $order = $query->get( 'order' );
286 $orderby = ( ! isset( $query->query['views_query']['hide_empty'] ) || $query->query['views_query']['hide_empty'] === true ? 'post_views' : 'pvc.count' ) . ' ' . $order . ', ' . $wpdb->prefix . 'posts.ID ' . $order;
287 }
288
289 return $orderby;
290 }
291
292 /**
293 * Return post views in queried post objects.
294 *
295 * @param string $fields
296 * @param object $query
297 * @return string
298 */
299 public function posts_fields( $fields, $query ) {
300 if ( ( ! isset( $query->query['fields'] ) || $query->query['fields'] === '' ) && ( ( isset( $query->pvc_orderby ) && $query->pvc_orderby ) || ( isset( $query->pvc_query ) && $query->pvc_query ) || apply_filters( 'pvc_extend_post_object', false, $query ) === true ) )
301 $fields = $fields . ', SUM( IFNULL( pvc.count, 0 ) ) AS post_views';
302
303 return $fields;
304 }
305
306 /**
307 * Extend query object with total post views.
308 *
309 * @param array $posts
310 * @param object $query
311 * @return array
312 */
313 public function the_posts( $posts, $query ) {
314 if ( ( isset( $query->pvc_orderby ) && $query->pvc_orderby ) || ( isset( $query->pvc_query ) && $query->pvc_query ) || apply_filters( 'pvc_extend_post_object', false, $query ) === true ) {
315 $sum = 0;
316
317 // any posts found?
318 if ( ! empty( $posts ) ) {
319 foreach ( $posts as $post ) {
320 if ( ! empty( $post->post_views ) )
321 $sum += (int) $post->post_views;
322 }
323 }
324
325 // pass total views
326 $query->total_views = $sum;
327 }
328
329 return $posts;
330 }
331
332 /**
333 * Check whether date is valid.
334 *
335 * @param string $type
336 * @param int $year
337 * @param int $month
338 * @param int $day
339 * @param int $week
340 * @return bool
341 */
342 private function is_date_valid( $type, $year = 0, $month = 0, $day = 0, $week = 0 ) {
343 switch ( $type ) {
344 case 'y':
345 $bool = ( $year >= 1 && $year <= 32767 );
346 break;
347
348 case 'yw':
349 $bool = ( $year >= 1 && $year <= 32767 && $week >= 0 && $week <= 53 );
350 break;
351
352 case 'ym':
353 $bool = ( $year >= 1 && $year <= 32767 && $month >= 1 && $month <= 12 );
354 break;
355
356 case 'ymd':
357 $bool = checkdate( $month, $day, $year );
358 break;
359
360 case 'm':
361 $bool = ( $month >= 1 && $month <= 12 );
362 break;
363
364 case 'md':
365 $bool = ( $month >= 1 && $month <= 12 && $day >= 1 && $day <= 31 );
366 break;
367
368 case 'w':
369 $bool = ( $week >= 0 && $week <= 53 );
370 break;
371
372 case 'd':
373 $bool = ( $day >= 1 && $day <= 31 );
374 break;
375 }
376
377 return $bool;
378 }
379 }