PluginProbe
Stream – Activity Log & Audit Trail / 3.0.1
Stream – Activity Log & Audit Trail v3.0.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.0.1, at classes/class-query.php

350 lines 9.1 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 $where .= $wpdb->prepare( " AND $wpdb->stream.{$field} LIKE %s", "%{$args['search']}%" );
129 }
130
131 if ( ! empty( $args['connector'] ) ) {
132 $where .= $wpdb->prepare( " AND $wpdb->stream.connector = %s", $args['connector'] );
133 }
134
135 if ( ! empty( $args['context'] ) ) {
136 $where .= $wpdb->prepare( " AND $wpdb->stream.context = %s", $args['context'] );
137 }
138
139 if ( ! empty( $args['action'] ) ) {
140 $where .= $wpdb->prepare( " AND $wpdb->stream.action = %s", $args['action'] );
141 }
142
143 if ( ! empty( $args['ip'] ) ) {
144 $where .= $wpdb->prepare( " AND $wpdb->stream.ip = %s", wp_stream_filter_var( $args['ip'], FILTER_VALIDATE_IP ) );
145 }
146
147 /**
148 * PARSE DATE PARAM FAMILY
149 */
150 if ( ! empty( $args['date_from'] ) ) {
151 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_from'] . ' 00:00:00' ) ) );
152 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) >= %s", $date );
153 }
154
155 if ( ! empty( $args['date_to'] ) ) {
156 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_to'] . ' 23:59:59' ) ) );
157 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) <= %s", $date );
158 }
159
160 if ( ! empty( $args['date_after'] ) ) {
161 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_after'] ) ) );
162 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) > %s", $date );
163 }
164
165 if ( ! empty( $args['date_before'] ) ) {
166 $date = get_gmt_from_date( date( 'Y-m-d H:i:s', strtotime( $args['date_before'] ) ) );
167 $where .= $wpdb->prepare( " AND DATE($wpdb->stream.created) < %s", $date );
168 }
169
170 if ( ! empty( $args['date'] ) ) {
171 $args['date_from'] = date( 'Y-m-d', strtotime( $args['date'] ) ) . ' 00:00:00';
172 $args['date_to'] = date( 'Y-m-d', strtotime( $args['date'] ) ) . ' 23:59:59';
173 }
174
175 /**
176 * PARSE __IN PARAM FAMILY
177 */
178 $ins = array();
179
180 foreach ( $args as $arg => $value ) {
181 if ( '__in' === substr( $arg, -4 ) ) {
182 $ins[ $arg ] = $value;
183 }
184 }
185
186 if ( ! empty( $ins ) ) {
187 foreach ( $ins as $key => $value ) {
188 if ( empty( $value ) || ! is_array( $value ) ) {
189 continue;
190 }
191
192 $field = str_replace( array( 'record_', '__in' ), '', $key );
193 $field = empty( $field ) ? 'ID' : $field;
194 $type = is_numeric( array_shift( $value ) ) ? '%d' : '%s';
195
196 if ( ! empty( $value ) ) {
197 $format = '(' . join( ',', array_fill( 0, count( $value ), $type ) ) . ')';
198 $where .= $wpdb->prepare( " AND $wpdb->stream.%s IN {$format}", $field, $value );
199 }
200 }
201 }
202
203 /**
204 * PARSE __NOT_IN PARAM FAMILY
205 */
206 $not_ins = array();
207
208 foreach ( $args as $arg => $value ) {
209 if ( '__not_in' === substr( $arg, -8 ) ) {
210 $not_ins[ $arg ] = $value;
211 }
212 }
213
214 if ( ! empty( $not_ins ) ) {
215 foreach ( $not_ins as $key => $value ) {
216 if ( empty( $value ) || ! is_array( $value ) ) {
217 continue;
218 }
219
220 $field = str_replace( array( 'record_', '__not_in' ), '', $key );
221 $field = empty( $field ) ? 'ID' : $field;
222 $type = is_numeric( array_shift( $value ) ) ? '%d' : '%s';
223
224 if ( ! empty( $value ) ) {
225 $format = '(' . join( ',', array_fill( 0, count( $value ), $type ) ) . ')';
226 $where .= $wpdb->prepare( " AND $wpdb->stream.%s NOT IN {$format}", $field, $value );
227 }
228 }
229 }
230
231 /**
232 * PARSE PAGINATION PARAMS
233 */
234 $limits = '';
235 $page = absint( $args['paged'] );
236 $per_page = absint( $args['records_per_page'] );
237
238 if ( $per_page >= 0 ) {
239 $offset = absint( ( $page - 1 ) * $per_page );
240 $limits = "LIMIT {$offset}, {$per_page}";
241 }
242
243 /**
244 * PARSE ORDER PARAMS
245 */
246 $order = esc_sql( $args['order'] );
247 $orderby = esc_sql( $args['orderby'] );
248 $orderable = array( 'ID', 'site_id', 'blog_id', 'object_id', 'user_id', 'user_role', 'summary', 'created', 'connector', 'context', 'action' );
249
250 if ( in_array( $orderby, $orderable ) ) {
251 $orderby = sprintf( '%s.%s', $wpdb->stream, $orderby );
252 } elseif ( 'meta_value_num' === $orderby && ! empty( $args['meta_key'] ) ) {
253 $orderby = "CAST($wpdb->streammeta.meta_value AS SIGNED)";
254 } elseif ( 'meta_value' === $orderby && ! empty( $args['meta_key'] ) ) {
255 $orderby = "$wpdb->streammeta.meta_value";
256 } else {
257 $orderby = "$wpdb->stream.ID";
258 }
259
260 $orderby = "ORDER BY {$orderby} {$order}";
261
262 /**
263 * PARSE FIELDS PARAMETER
264 */
265 $fields = (array) $args['fields'];
266 $selects = array();
267
268 if ( ! empty( $fields ) ) {
269 foreach ( $fields as $field ) {
270 // We'll query the meta table later
271 if ( 'meta' === $field ) {
272 continue;
273 }
274
275 $selects[] = sprintf( "$wpdb->stream.%s", $field );
276 }
277 } else {
278 $selects[] = "$wpdb->stream.*";
279 }
280
281 $select = implode( ', ', $selects );
282
283 /**
284 * BUILD THE FINAL QUERY
285 */
286 $query = "SELECT SQL_CALC_FOUND_ROWS {$select}
287 FROM $wpdb->stream
288 {$join}
289 WHERE 1=1 {$where}
290 {$orderby}
291 {$limits}";
292
293 /**
294 * Filter allows the final query to be modified before execution
295 *
296 * @param string $query
297 * @param array $args
298 *
299 * @return string
300 */
301 $query = apply_filters( 'wp_stream_db_query', $query, $args );
302
303 /**
304 * QUERY THE DATABASE FOR RESULTS
305 */
306 $results = $wpdb->get_results( $query );
307
308 // Hold the number of records found
309 $this->found_records = absint( $wpdb->get_var( 'SELECT FOUND_ROWS()' ) );
310
311 // Add meta to the records, when applicable
312 if ( empty( $fields ) || in_array( 'meta', $fields ) ) {
313 $results = $this->add_record_meta( $results );
314 }
315
316 return (array) $results;
317 }
318
319 /**
320 * Add meta to a set of records
321 *
322 * @param array $records
323 *
324 * @return array
325 */
326 public function add_record_meta( $records ) {
327 global $wpdb;
328
329 $record_ids = array_map( 'absint', wp_list_pluck( $records, 'ID' ) );
330
331 if ( empty( $record_ids ) ) {
332 return (array) $records;
333 }
334
335 $sql_meta = sprintf(
336 "SELECT * FROM $wpdb->streammeta WHERE record_id IN ( %s )",
337 implode( ',', $record_ids )
338 );
339
340 $meta = $wpdb->get_results( $sql_meta );
341 $ids_f = array_flip( $record_ids );
342
343 foreach ( $meta as $meta_record ) {
344 $records[ $ids_f[ $meta_record->record_id ] ]->meta[ $meta_record->meta_key ] = maybe_unserialize( $meta_record->meta_value );
345 }
346
347 return (array) $records;
348 }
349 }
350