PluginProbe
Stream – Activity Log & Audit Trail / 3.1
Stream – Activity Log & Audit Trail v3.1
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / classes / class-query.php

class-query.php in Stream – Activity Log & Audit Trail 3.1, at classes/class-query.php

355 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WP_Stream;
3
4 class Query {
5 /**
6 * @var DB
7 */
8 public $db;
9
10 /**
11 * Hold the number of records found
12 *
13 * @var int
14 */
15 public $found_records = 0;
16
17 /**
18 * Class constructor.
19 *
20 * @param DB $db The parent database class.
21 */
22 public function __construct( $db ) {
23 $this->db = $db;
24 }
25
26 /**
27 * Query records
28 *
29 * @param array Query args
30 *
31 * @return array Stream Records
32 */
33 public function query( $args ) {
34 global $wpdb;
35
36 $defaults = array(
37 // Search param
38 'search' => null,
39 'search_field' => 'summary',
40 'record_after' => null, // Deprecated, use date_after instead
41 // Date-based filters
42 'date' => null, // Ex: 2015-07-01
43 'date_from' => null, // Ex: 2015-07-01
44 'date_to' => null, // Ex: 2015-07-01
45 'date_after' => null, // Ex: 2015-07-01T15:19:21+00:00
46 'date_before' => null, // Ex: 2015-07-01T15:19:21+00:00
47 // Record ID filters
48 'record' => null,
49 'record__in' => array(),
50 'record__not_in' => array(),
51 // Pagination params
52 'records_per_page' => get_option( 'posts_per_page', 20 ),
53 'paged' => 1,
54 // Order
55 'order' => 'desc',
56 'orderby' => 'date',
57 // Fields selection
58 'fields' => array(),
59 );
60
61 // Additional property fields
62 $properties = array(
63 'user_id' => null,
64 'user_role' => null,
65 'ip' => null,
66 'object_id' => null,
67 'site_id' => null,
68 'blog_id' => null,
69 'connector' => null,
70 'context' => null,
71 'action' => null,
72 );
73
74 /**
75 * Filter allows additional query properties to be added
76 *
77 * @return array Array of query properties
78 */
79 $properties = apply_filters( 'wp_stream_query_properties', $properties );
80
81 // Add property fields to defaults, including their __in/__not_in variations
82 foreach ( $properties as $property => $default ) {
83 if ( ! isset( $defaults[ $property ] ) ) {
84 $defaults[ $property ] = $default;
85 }
86
87 $defaults[ "{$property}__in" ] = array();
88 $defaults[ "{$property}__not_in" ] = array();
89 }
90
91 $args = wp_parse_args( $args, $defaults );
92
93 /**
94 * Filter allows additional arguments to query $args
95 *
96 * @return array Array of query arguments
97 */
98 $args = apply_filters( 'wp_stream_query_args', $args );
99
100 $join = '';
101 $where = '';
102
103 /**
104 * PARSE CORE PARAMS
105 */
106 if ( is_numeric( $args['site_id'] ) ) {
107 $where .= $wpdb->prepare( " AND $wpdb->stream.site_id = %d", $args['site_id'] );
108 }
109
110 if ( is_numeric( $args['blog_id'] ) ) {
111 $where .= $wpdb->prepare( " AND $wpdb->stream.blog_id = %d", $args['blog_id'] );
112 }
113
114 if ( is_numeric( $args['object_id'] ) ) {
115 $where .= $wpdb->prepare( " AND $wpdb->stream.object_id = %d", $args['object_id'] );
116 }
117
118 if ( is_numeric( $args['user_id'] ) ) {
119 $where .= $wpdb->prepare( " AND $wpdb->stream.user_id = %d", $args['user_id'] );
120 }
121
122 if ( ! empty( $args['user_role'] ) ) {
123 $where .= $wpdb->prepare( " AND $wpdb->stream.user_role = %s", $args['user_role'] );
124 }
125
126 if ( ! empty( $args['search'] ) ) {
127 $field = ! empty( $args['search_field'] ) ? $args['search_field'] : 'summary';
128
129 // Sanitize field
130 $allowed_fields = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'created', 'summary', 'connector', 'context', 'action', 'ip' );
131 if ( in_array( $field, $allowed_fields, true ) ) {
132 $where .= $wpdb->prepare( " AND $wpdb->stream.{$field} LIKE %s", "%{$args['search']}%" ); // @codingStandardsIgnoreLine can't prepare column name
133 }
134 }
135
136 if ( ! empty( $args['connector'] ) ) {
137 $where .= $wpdb->prepare( " AND $wpdb->stream.connector = %s", $args['connector'] );
138 }
139
140 if ( ! empty( $args['context'] ) ) {
141 $where .= $wpdb->prepare( " AND $wpdb->stream.context = %s", $args['context'] );
142 }
143
144 if ( ! empty( $args['action'] ) ) {
145 $where .= $wpdb->prepare( " AND $wpdb->stream.action = %s", $args['action'] );
146 }
147
148 if ( ! empty( $args['ip'] ) ) {
149 $where .= $wpdb->prepare( " AND $wpdb->stream.ip = %s", wp_stream_filter_var( $args['ip'], FILTER_VALIDATE_IP ) );
150 }
151
152 /**
153 * PARSE DATE PARAM FAMILY
154 */
155 if ( ! empty( $args['date_from'] ) ) {
156 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_from'] . ' 00:00:00' ) ) );
157 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) >= %s", $date );
158 }
159
160 if ( ! empty( $args['date_to'] ) ) {
161 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_to'] . ' 23:59:59' ) ) );
162 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) <= %s", $date );
163 }
164
165 if ( ! empty( $args['date_after'] ) ) {
166 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_after'] ) ) );
167 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) > %s", $date );
168 }
169
170 if ( ! empty( $args['date_before'] ) ) {
171 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_before'] ) ) );
172 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) < %s", $date );
173 }
174
175 if ( ! empty( $args['date'] ) ) {
176 $args['date_from'] = date( 'Y-m-d', strtotime( $args['date'] ) ) . ' 00:00:00';
177 $args['date_to'] = date( 'Y-m-d', strtotime( $args['date'] ) ) . ' 23:59:59';
178 }
179
180 /**
181 * PARSE __IN PARAM FAMILY
182 */
183 $ins = array();
184
185 foreach ( $args as $arg => $value ) {
186 if ( '__in' === substr( $arg, -4 ) ) {
187 $ins[ $arg ] = $value;
188 }
189 }
190
191 if ( ! empty( $ins ) ) {
192 foreach ( $ins as $key => $value ) {
193 if ( empty( $value ) || ! is_array( $value ) ) {
194 continue;
195 }
196
197 $field = str_replace( array( 'record_', '__in' ), '', $key );
198 $field = empty( $field ) ? 'ID' : $field;
199 $type = is_numeric( array_shift( $value ) ) ? '%d' : '%s';
200
201 if ( ! empty( $value ) ) {
202 $format = '(' . join( ',', array_fill( 0, count( $value ), $type ) ) . ')';
203 $where .= $wpdb->prepare( " AND $wpdb->stream.%s IN {$format}", $field, $value ); // @codingStandardsIgnoreLine prepare okay
204 }
205 }
206 }
207
208 /**
209 * PARSE __NOT_IN PARAM FAMILY
210 */
211 $not_ins = array();
212
213 foreach ( $args as $arg => $value ) {
214 if ( '__not_in' === substr( $arg, -8 ) ) {
215 $not_ins[ $arg ] = $value;
216 }
217 }
218
219 if ( ! empty( $not_ins ) ) {
220 foreach ( $not_ins as $key => $value ) {
221 if ( empty( $value ) || ! is_array( $value ) ) {
222 continue;
223 }
224
225 $field = str_replace( array( 'record_', '__not_in' ), '', $key );
226 $field = empty( $field ) ? 'ID' : $field;
227 $type = is_numeric( array_shift( $value ) ) ? '%d' : '%s';
228
229 if ( ! empty( $value ) ) {
230 $format = '(' . join( ',', array_fill( 0, count( $value ), $type ) ) . ')';
231 $where .= $wpdb->prepare( " AND $wpdb->stream.%s NOT IN {$format}", $field, $value ); // @codingStandardsIgnoreLine prepare okay
232 }
233 }
234 }
235
236 /**
237 * PARSE PAGINATION PARAMS
238 */
239 $limits = '';
240 $page = absint( $args['paged'] );
241 $per_page = absint( $args['records_per_page'] );
242
243 if ( $per_page >= 0 ) {
244 $offset = absint( ( $page - 1 ) * $per_page );
245 $limits = "LIMIT {$offset}, {$per_page}";
246 }
247
248 /**
249 * PARSE ORDER PARAMS
250 */
251 $order = esc_sql( $args['order'] );
252 $orderby = esc_sql( $args['orderby'] );
253 $orderable = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'summary', 'created', 'connector', 'context', 'action' );
254
255 if ( in_array( $orderby, $orderable, true ) ) {
256 $orderby = sprintf( '%s.%s', $wpdb->stream, $orderby );
257 } elseif ( 'meta_value_num' === $orderby && ! empty( $args['meta_key'] ) ) {
258 $orderby = "CAST($wpdb->streammeta.meta_value AS SIGNED)";
259 } elseif ( 'meta_value' === $orderby && ! empty( $args['meta_key'] ) ) {
260 $orderby = "$wpdb->streammeta.meta_value";
261 } else {
262 $orderby = "$wpdb->stream.ID";
263 }
264
265 $orderby = "ORDER BY {$orderby} {$order}";
266
267 /**
268 * PARSE FIELDS PARAMETER
269 */
270 $fields = (array) $args['fields'];
271 $selects = array();
272
273 if ( ! empty( $fields ) ) {
274 foreach ( $fields as $field ) {
275 // We'll query the meta table later
276 if ( 'meta' === $field ) {
277 continue;
278 }
279
280 $selects[] = sprintf( "$wpdb->stream.%s", $field );
281 }
282 } else {
283 $selects[] = "$wpdb->stream.*";
284 }
285
286 $select = implode( ', ', $selects );
287
288 /**
289 * BUILD THE FINAL QUERY
290 */
291 $query = "SELECT SQL_CALC_FOUND_ROWS {$select}
292 FROM $wpdb->stream
293 {$join}
294 WHERE 1=1 {$where}
295 {$orderby}
296 {$limits}";
297
298 /**
299 * Filter allows the final query to be modified before execution
300 *
301 * @param string $query
302 * @param array $args
303 *
304 * @return string
305 */
306 $query = apply_filters( 'wp_stream_db_query', $query, $args );
307
308 /**
309 * QUERY THE DATABASE FOR RESULTS
310 */
311 $results = $wpdb->get_results( $query ); // @codingStandardsIgnoreLine $query already prepared
312
313 // Hold the number of records found
314 $this->found_records = absint( $wpdb->get_var( 'SELECT FOUND_ROWS()' ) );
315
316 // Add meta to the records, when applicable
317 if ( empty( $fields ) || in_array( 'meta', $fields, true ) ) {
318 $results = $this->add_record_meta( $results );
319 }
320
321 return (array) $results;
322 }
323
324 /**
325 * Add meta to a set of records
326 *
327 * @param array $records
328 *
329 * @return array
330 */
331 public function add_record_meta( $records ) {
332 global $wpdb;
333
334 $record_ids = array_map( 'absint', wp_list_pluck( $records, 'ID' ) );
335
336 if ( empty( $record_ids ) ) {
337 return (array) $records;
338 }
339
340 $sql_meta = sprintf(
341 "SELECT * FROM $wpdb->streammeta WHERE record_id IN ( %s )",
342 implode( ',', $record_ids )
343 );
344
345 $meta = $wpdb->get_results( $sql_meta ); // @codingStandardsIgnoreLine prepare okay
346 $ids_f = array_flip( $record_ids );
347
348 foreach ( $meta as $meta_record ) {
349 $records[ $ids_f[ $meta_record->record_id ] ]->meta[ $meta_record->meta_key ] = maybe_unserialize( $meta_record->meta_value );
350 }
351
352 return (array) $records;
353 }
354 }
355