1 | <?php |
---|
2 | |
---|
3 | // Exit if accessed directly |
---|
4 | if ( !defined( 'ABSPATH' ) ) exit; |
---|
5 | |
---|
6 | /** |
---|
7 | * BuddyPress User Query class |
---|
8 | * |
---|
9 | * Used for querying users in a BuddyPress context, in situations where |
---|
10 | * WP_User_Query won't do the trick: Member directories, the Friends component, |
---|
11 | * etc. |
---|
12 | * |
---|
13 | * Accepted parameters: |
---|
14 | * type - Determines sort order. Select from 'newest', 'active', |
---|
15 | * 'online', 'random', 'popular', 'alphabetical' |
---|
16 | * per_page - Number of results to return |
---|
17 | * page - Page offset (together with per_page) |
---|
18 | * user_id - Pass a single numeric user id to limit results to |
---|
19 | * friends of that user. Requires the Friends component |
---|
20 | * search_terms - Terms to search by. Search happens across xprofile |
---|
21 | * fields. Requires XProfile component |
---|
22 | * include - An array or comma-separated list of user ids. Results |
---|
23 | * will be limited to users in this list |
---|
24 | * exclude - An array or comma-separated list of user ids. Results |
---|
25 | * will not include any users in this list |
---|
26 | * user_ids - An array or comma-separated list of user ids. When |
---|
27 | * this parameter is passed, it will override all other |
---|
28 | * parameters; BP User objects will be constructed using |
---|
29 | * these IDs only |
---|
30 | * meta_key - Limit results to users that have usermeta associated |
---|
31 | * with this meta_key. Usually used with meta_value |
---|
32 | * meta_value - When used with meta_key, limits results to users whose |
---|
33 | * usermeta value associated with meta_key matches |
---|
34 | * meta_value |
---|
35 | * populate_extras - Boolean. True if you want to fetch extra metadata about |
---|
36 | * returned users, such as total group and friend counts |
---|
37 | * count_total - Determines how BP_User_Query will do a count of total |
---|
38 | * users matching the other filter criteria. Default value |
---|
39 | * is 'count_query', which does a separate SELECT COUNT |
---|
40 | * query to determine the total. 'sql_count_found_rows' |
---|
41 | * uses SQL_COUNT_FOUND_ROWS and SELECT FOUND_ROWS(). Pass |
---|
42 | * an empty string to skip the total user count query. |
---|
43 | * |
---|
44 | * @since BuddyPress (1.7) |
---|
45 | */ |
---|
46 | class BP_User_Query { |
---|
47 | |
---|
48 | /** Variables *************************************************************/ |
---|
49 | |
---|
50 | /** |
---|
51 | * Array of variables to query with |
---|
52 | * |
---|
53 | * @since BuddyPress (1.7) |
---|
54 | * @var array |
---|
55 | */ |
---|
56 | public $query_vars = array(); |
---|
57 | |
---|
58 | /** |
---|
59 | * List of found users and their respective data |
---|
60 | * |
---|
61 | * @since BuddyPress (1.7) |
---|
62 | * @access public To allow components to manipulate them |
---|
63 | * @var array |
---|
64 | */ |
---|
65 | public $results = array(); |
---|
66 | |
---|
67 | /** |
---|
68 | * Total number of found users for the current query |
---|
69 | * |
---|
70 | * @since BuddyPress (1.7) |
---|
71 | * @access public To allow components to manipulate it |
---|
72 | * @var int |
---|
73 | */ |
---|
74 | public $total_users = 0; |
---|
75 | |
---|
76 | /** |
---|
77 | * List of found user ID's |
---|
78 | * |
---|
79 | * @since BuddyPress (1.7) |
---|
80 | * @access public To allow components to manipulate it |
---|
81 | * @var array |
---|
82 | */ |
---|
83 | public $user_ids = array(); |
---|
84 | |
---|
85 | /** |
---|
86 | * SQL clauses for the user ID query |
---|
87 | * |
---|
88 | * @since BuddyPress (1.7) |
---|
89 | * @access public To allow components to manipulate it |
---|
90 | * @var array() |
---|
91 | */ |
---|
92 | public $uid_clauses = array(); |
---|
93 | |
---|
94 | /** |
---|
95 | * SQL database column name to order by |
---|
96 | * |
---|
97 | * @since BuddyPress (1.7) |
---|
98 | * @var string |
---|
99 | */ |
---|
100 | public $uid_name = ''; |
---|
101 | |
---|
102 | /** |
---|
103 | * Standard response when the query should not return any rows. |
---|
104 | * |
---|
105 | * @since BuddyPress (1.7) |
---|
106 | * @access protected |
---|
107 | * @var string |
---|
108 | */ |
---|
109 | protected $no_results = array( 'join' => '', 'where' => '0 = 1' ); |
---|
110 | |
---|
111 | |
---|
112 | /** Methods ***************************************************************/ |
---|
113 | |
---|
114 | /** |
---|
115 | * Constructor |
---|
116 | * |
---|
117 | * @since BuddyPress (1.7) |
---|
118 | * |
---|
119 | * @param string|array $query The query variables |
---|
120 | */ |
---|
121 | public function __construct( $query = null ) { |
---|
122 | if ( ! empty( $query ) ) { |
---|
123 | $this->query_vars = wp_parse_args( $query, array( |
---|
124 | 'type' => 'newest', |
---|
125 | 'per_page' => 0, |
---|
126 | 'page' => 1, |
---|
127 | 'user_id' => 0, |
---|
128 | 'search_terms' => false, |
---|
129 | 'include' => false, |
---|
130 | 'exclude' => false, |
---|
131 | 'user_ids' => false, |
---|
132 | 'meta_key' => false, |
---|
133 | 'meta_value' => false, |
---|
134 | 'populate_extras' => true, |
---|
135 | 'count_total' => 'count_query' |
---|
136 | ) ); |
---|
137 | |
---|
138 | // Plugins can use this filter to modify query args |
---|
139 | // before the query is constructed |
---|
140 | do_action_ref_array( 'bp_pre_user_query_construct', array( &$this ) ); |
---|
141 | |
---|
142 | // Get user ids |
---|
143 | // If the user_ids param is present, we skip the query |
---|
144 | if ( false !== $this->query_vars['user_ids'] ) { |
---|
145 | $this->user_ids = wp_parse_id_list( $this->query_vars['user_ids'] ); |
---|
146 | } else { |
---|
147 | $this->prepare_user_ids_query(); |
---|
148 | $this->do_user_ids_query(); |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | // Bail if no user IDs were found |
---|
153 | if ( empty( $this->user_ids ) ) { |
---|
154 | return; |
---|
155 | } |
---|
156 | |
---|
157 | // Fetch additional data. First, using WP_User_Query |
---|
158 | $this->do_wp_user_query(); |
---|
159 | |
---|
160 | // Get BuddyPress specific user data |
---|
161 | $this->populate_extras(); |
---|
162 | } |
---|
163 | |
---|
164 | /** |
---|
165 | * Prepare the query for user_ids |
---|
166 | * |
---|
167 | * @since BuddyPress (1.7) |
---|
168 | */ |
---|
169 | public function prepare_user_ids_query() { |
---|
170 | global $wpdb, $bp; |
---|
171 | |
---|
172 | // Default query variables used here |
---|
173 | $type = ''; |
---|
174 | $per_page = 0; |
---|
175 | $page = 1; |
---|
176 | $user_id = 0; |
---|
177 | $include = false; |
---|
178 | $search_terms = false; |
---|
179 | $exclude = false; |
---|
180 | $meta_key = false; |
---|
181 | $meta_value = false; |
---|
182 | |
---|
183 | extract( $this->query_vars ); |
---|
184 | |
---|
185 | // Setup the main SQL query container |
---|
186 | $sql = array( |
---|
187 | 'select' => '', |
---|
188 | 'where' => array(), |
---|
189 | 'orderby' => '', |
---|
190 | 'order' => '', |
---|
191 | 'limit' => '' |
---|
192 | ); |
---|
193 | |
---|
194 | /** TYPE **************************************************************/ |
---|
195 | |
---|
196 | // Determines the sort order, which means it also determines where the |
---|
197 | // user IDs are drawn from (the SELECT and WHERE statements) |
---|
198 | switch ( $type ) { |
---|
199 | |
---|
200 | // 'online' query happens against the last_activity usermeta key |
---|
201 | case 'online' : |
---|
202 | $this->uid_name = 'user_id'; |
---|
203 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u"; |
---|
204 | $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) ); |
---|
205 | $sql['where'][] = 'u.meta_value >= DATE_SUB( UTC_TIMESTAMP(), INTERVAL 5 MINUTE )'; |
---|
206 | $sql['orderby'] = "ORDER BY u.meta_value"; |
---|
207 | $sql['order'] = "DESC"; |
---|
208 | |
---|
209 | break; |
---|
210 | |
---|
211 | // 'active', 'newest', and 'random' queries |
---|
212 | // all happen against the last_activity usermeta key |
---|
213 | case 'active' : |
---|
214 | case 'newest' : |
---|
215 | case 'random' : |
---|
216 | $this->uid_name = 'user_id'; |
---|
217 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u"; |
---|
218 | $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) ); |
---|
219 | |
---|
220 | if ( 'newest' == $type ) { |
---|
221 | $sql['orderby'] = "ORDER BY u.user_id"; |
---|
222 | $sql['order'] = "DESC"; |
---|
223 | } else if ( 'random' == $type ) { |
---|
224 | $sql['orderby'] = "ORDER BY rand()"; |
---|
225 | } else { |
---|
226 | $sql['orderby'] = "ORDER BY u.meta_value"; |
---|
227 | $sql['order'] = "DESC"; |
---|
228 | } |
---|
229 | |
---|
230 | break; |
---|
231 | |
---|
232 | // 'popular' sorts by the 'total_friend_count' usermeta |
---|
233 | case 'popular' : |
---|
234 | $this->uid_name = 'user_id'; |
---|
235 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->usermeta} u"; |
---|
236 | $sql['where'][] = $wpdb->prepare( "u.meta_key = %s", bp_get_user_meta_key( 'total_friend_count' ) ); |
---|
237 | $sql['orderby'] = "ORDER BY u.meta_value"; |
---|
238 | $sql['order'] = "DESC"; |
---|
239 | |
---|
240 | break; |
---|
241 | |
---|
242 | // 'alphabetical' sorts depend on the xprofile setup |
---|
243 | case 'alphabetical' : |
---|
244 | |
---|
245 | // We prefer to do alphabetical sorts against the display_name field |
---|
246 | // of wp_users, because the table is smaller and better indexed. We |
---|
247 | // can do so if xprofile sync is enabled, or if xprofile is inactive. |
---|
248 | // |
---|
249 | // @todo remove need for bp_is_active() check |
---|
250 | if ( ! bp_disable_profile_sync() || ! bp_is_active( 'xprofile' ) ) { |
---|
251 | $this->uid_name = 'ID'; |
---|
252 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->users} u"; |
---|
253 | $sql['orderby'] = "ORDER BY u.display_name"; |
---|
254 | $sql['order'] = "ASC"; |
---|
255 | |
---|
256 | // When profile sync is disabled, alphabetical sorts must happen against |
---|
257 | // the xprofile table |
---|
258 | } else { |
---|
259 | $fullname_field_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->profile->table_name_fields} WHERE name = %s", bp_xprofile_fullname_field_name() ) ); |
---|
260 | |
---|
261 | $this->uid_name = 'user_id'; |
---|
262 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$bp->profile->table_name_data} u"; |
---|
263 | $sql['where'][] = "u.field_id = {$fullname_field_id}"; |
---|
264 | $sql['orderby'] = "ORDER BY u.value"; |
---|
265 | $sql['order'] = "ASC"; |
---|
266 | } |
---|
267 | |
---|
268 | break; |
---|
269 | |
---|
270 | // Any other 'type' falls through |
---|
271 | default : |
---|
272 | $this->uid_name = 'ID'; |
---|
273 | $sql['select'] = "SELECT DISTINCT u.{$this->uid_name} as id FROM {$wpdb->users} u"; |
---|
274 | |
---|
275 | // In this case, we assume that a plugin is |
---|
276 | // handling order, so we leave those clauses |
---|
277 | // blank |
---|
278 | |
---|
279 | break; |
---|
280 | } |
---|
281 | |
---|
282 | /** WHERE *************************************************************/ |
---|
283 | |
---|
284 | // 'include' - User ids to include in the results |
---|
285 | if ( false !== $include ) { |
---|
286 | $include = wp_parse_id_list( $include ); |
---|
287 | $include_ids = $wpdb->escape( implode( ',', (array) $include ) ); |
---|
288 | $sql['where'][] = "u.{$this->uid_name} IN ({$include_ids})"; |
---|
289 | } |
---|
290 | |
---|
291 | // 'exclude' - User ids to exclude from the results |
---|
292 | if ( false !== $exclude ) { |
---|
293 | $exclude = wp_parse_id_list( $exclude ); |
---|
294 | $exclude_ids = $wpdb->escape( implode( ',', (array) $exclude ) ); |
---|
295 | $sql['where'][] = "u.{$this->uid_name} NOT IN ({$exclude_ids})"; |
---|
296 | } |
---|
297 | |
---|
298 | // 'user_id' - When a user id is passed, limit to the friends of the user |
---|
299 | // Only parse this if no 'include' param is passed, to account for |
---|
300 | // friend request queries |
---|
301 | // @todo remove need for bp_is_active() check |
---|
302 | // if ( empty( $include ) && ! empty( $user_id ) && bp_is_active( 'friends' ) ) { |
---|
303 | if ( ! empty( $user_id ) && bp_is_active( 'friends' ) ) { |
---|
304 | $friend_ids = friends_get_friend_user_ids( $user_id ); |
---|
305 | $friend_ids = $wpdb->escape( implode( ',', (array) $friend_ids ) ); |
---|
306 | |
---|
307 | if ( ! empty( $friend_ids ) ) { |
---|
308 | $sql['where'][] = "u.{$this->uid_name} IN ({$friend_ids})"; |
---|
309 | |
---|
310 | // If the user has no friends, and we're not including specific users, make sure the query returns null |
---|
311 | // } elseif ( empty( $include ) ) { |
---|
312 | } else { |
---|
313 | $sql['where'][] = $this->no_results['where']; |
---|
314 | } |
---|
315 | } |
---|
316 | |
---|
317 | /** Search Terms ******************************************************/ |
---|
318 | |
---|
319 | // 'search_terms' searches the xprofile fields |
---|
320 | // To avoid global joins, do a separate query |
---|
321 | // @todo remove need for bp_is_active() check |
---|
322 | if ( false !== $search_terms && bp_is_active( 'xprofile' ) ) { |
---|
323 | $found_user_ids = $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->profile->table_name_data} WHERE value LIKE %s", '%%' . like_escape( $search_terms ) . '%%' ) ); |
---|
324 | |
---|
325 | if ( ! empty( $found_user_ids ) ) { |
---|
326 | $sql['where'][] = "u.{$this->uid_name} IN (" . implode( ',', wp_parse_id_list( $found_user_ids ) ) . ")"; |
---|
327 | } else { |
---|
328 | $sql['where'][] = $this->no_results['where']; |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | // 'meta_key', 'meta_value' allow usermeta search |
---|
333 | // To avoid global joins, do a separate query |
---|
334 | if ( false !== $meta_key ) { |
---|
335 | $meta_sql = $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = %s", $meta_key ); |
---|
336 | |
---|
337 | if ( false !== $meta_value ) { |
---|
338 | $meta_sql .= $wpdb->prepare( " AND meta_value = %s", $meta_value ); |
---|
339 | } |
---|
340 | |
---|
341 | $found_user_ids = $wpdb->get_col( $meta_sql ); |
---|
342 | |
---|
343 | if ( ! empty( $found_user_ids ) ) { |
---|
344 | $sql['where'][] = "u.{$this->uid_name} IN (" . implode( ',', wp_parse_id_list( $found_user_ids ) ) . ")"; |
---|
345 | } |
---|
346 | } |
---|
347 | |
---|
348 | // 'per_page', 'page' - handles LIMIT |
---|
349 | if ( !empty( $per_page ) && !empty( $page ) ) { |
---|
350 | $sql['limit'] = $wpdb->prepare( "LIMIT %d, %d", intval( ( $page - 1 ) * $per_page ), intval( $per_page ) ); |
---|
351 | } else { |
---|
352 | $sql['limit'] = ''; |
---|
353 | } |
---|
354 | |
---|
355 | // Assemble the query chunks |
---|
356 | $this->uid_clauses['select'] = $sql['select']; |
---|
357 | $this->uid_clauses['where'] = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : ''; |
---|
358 | $this->uid_clauses['orderby'] = $sql['orderby']; |
---|
359 | $this->uid_clauses['order'] = $sql['order']; |
---|
360 | $this->uid_clauses['limit'] = $sql['limit']; |
---|
361 | |
---|
362 | do_action_ref_array( 'bp_pre_user_query', array( &$this ) ); |
---|
363 | } |
---|
364 | |
---|
365 | /** |
---|
366 | * Perform a database query to specifically get only user IDs, using |
---|
367 | * existing query variables set previously in the constructor. |
---|
368 | * |
---|
369 | * Also used to quickly perform user total counts. |
---|
370 | * |
---|
371 | * @since BuddyPress (1.7) |
---|
372 | */ |
---|
373 | public function do_user_ids_query() { |
---|
374 | global $wpdb; |
---|
375 | |
---|
376 | // If counting using SQL_CALC_FOUND_ROWS, set it up here |
---|
377 | if ( 'sql_calc_found_rows' == $this->query_vars['count_total'] ) { |
---|
378 | $this->uid_clauses['select'] = str_replace( 'SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $this->uid_clauses['select'] ); |
---|
379 | } |
---|
380 | |
---|
381 | // Get the specific user ids |
---|
382 | $this->user_ids = $wpdb->get_col( "{$this->uid_clauses['select']} {$this->uid_clauses['where']} {$this->uid_clauses['orderby']} {$this->uid_clauses['order']} {$this->uid_clauses['limit']}" ); |
---|
383 | |
---|
384 | // Get the total user count |
---|
385 | if ( 'sql_calc_found_rows' == $this->query_vars['count_total'] ) { |
---|
386 | $this->total_users = $wpdb->get_var( apply_filters( 'bp_found_user_query', "SELECT FOUND_ROWS()", $this ) ); |
---|
387 | } elseif ( 'count_query' == $this->query_vars['count_total'] ) { |
---|
388 | $count_select = preg_replace( '/^SELECT.*?FROM (\S+) u/', "SELECT COUNT(DISTINCT u.{$this->uid_name}) FROM $1 u", $this->uid_clauses['select'] ); |
---|
389 | $this->total_users = $wpdb->get_var( apply_filters( 'bp_found_user_query', "{$count_select} {$this->uid_clauses['where']}", $this ) ); |
---|
390 | } |
---|
391 | } |
---|
392 | |
---|
393 | /** |
---|
394 | * Perform a database query using the WP_User_Query() object, using existing |
---|
395 | * fields, variables, and user ID's set previously in this class. |
---|
396 | * |
---|
397 | * @since BuddyPress (1.7) |
---|
398 | */ |
---|
399 | public function do_wp_user_query() { |
---|
400 | $wp_user_query = new WP_User_Query( apply_filters( 'bp_wp_user_query_args', array( |
---|
401 | |
---|
402 | // Relevant |
---|
403 | 'fields' => array( 'ID', 'user_registered', 'user_login', 'user_nicename', 'display_name', 'user_email' ), |
---|
404 | 'include' => $this->user_ids, |
---|
405 | |
---|
406 | // Overrides |
---|
407 | 'blog_id' => 0, // BP does not require blog roles |
---|
408 | 'count_total' => false // We already have a count |
---|
409 | |
---|
410 | ), $this ) ); |
---|
411 | |
---|
412 | // Reindex for easier matching |
---|
413 | $r = array(); |
---|
414 | foreach ( $wp_user_query->results as $u ) { |
---|
415 | $r[ $u->ID ] = $u; |
---|
416 | } |
---|
417 | |
---|
418 | // Match up to the user ids from the main query |
---|
419 | foreach ( $this->user_ids as $uid ) { |
---|
420 | if ( isset( $r[ $uid ] ) ) { |
---|
421 | $this->results[ $uid ] = $r[ $uid ]; |
---|
422 | |
---|
423 | // The BP template functions expect an 'id' |
---|
424 | // (as opposed to 'ID') property |
---|
425 | $this->results[ $uid ]->id = $uid; |
---|
426 | } |
---|
427 | } |
---|
428 | } |
---|
429 | |
---|
430 | /** |
---|
431 | * Perform a database query to populate any extra metadata we might need. |
---|
432 | * Different components will hook into the 'bp_user_query_populate_extras' |
---|
433 | * action to loop in the things they want. |
---|
434 | * |
---|
435 | * @since BuddyPress (1.7) |
---|
436 | * |
---|
437 | * @global BuddyPress $bp |
---|
438 | * @global WPDB $wpdb |
---|
439 | * @return |
---|
440 | */ |
---|
441 | public function populate_extras() { |
---|
442 | global $wpdb; |
---|
443 | |
---|
444 | // Bail if no users |
---|
445 | if ( empty( $this->user_ids ) || empty( $this->results ) ) { |
---|
446 | return; |
---|
447 | } |
---|
448 | |
---|
449 | // Bail if the populate_extras flag is set to false |
---|
450 | // In the case of the 'popular' sort type, we force |
---|
451 | // populate_extras to true, because we need the friend counts |
---|
452 | if ( 'popular' == $this->query_vars['type'] ) { |
---|
453 | $this->query_vars['populate_extras'] = 1; |
---|
454 | } |
---|
455 | |
---|
456 | if ( ! (bool) $this->query_vars['populate_extras'] ) { |
---|
457 | return; |
---|
458 | } |
---|
459 | |
---|
460 | // Turn user ID's into a query-usable, comma separated value |
---|
461 | $user_ids_sql = implode( ',', wp_parse_id_list( $this->user_ids ) ); |
---|
462 | |
---|
463 | /** |
---|
464 | * Use this action to independently populate your own custom extras. |
---|
465 | * |
---|
466 | * Note that anything you add here should query using $user_ids_sql, to |
---|
467 | * avoid running multiple queries per user in the loop. |
---|
468 | * |
---|
469 | * Two BuddyPress components currently do this: |
---|
470 | * - XProfile: To override display names |
---|
471 | * - Friends: To set whether or not a user is the current users friend |
---|
472 | * |
---|
473 | * @see bp_xprofile_filter_user_query_populate_extras() |
---|
474 | * @see bp_friends_filter_user_query_populate_extras() |
---|
475 | */ |
---|
476 | do_action_ref_array( 'bp_user_query_populate_extras', array( $this, $user_ids_sql ) ); |
---|
477 | |
---|
478 | // Fetch usermeta data |
---|
479 | // We want the three following pieces of info from usermeta: |
---|
480 | // - friend count |
---|
481 | // - last activity |
---|
482 | // - latest update |
---|
483 | $total_friend_count_key = bp_get_user_meta_key( 'total_friend_count' ); |
---|
484 | $last_activity_key = bp_get_user_meta_key( 'last_activity' ); |
---|
485 | $bp_latest_update_key = bp_get_user_meta_key( 'bp_latest_update' ); |
---|
486 | |
---|
487 | // total_friend_count must be set for each user, even if its |
---|
488 | // value is 0 |
---|
489 | foreach ( $this->results as $uindex => $user ) { |
---|
490 | $this->results[$uindex]->total_friend_count = 0; |
---|
491 | } |
---|
492 | |
---|
493 | // Create, prepare, and run the seperate usermeta query |
---|
494 | $user_metas = $wpdb->get_results( $wpdb->prepare( "SELECT user_id, meta_key, meta_value FROM {$wpdb->usermeta} WHERE meta_key IN (%s,%s,%s) AND user_id IN ({$user_ids_sql})", $total_friend_count_key, $last_activity_key, $bp_latest_update_key ) ); |
---|
495 | |
---|
496 | // The $members_template global expects the index key to be different |
---|
497 | // from the meta_key in some cases, so we rejig things here. |
---|
498 | foreach ( $user_metas as $user_meta ) { |
---|
499 | switch ( $user_meta->meta_key ) { |
---|
500 | case $total_friend_count_key : |
---|
501 | $key = 'total_friend_count'; |
---|
502 | break; |
---|
503 | |
---|
504 | case $last_activity_key : |
---|
505 | $key = 'last_activity'; |
---|
506 | break; |
---|
507 | |
---|
508 | case $bp_latest_update_key : |
---|
509 | $key = 'latest_update'; |
---|
510 | break; |
---|
511 | } |
---|
512 | |
---|
513 | if ( isset( $this->results[ $user_meta->user_id ] ) ) { |
---|
514 | $this->results[ $user_meta->user_id ]->{$key} = $user_meta->meta_value; |
---|
515 | } |
---|
516 | } |
---|
517 | |
---|
518 | // When meta_key or meta_value have been passed to the query, |
---|
519 | // fetch the resulting values for use in the template functions |
---|
520 | if ( ! empty( $this->query_vars['meta_key'] ) ) { |
---|
521 | $meta_sql = array( |
---|
522 | 'select' => "SELECT user_id, meta_key, meta_value", |
---|
523 | 'from' => "FROM $wpdb->usermeta", |
---|
524 | 'where' => $wpdb->prepare( "WHERE meta_key = %s", $this->query_vars['meta_key'] ) |
---|
525 | ); |
---|
526 | |
---|
527 | if ( false !== $this->query_vars['meta_value'] ) { |
---|
528 | $meta_sql['where'] .= $wpdb->prepare( " AND meta_value = %s", $this->query_vars['meta_value'] ); |
---|
529 | } |
---|
530 | |
---|
531 | $metas = $wpdb->get_results( "{$meta_sql['select']} {$meta_sql['from']} {$meta_sql['where']}" ); |
---|
532 | |
---|
533 | if ( ! empty( $metas ) ) { |
---|
534 | foreach ( $metas as $meta ) { |
---|
535 | if ( isset( $this->results[ $meta->user_id ] ) ) { |
---|
536 | $this->results[ $meta->user_id ]->meta_key = $meta->meta_key; |
---|
537 | |
---|
538 | if ( ! empty( $meta->meta_value ) ) { |
---|
539 | $this->results[ $meta->user_id ]->meta_value = $meta->meta_value; |
---|
540 | } |
---|
541 | } |
---|
542 | } |
---|
543 | } |
---|
544 | } |
---|
545 | } |
---|
546 | } |
---|
547 | |
---|
548 | /** |
---|
549 | * BP_Core_User class can be used by any component. It will fetch useful |
---|
550 | * details for any user when provided with a user_id. |
---|
551 | * |
---|
552 | * Example: |
---|
553 | * $user = new BP_Core_User( $user_id ); |
---|
554 | * $user_avatar = $user->avatar; |
---|
555 | * $user_email = $user->email; |
---|
556 | * $user_status = $user->status; |
---|
557 | * etc. |
---|
558 | * |
---|
559 | * @package BuddyPress Core |
---|
560 | */ |
---|
561 | class BP_Core_User { |
---|
562 | |
---|
563 | /** |
---|
564 | * ID of the user which the object relates to. |
---|
565 | * |
---|
566 | * @var integer |
---|
567 | */ |
---|
568 | var $id; |
---|
569 | |
---|
570 | /** |
---|
571 | * The URL to the full size of the avatar for the user. |
---|
572 | * |
---|
573 | * @var string |
---|
574 | */ |
---|
575 | var $avatar; |
---|
576 | |
---|
577 | /** |
---|
578 | * The URL to the thumb size of the avatar for the user. |
---|
579 | * |
---|
580 | * @var string |
---|
581 | */ |
---|
582 | var $avatar_thumb; |
---|
583 | |
---|
584 | /** |
---|
585 | * The URL to the mini size of the avatar for the user. |
---|
586 | * |
---|
587 | * @var string |
---|
588 | */ |
---|
589 | var $avatar_mini; |
---|
590 | |
---|
591 | /** |
---|
592 | * The full name of the user |
---|
593 | * |
---|
594 | * @var string |
---|
595 | */ |
---|
596 | var $fullname; |
---|
597 | |
---|
598 | /** |
---|
599 | * The email for the user. |
---|
600 | * |
---|
601 | * @var string |
---|
602 | */ |
---|
603 | var $email; |
---|
604 | |
---|
605 | /** |
---|
606 | * The absolute url for the user's profile. |
---|
607 | * |
---|
608 | * @var string |
---|
609 | */ |
---|
610 | var $user_url; |
---|
611 | |
---|
612 | /** |
---|
613 | * The HTML for the user link, with the link text being the user's full name. |
---|
614 | * |
---|
615 | * @var string |
---|
616 | */ |
---|
617 | var $user_link; |
---|
618 | |
---|
619 | /** |
---|
620 | * Contains a formatted string when the last time the user was active. |
---|
621 | * |
---|
622 | * Example: "active 2 hours and 50 minutes ago" |
---|
623 | * |
---|
624 | * @var string |
---|
625 | */ |
---|
626 | var $last_active; |
---|
627 | |
---|
628 | /* Extras */ |
---|
629 | |
---|
630 | /** |
---|
631 | * The total number of "Friends" the user has on site. |
---|
632 | * |
---|
633 | * @var integer |
---|
634 | */ |
---|
635 | var $total_friends; |
---|
636 | |
---|
637 | /** |
---|
638 | * The total number of blog posts posted by the user |
---|
639 | * |
---|
640 | * @var integer |
---|
641 | * @deprecated No longer used |
---|
642 | */ |
---|
643 | var $total_blogs; |
---|
644 | |
---|
645 | /** |
---|
646 | * The total number of groups the user is a part of. |
---|
647 | * |
---|
648 | * Example: "1 group", "2 groups" |
---|
649 | * |
---|
650 | * @var string |
---|
651 | */ |
---|
652 | var $total_groups; |
---|
653 | |
---|
654 | /** |
---|
655 | * Profile information for the specific user. |
---|
656 | * |
---|
657 | * @since BuddyPress (1.2) |
---|
658 | * @var array |
---|
659 | */ |
---|
660 | public $profile_data; |
---|
661 | |
---|
662 | /** Public Methods *******************************************************/ |
---|
663 | |
---|
664 | /** |
---|
665 | * Class constructor. |
---|
666 | * |
---|
667 | * @param integer $user_id The ID for the user |
---|
668 | * @param boolean $populate_extras Whether to fetch extra information such as group/friendship counts or not. |
---|
669 | */ |
---|
670 | function __construct( $user_id, $populate_extras = false ) { |
---|
671 | if ( !empty( $user_id ) ) { |
---|
672 | $this->id = $user_id; |
---|
673 | $this->populate(); |
---|
674 | |
---|
675 | if ( !empty( $populate_extras ) ) { |
---|
676 | $this->populate_extras(); |
---|
677 | } |
---|
678 | } |
---|
679 | } |
---|
680 | |
---|
681 | /** Private Methods *******************************************************/ |
---|
682 | |
---|
683 | /** |
---|
684 | * Populate the instantiated class with data based on the User ID provided. |
---|
685 | * |
---|
686 | * @uses bp_core_get_userurl() Returns the URL with no HTML markup for a user based on their user id |
---|
687 | * @uses bp_core_get_userlink() Returns a HTML formatted link for a user with the user's full name as the link text |
---|
688 | * @uses bp_core_get_user_email() Returns the email address for the user based on user ID |
---|
689 | * @uses bp_get_user_meta() BP function returns the value of passed usermeta name from usermeta table |
---|
690 | * @uses bp_core_fetch_avatar() Returns HTML formatted avatar for a user |
---|
691 | * @uses bp_profile_last_updated_date() Returns the last updated date for a user. |
---|
692 | */ |
---|
693 | function populate() { |
---|
694 | |
---|
695 | if ( bp_is_active( 'xprofile' ) ) |
---|
696 | $this->profile_data = $this->get_profile_data(); |
---|
697 | |
---|
698 | if ( !empty( $this->profile_data ) ) { |
---|
699 | $full_name_field_name = bp_xprofile_fullname_field_name(); |
---|
700 | |
---|
701 | $this->user_url = bp_core_get_user_domain( $this->id, $this->profile_data['user_nicename'], $this->profile_data['user_login'] ); |
---|
702 | $this->fullname = esc_attr( $this->profile_data[$full_name_field_name]['field_data'] ); |
---|
703 | $this->user_link = "<a href='{$this->user_url}' title='{$this->fullname}'>{$this->fullname}</a>"; |
---|
704 | $this->email = esc_attr( $this->profile_data['user_email'] ); |
---|
705 | } else { |
---|
706 | $this->user_url = bp_core_get_user_domain( $this->id ); |
---|
707 | $this->user_link = bp_core_get_userlink( $this->id ); |
---|
708 | $this->fullname = esc_attr( bp_core_get_user_displayname( $this->id ) ); |
---|
709 | $this->email = esc_attr( bp_core_get_user_email( $this->id ) ); |
---|
710 | } |
---|
711 | |
---|
712 | // Cache a few things that are fetched often |
---|
713 | wp_cache_set( 'bp_user_fullname_' . $this->id, $this->fullname, 'bp' ); |
---|
714 | wp_cache_set( 'bp_user_email_' . $this->id, $this->email, 'bp' ); |
---|
715 | wp_cache_set( 'bp_user_url_' . $this->id, $this->user_url, 'bp' ); |
---|
716 | |
---|
717 | $this->avatar = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'full', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->fullname ) ) ); |
---|
718 | $this->avatar_thumb = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->fullname ) ) ); |
---|
719 | $this->avatar_mini = bp_core_fetch_avatar( array( 'item_id' => $this->id, 'type' => 'thumb', 'alt' => sprintf( __( 'Avatar of %s', 'buddypress' ), $this->fullname ), 'width' => 30, 'height' => 30 ) ); |
---|
720 | $this->last_active = bp_core_get_last_activity( bp_get_user_meta( $this->id, 'last_activity', true ), __( 'active %s', 'buddypress' ) ); |
---|
721 | } |
---|
722 | |
---|
723 | /** |
---|
724 | * Populates extra fields such as group and friendship counts. |
---|
725 | */ |
---|
726 | function populate_extras() { |
---|
727 | |
---|
728 | if ( bp_is_active( 'friends' ) ) { |
---|
729 | $this->total_friends = BP_Friends_Friendship::total_friend_count( $this->id ); |
---|
730 | } |
---|
731 | |
---|
732 | if ( bp_is_active( 'groups' ) ) { |
---|
733 | $this->total_groups = BP_Groups_Member::total_group_count( $this->id ); |
---|
734 | $this->total_groups = sprintf( _n( '%d group', '%d groups', $this->total_groups, 'buddypress' ), $this->total_groups ); |
---|
735 | } |
---|
736 | } |
---|
737 | |
---|
738 | function get_profile_data() { |
---|
739 | return BP_XProfile_ProfileData::get_all_for_user( $this->id ); |
---|
740 | } |
---|
741 | |
---|
742 | /** Static Methods ********************************************************/ |
---|
743 | |
---|
744 | function get_users( $type, $limit = 0, $page = 1, $user_id = 0, $include = false, $search_terms = false, $populate_extras = true, $exclude = false, $meta_key = false, $meta_value = false ) { |
---|
745 | global $wpdb, $bp; |
---|
746 | |
---|
747 | _deprecated_function( __METHOD__, '1.7', 'BP_User_Query' ); |
---|
748 | |
---|
749 | $sql = array(); |
---|
750 | |
---|
751 | $sql['select_main'] = "SELECT DISTINCT u.ID as id, u.user_registered, u.user_nicename, u.user_login, u.display_name, u.user_email"; |
---|
752 | |
---|
753 | if ( 'active' == $type || 'online' == $type || 'newest' == $type ) { |
---|
754 | $sql['select_active'] = ", um.meta_value as last_activity"; |
---|
755 | } |
---|
756 | |
---|
757 | if ( 'popular' == $type ) { |
---|
758 | $sql['select_popular'] = ", um.meta_value as total_friend_count"; |
---|
759 | } |
---|
760 | |
---|
761 | if ( 'alphabetical' == $type ) { |
---|
762 | $sql['select_alpha'] = ", pd.value as fullname"; |
---|
763 | } |
---|
764 | |
---|
765 | if ( $meta_key ) { |
---|
766 | $sql['select_meta'] = ", umm.meta_key"; |
---|
767 | |
---|
768 | if ( $meta_value ) { |
---|
769 | $sql['select_meta'] .= ", umm.meta_value"; |
---|
770 | } |
---|
771 | } |
---|
772 | |
---|
773 | $sql['from'] = "FROM {$wpdb->users} u LEFT JOIN {$wpdb->usermeta} um ON um.user_id = u.ID"; |
---|
774 | |
---|
775 | // We search against xprofile fields, so we must join the table |
---|
776 | if ( $search_terms && bp_is_active( 'xprofile' ) ) { |
---|
777 | $sql['join_profiledata_search'] = "LEFT JOIN {$bp->profile->table_name_data} spd ON u.ID = spd.user_id"; |
---|
778 | } |
---|
779 | |
---|
780 | // Alphabetical sorting is done by the xprofile Full Name field |
---|
781 | if ( 'alphabetical' == $type ) { |
---|
782 | $sql['join_profiledata_alpha'] = "LEFT JOIN {$bp->profile->table_name_data} pd ON u.ID = pd.user_id"; |
---|
783 | } |
---|
784 | |
---|
785 | if ( $meta_key ) { |
---|
786 | $sql['join_meta'] = "LEFT JOIN {$wpdb->usermeta} umm ON umm.user_id = u.ID"; |
---|
787 | } |
---|
788 | |
---|
789 | $sql['where'] = 'WHERE ' . bp_core_get_status_sql( 'u.' ); |
---|
790 | |
---|
791 | if ( 'active' == $type || 'online' == $type || 'newest' == $type ) { |
---|
792 | $sql['where_active'] = $wpdb->prepare( "AND um.meta_key = %s", bp_get_user_meta_key( 'last_activity' ) ); |
---|
793 | } |
---|
794 | |
---|
795 | if ( 'popular' == $type ) { |
---|
796 | $sql['where_popular'] = $wpdb->prepare( "AND um.meta_key = %s", bp_get_user_meta_key( 'total_friend_count' ) ); |
---|
797 | } |
---|
798 | |
---|
799 | if ( 'online' == $type ) { |
---|
800 | $sql['where_online'] = "AND DATE_ADD( um.meta_value, INTERVAL 5 MINUTE ) >= UTC_TIMESTAMP()"; |
---|
801 | } |
---|
802 | |
---|
803 | if ( 'alphabetical' == $type ) { |
---|
804 | $sql['where_alpha'] = "AND pd.field_id = 1"; |
---|
805 | } |
---|
806 | |
---|
807 | if ( !empty( $exclude ) ) { |
---|
808 | $sql['where_exclude'] = "AND u.ID NOT IN ({$exclude})"; |
---|
809 | } |
---|
810 | |
---|
811 | // Passing an $include value of 0 or '0' will necessarily result in an empty set |
---|
812 | // returned. The default value of false will hit the 'else' clause. |
---|
813 | if ( 0 === $include || '0' === $include ) { |
---|
814 | $sql['where_users'] = "AND 0 = 1"; |
---|
815 | } else { |
---|
816 | if ( !empty( $include ) ) { |
---|
817 | if ( is_array( $include ) ) { |
---|
818 | $uids = $wpdb->escape( implode( ',', (array) $include ) ); |
---|
819 | } else { |
---|
820 | $uids = $wpdb->escape( $include ); |
---|
821 | } |
---|
822 | |
---|
823 | if ( !empty( $uids ) ) { |
---|
824 | $sql['where_users'] = "AND u.ID IN ({$uids})"; |
---|
825 | } |
---|
826 | } elseif ( !empty( $user_id ) && bp_is_active( 'friends' ) ) { |
---|
827 | $friend_ids = friends_get_friend_user_ids( $user_id ); |
---|
828 | $friend_ids = $wpdb->escape( implode( ',', (array) $friend_ids ) ); |
---|
829 | |
---|
830 | if ( !empty( $friend_ids ) ) { |
---|
831 | $sql['where_friends'] = "AND u.ID IN ({$friend_ids})"; |
---|
832 | |
---|
833 | // User has no friends, return false since there will be no users to fetch. |
---|
834 | } else { |
---|
835 | return false; |
---|
836 | } |
---|
837 | } |
---|
838 | } |
---|
839 | |
---|
840 | if ( !empty( $search_terms ) && bp_is_active( 'xprofile' ) ) { |
---|
841 | $search_terms = like_escape( $wpdb->escape( $search_terms ) ); |
---|
842 | $sql['where_searchterms'] = "AND spd.value LIKE '%%$search_terms%%'"; |
---|
843 | } |
---|
844 | |
---|
845 | if ( !empty( $meta_key ) ) { |
---|
846 | $sql['where_meta'] = $wpdb->prepare( " AND umm.meta_key = %s", $meta_key ); |
---|
847 | |
---|
848 | // If a meta value is provided, match it |
---|
849 | if ( $meta_value ) { |
---|
850 | $sql['where_meta'] .= $wpdb->prepare( " AND umm.meta_value = %s", $meta_value ); |
---|
851 | } |
---|
852 | } |
---|
853 | |
---|
854 | switch ( $type ) { |
---|
855 | case 'active': case 'online': default: |
---|
856 | $sql[] = "ORDER BY um.meta_value DESC"; |
---|
857 | break; |
---|
858 | case 'newest': |
---|
859 | $sql[] = "ORDER BY u.ID DESC"; |
---|
860 | break; |
---|
861 | case 'alphabetical': |
---|
862 | $sql[] = "ORDER BY pd.value ASC"; |
---|
863 | break; |
---|
864 | case 'random': |
---|
865 | $sql[] = "ORDER BY rand()"; |
---|
866 | break; |
---|
867 | case 'popular': |
---|
868 | $sql[] = "ORDER BY CONVERT(um.meta_value, SIGNED) DESC"; |
---|
869 | break; |
---|
870 | } |
---|
871 | |
---|
872 | if ( !empty( $limit ) && !empty( $page ) ) { |
---|
873 | $sql['pagination'] = $wpdb->prepare( "LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ); |
---|
874 | } |
---|
875 | |
---|
876 | // Get paginated results |
---|
877 | $paged_users_sql = apply_filters( 'bp_core_get_paged_users_sql', join( ' ', (array) $sql ), $sql ); |
---|
878 | $paged_users = $wpdb->get_results( $paged_users_sql ); |
---|
879 | |
---|
880 | // Re-jig the SQL so we can get the total user count |
---|
881 | unset( $sql['select_main'] ); |
---|
882 | |
---|
883 | if ( !empty( $sql['select_active'] ) ) { |
---|
884 | unset( $sql['select_active'] ); |
---|
885 | } |
---|
886 | |
---|
887 | if ( !empty( $sql['select_popular'] ) ) { |
---|
888 | unset( $sql['select_popular'] ); |
---|
889 | } |
---|
890 | |
---|
891 | if ( !empty( $sql['select_alpha'] ) ) { |
---|
892 | unset( $sql['select_alpha'] ); |
---|
893 | } |
---|
894 | |
---|
895 | if ( !empty( $sql['pagination'] ) ) { |
---|
896 | unset( $sql['pagination'] ); |
---|
897 | } |
---|
898 | |
---|
899 | array_unshift( $sql, "SELECT COUNT(DISTINCT u.ID)" ); |
---|
900 | |
---|
901 | // Get total user results |
---|
902 | $total_users_sql = apply_filters( 'bp_core_get_total_users_sql', join( ' ', (array) $sql ), $sql ); |
---|
903 | $total_users = $wpdb->get_var( $total_users_sql ); |
---|
904 | |
---|
905 | /*** |
---|
906 | * Lets fetch some other useful data in a separate queries, this will be faster than querying the data for every user in a list. |
---|
907 | * We can't add these to the main query above since only users who have this information will be returned (since the much of the data is in usermeta and won't support any type of directional join) |
---|
908 | */ |
---|
909 | if ( !empty( $populate_extras ) ) { |
---|
910 | $user_ids = array(); |
---|
911 | |
---|
912 | foreach ( (array) $paged_users as $user ) { |
---|
913 | $user_ids[] = $user->id; |
---|
914 | } |
---|
915 | |
---|
916 | $user_ids = $wpdb->escape( join( ',', (array) $user_ids ) ); |
---|
917 | |
---|
918 | // Add additional data to the returned results |
---|
919 | $paged_users = BP_Core_User::get_user_extras( $paged_users, $user_ids, $type ); |
---|
920 | } |
---|
921 | |
---|
922 | return array( 'users' => $paged_users, 'total' => $total_users ); |
---|
923 | } |
---|
924 | |
---|
925 | |
---|
926 | /** |
---|
927 | * Fetches the user details for all the users who username starts with the letter given. |
---|
928 | * |
---|
929 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
930 | * @global wpdb $wpdb WordPress database object |
---|
931 | * @param string $letter The letter the users names are to start with. |
---|
932 | * @param integer $limit The number of users we wish to retrive. |
---|
933 | * @param integer $page The page number we are currently on, used in conjunction with $limit to get the start position for the limit. |
---|
934 | * @param boolean $populate_extras Populate extra user fields? |
---|
935 | * @param string $exclude Comma-separated IDs of users whose results aren't to be fetched. |
---|
936 | * @return mixed False on error, otherwise associative array of results. |
---|
937 | * @static |
---|
938 | */ |
---|
939 | function get_users_by_letter( $letter, $limit = null, $page = 1, $populate_extras = true, $exclude = '' ) { |
---|
940 | global $bp, $wpdb; |
---|
941 | |
---|
942 | $pag_sql = ''; |
---|
943 | if ( $limit && $page ) { |
---|
944 | $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ); |
---|
945 | } |
---|
946 | |
---|
947 | // Multibyte compliance |
---|
948 | if ( function_exists( 'mb_strlen' ) ) { |
---|
949 | if ( mb_strlen( $letter, 'UTF-8' ) > 1 || is_numeric( $letter ) || !$letter ) { |
---|
950 | return false; |
---|
951 | } |
---|
952 | } else { |
---|
953 | if ( strlen( $letter ) > 1 || is_numeric( $letter ) || !$letter ) { |
---|
954 | return false; |
---|
955 | } |
---|
956 | } |
---|
957 | |
---|
958 | $letter = like_escape( $wpdb->escape( $letter ) ); |
---|
959 | $status_sql = bp_core_get_status_sql( 'u.' ); |
---|
960 | |
---|
961 | $exclude_sql = ( !empty( $exclude ) ) ? " AND u.ID NOT IN ({$exclude})" : ""; |
---|
962 | |
---|
963 | $total_users_sql = apply_filters( 'bp_core_users_by_letter_count_sql', $wpdb->prepare( "SELECT COUNT(DISTINCT u.ID) FROM {$wpdb->users} u LEFT JOIN {$bp->profile->table_name_data} pd ON u.ID = pd.user_id LEFT JOIN {$bp->profile->table_name_fields} pf ON pd.field_id = pf.id WHERE {$status_sql} AND pf.name = %s {$exclude_sql} AND pd.value LIKE '{$letter}%%' ORDER BY pd.value ASC", bp_xprofile_fullname_field_name() ) ); |
---|
964 | $paged_users_sql = apply_filters( 'bp_core_users_by_letter_sql', $wpdb->prepare( "SELECT DISTINCT u.ID as id, u.user_registered, u.user_nicename, u.user_login, u.user_email FROM {$wpdb->users} u LEFT JOIN {$bp->profile->table_name_data} pd ON u.ID = pd.user_id LEFT JOIN {$bp->profile->table_name_fields} pf ON pd.field_id = pf.id WHERE {$status_sql} AND pf.name = %s {$exclude_sql} AND pd.value LIKE '{$letter}%%' ORDER BY pd.value ASC{$pag_sql}", bp_xprofile_fullname_field_name() ) ); |
---|
965 | |
---|
966 | $total_users = $wpdb->get_var( $total_users_sql ); |
---|
967 | $paged_users = $wpdb->get_results( $paged_users_sql ); |
---|
968 | |
---|
969 | /*** |
---|
970 | * Lets fetch some other useful data in a separate queries, this will be |
---|
971 | * faster than querying the data for every user in a list. We can't add |
---|
972 | * these to the main query above since only users who have this |
---|
973 | * information will be returned (since the much of the data is in |
---|
974 | * usermeta and won't support any type of directional join) |
---|
975 | */ |
---|
976 | $user_ids = array(); |
---|
977 | foreach ( (array) $paged_users as $user ) |
---|
978 | $user_ids[] = $user->id; |
---|
979 | |
---|
980 | $user_ids = $wpdb->escape( join( ',', (array) $user_ids ) ); |
---|
981 | |
---|
982 | // Add additional data to the returned results |
---|
983 | if ( $populate_extras ) { |
---|
984 | $paged_users = BP_Core_User::get_user_extras( $paged_users, $user_ids ); |
---|
985 | } |
---|
986 | |
---|
987 | return array( 'users' => $paged_users, 'total' => $total_users ); |
---|
988 | } |
---|
989 | |
---|
990 | /** |
---|
991 | * Get details of specific users from the database |
---|
992 | * |
---|
993 | * @global wpdb $wpdb WordPress database object |
---|
994 | * @param array $user_ids The user IDs of the users who we wish to fetch information on. |
---|
995 | * @param integer $limit The limit of results we want. |
---|
996 | * @param integer $page The page we are on for pagination. |
---|
997 | * @param boolean $populate_extras Populate extra user fields? |
---|
998 | * @return array Associative array |
---|
999 | * @static |
---|
1000 | */ |
---|
1001 | function get_specific_users( $user_ids, $limit = null, $page = 1, $populate_extras = true ) { |
---|
1002 | global $wpdb; |
---|
1003 | |
---|
1004 | $pag_sql = ''; |
---|
1005 | if ( $limit && $page ) |
---|
1006 | $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ); |
---|
1007 | |
---|
1008 | $status_sql = bp_core_get_status_sql(); |
---|
1009 | |
---|
1010 | $total_users_sql = apply_filters( 'bp_core_get_specific_users_count_sql', "SELECT COUNT(DISTINCT ID) FROM {$wpdb->users} WHERE {$status_sql} AND ID IN ( " . $wpdb->escape( $user_ids ) . " ) " ); |
---|
1011 | $paged_users_sql = apply_filters( 'bp_core_get_specific_users_count_sql', "SELECT DISTINCT ID as id, user_registered, user_nicename, user_login, user_email FROM {$wpdb->users} WHERE {$status_sql} AND ID IN ( " . $wpdb->escape( $user_ids ) . " ) {$pag_sql}" ); |
---|
1012 | |
---|
1013 | $total_users = $wpdb->get_var( $total_users_sql ); |
---|
1014 | $paged_users = $wpdb->get_results( $paged_users_sql ); |
---|
1015 | |
---|
1016 | /*** |
---|
1017 | * Lets fetch some other useful data in a separate queries, this will be |
---|
1018 | * faster than querying the data for every user in a list. We can't add |
---|
1019 | * these to the main query above since only users who have this |
---|
1020 | * information will be returned (since the much of the data is in |
---|
1021 | * usermeta and won't support any type of directional join) |
---|
1022 | */ |
---|
1023 | |
---|
1024 | // Add additional data to the returned results |
---|
1025 | if ( !empty( $populate_extras ) ) { |
---|
1026 | $paged_users = BP_Core_User::get_user_extras( $paged_users, $user_ids ); |
---|
1027 | } |
---|
1028 | |
---|
1029 | return array( 'users' => $paged_users, 'total' => $total_users ); |
---|
1030 | } |
---|
1031 | |
---|
1032 | /** |
---|
1033 | * Find users who match on the value of an xprofile data. |
---|
1034 | * |
---|
1035 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1036 | * @global wpdb $wpdb WordPress database object |
---|
1037 | * @param string $search_terms The terms to search the profile table value column for. |
---|
1038 | * @param integer $limit The limit of results we want. |
---|
1039 | * @param integer $page The page we are on for pagination. |
---|
1040 | * @param boolean $populate_extras Populate extra user fields? |
---|
1041 | * @return array Associative array |
---|
1042 | * @static |
---|
1043 | */ |
---|
1044 | function search_users( $search_terms, $limit = null, $page = 1, $populate_extras = true ) { |
---|
1045 | global $bp, $wpdb; |
---|
1046 | |
---|
1047 | $user_ids = array(); |
---|
1048 | $pag_sql = $limit && $page ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * intval( $limit ) ), intval( $limit ) ) : ''; |
---|
1049 | |
---|
1050 | $search_terms = like_escape( $wpdb->escape( $search_terms ) ); |
---|
1051 | $status_sql = bp_core_get_status_sql( 'u.' ); |
---|
1052 | |
---|
1053 | $total_users_sql = apply_filters( 'bp_core_search_users_count_sql', "SELECT COUNT(DISTINCT u.ID) as id FROM {$wpdb->users} u LEFT JOIN {$bp->profile->table_name_data} pd ON u.ID = pd.user_id WHERE {$status_sql} AND pd.value LIKE '%%{$search_terms}%%' ORDER BY pd.value ASC", $search_terms ); |
---|
1054 | $paged_users_sql = apply_filters( 'bp_core_search_users_sql', "SELECT DISTINCT u.ID as id, u.user_registered, u.user_nicename, u.user_login, u.user_email FROM {$wpdb->users} u LEFT JOIN {$bp->profile->table_name_data} pd ON u.ID = pd.user_id WHERE {$status_sql} AND pd.value LIKE '%%{$search_terms}%%' ORDER BY pd.value ASC{$pag_sql}", $search_terms, $pag_sql ); |
---|
1055 | |
---|
1056 | $total_users = $wpdb->get_var( $total_users_sql ); |
---|
1057 | $paged_users = $wpdb->get_results( $paged_users_sql ); |
---|
1058 | |
---|
1059 | /*** |
---|
1060 | * Lets fetch some other useful data in a separate queries, this will be faster than querying the data for every user in a list. |
---|
1061 | * We can't add these to the main query above since only users who have this information will be returned (since the much of the data is in usermeta and won't support any type of directional join) |
---|
1062 | */ |
---|
1063 | foreach ( (array) $paged_users as $user ) |
---|
1064 | $user_ids[] = $user->id; |
---|
1065 | |
---|
1066 | $user_ids = $wpdb->escape( join( ',', (array) $user_ids ) ); |
---|
1067 | |
---|
1068 | // Add additional data to the returned results |
---|
1069 | if ( $populate_extras ) |
---|
1070 | $paged_users = BP_Core_User::get_user_extras( $paged_users, $user_ids ); |
---|
1071 | |
---|
1072 | return array( 'users' => $paged_users, 'total' => $total_users ); |
---|
1073 | } |
---|
1074 | |
---|
1075 | /** |
---|
1076 | * Fetch extra user information, such as friend count and last profile update message. |
---|
1077 | * |
---|
1078 | * Accepts multiple user IDs to fetch data for. |
---|
1079 | * |
---|
1080 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1081 | * @global wpdb $wpdb WordPress database object |
---|
1082 | * @param array $paged_users an array of stdClass containing the users |
---|
1083 | * @param string $user_ids the user ids to select information about |
---|
1084 | * @param string $type the type of fields we wish to get |
---|
1085 | * @return mixed False on error, otherwise associative array of results. |
---|
1086 | * @static |
---|
1087 | */ |
---|
1088 | function get_user_extras( &$paged_users, &$user_ids, $type = false ) { |
---|
1089 | global $bp, $wpdb; |
---|
1090 | |
---|
1091 | if ( empty( $user_ids ) ) |
---|
1092 | return $paged_users; |
---|
1093 | |
---|
1094 | // Fetch the user's full name |
---|
1095 | if ( bp_is_active( 'xprofile' ) && 'alphabetical' != $type ) { |
---|
1096 | $names = $wpdb->get_results( $wpdb->prepare( "SELECT pd.user_id as id, pd.value as fullname FROM {$bp->profile->table_name_fields} pf, {$bp->profile->table_name_data} pd WHERE pf.id = pd.field_id AND pf.name = %s AND pd.user_id IN ( {$user_ids} )", bp_xprofile_fullname_field_name() ) ); |
---|
1097 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1098 | foreach ( (array) $names as $name ) { |
---|
1099 | if ( $name->id == $paged_users[$i]->id ) |
---|
1100 | $paged_users[$i]->fullname = $name->fullname; |
---|
1101 | } |
---|
1102 | } |
---|
1103 | } |
---|
1104 | |
---|
1105 | // Fetch the user's total friend count |
---|
1106 | if ( 'popular' != $type ) { |
---|
1107 | $friend_count = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as total_friend_count FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'total_friend_count' ) ) ); |
---|
1108 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1109 | foreach ( (array) $friend_count as $fcount ) { |
---|
1110 | if ( $fcount->id == $paged_users[$i]->id ) |
---|
1111 | $paged_users[$i]->total_friend_count = (int) $fcount->total_friend_count; |
---|
1112 | } |
---|
1113 | } |
---|
1114 | } |
---|
1115 | |
---|
1116 | // Fetch whether or not the user is a friend |
---|
1117 | if ( bp_is_active( 'friends' ) ) { |
---|
1118 | $friend_status = $wpdb->get_results( $wpdb->prepare( "SELECT initiator_user_id, friend_user_id, is_confirmed FROM {$bp->friends->table_name} WHERE (initiator_user_id = %d AND friend_user_id IN ( {$user_ids} ) ) OR (initiator_user_id IN ( {$user_ids} ) AND friend_user_id = %d )", bp_loggedin_user_id(), bp_loggedin_user_id() ) ); |
---|
1119 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1120 | foreach ( (array) $friend_status as $status ) { |
---|
1121 | if ( $status->initiator_user_id == $paged_users[$i]->id || $status->friend_user_id == $paged_users[$i]->id ) |
---|
1122 | $paged_users[$i]->is_friend = $status->is_confirmed; |
---|
1123 | } |
---|
1124 | } |
---|
1125 | } |
---|
1126 | |
---|
1127 | if ( 'active' != $type ) { |
---|
1128 | $user_activity = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as last_activity FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'last_activity' ) ) ); |
---|
1129 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1130 | foreach ( (array) $user_activity as $activity ) { |
---|
1131 | if ( $activity->id == $paged_users[$i]->id ) |
---|
1132 | $paged_users[$i]->last_activity = $activity->last_activity; |
---|
1133 | } |
---|
1134 | } |
---|
1135 | } |
---|
1136 | |
---|
1137 | // Fetch the user's last_activity |
---|
1138 | if ( 'active' != $type ) { |
---|
1139 | $user_activity = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as last_activity FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'last_activity' ) ) ); |
---|
1140 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1141 | foreach ( (array) $user_activity as $activity ) { |
---|
1142 | if ( $activity->id == $paged_users[$i]->id ) |
---|
1143 | $paged_users[$i]->last_activity = $activity->last_activity; |
---|
1144 | } |
---|
1145 | } |
---|
1146 | } |
---|
1147 | |
---|
1148 | // Fetch the user's latest update |
---|
1149 | $user_update = $wpdb->get_results( $wpdb->prepare( "SELECT user_id as id, meta_value as latest_update FROM {$wpdb->usermeta} WHERE meta_key = %s AND user_id IN ( {$user_ids} )", bp_get_user_meta_key( 'bp_latest_update' ) ) ); |
---|
1150 | for ( $i = 0, $count = count( $paged_users ); $i < $count; ++$i ) { |
---|
1151 | foreach ( (array) $user_update as $update ) { |
---|
1152 | if ( $update->id == $paged_users[$i]->id ) |
---|
1153 | $paged_users[$i]->latest_update = $update->latest_update; |
---|
1154 | } |
---|
1155 | } |
---|
1156 | |
---|
1157 | return $paged_users; |
---|
1158 | } |
---|
1159 | |
---|
1160 | /** |
---|
1161 | * Get WordPress user details for a specified user. |
---|
1162 | * |
---|
1163 | * @global wpdb $wpdb WordPress database object |
---|
1164 | * @param integer $user_id User ID |
---|
1165 | * @return array Associative array |
---|
1166 | * @static |
---|
1167 | */ |
---|
1168 | function get_core_userdata( $user_id ) { |
---|
1169 | global $wpdb; |
---|
1170 | |
---|
1171 | if ( !$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->users} WHERE ID = %d LIMIT 1", $user_id ) ) ) |
---|
1172 | return false; |
---|
1173 | |
---|
1174 | return $user; |
---|
1175 | } |
---|
1176 | } |
---|
1177 | |
---|
1178 | |
---|
1179 | /** |
---|
1180 | * BP_Core_Notification class can be used by any component. |
---|
1181 | * It will handle the fetching, saving and deleting of a user notification. |
---|
1182 | * |
---|
1183 | * @package BuddyPress Core |
---|
1184 | */ |
---|
1185 | |
---|
1186 | class BP_Core_Notification { |
---|
1187 | |
---|
1188 | /** |
---|
1189 | * The notification id |
---|
1190 | * |
---|
1191 | * @var integer |
---|
1192 | */ |
---|
1193 | var $id; |
---|
1194 | |
---|
1195 | /** |
---|
1196 | * The ID to which the notification relates to within the component. |
---|
1197 | * |
---|
1198 | * @var integer |
---|
1199 | */ |
---|
1200 | var $item_id; |
---|
1201 | |
---|
1202 | /** |
---|
1203 | * The secondary ID to which the notification relates to within the component. |
---|
1204 | * |
---|
1205 | * @var integer |
---|
1206 | */ |
---|
1207 | var $secondary_item_id = null; |
---|
1208 | |
---|
1209 | /** |
---|
1210 | * The user ID for who the notification is for. |
---|
1211 | * |
---|
1212 | * @var integer |
---|
1213 | */ |
---|
1214 | var $user_id; |
---|
1215 | |
---|
1216 | /** |
---|
1217 | * The name of the component that the notification is for. |
---|
1218 | * |
---|
1219 | * @var string |
---|
1220 | */ |
---|
1221 | var $component_name; |
---|
1222 | |
---|
1223 | /** |
---|
1224 | * The action within the component which the notification is related to. |
---|
1225 | * |
---|
1226 | * @var string |
---|
1227 | */ |
---|
1228 | var $component_action; |
---|
1229 | |
---|
1230 | /** |
---|
1231 | * The date the notification was created. |
---|
1232 | * |
---|
1233 | * @var string |
---|
1234 | */ |
---|
1235 | var $date_notified; |
---|
1236 | |
---|
1237 | /** |
---|
1238 | * Is the notification new or has it already been read. |
---|
1239 | * |
---|
1240 | * @var boolean |
---|
1241 | */ |
---|
1242 | var $is_new; |
---|
1243 | |
---|
1244 | /** Public Methods ********************************************************/ |
---|
1245 | |
---|
1246 | /** |
---|
1247 | * Constructor |
---|
1248 | * |
---|
1249 | * @param integer $id |
---|
1250 | */ |
---|
1251 | function __construct( $id = 0 ) { |
---|
1252 | if ( !empty( $id ) ) { |
---|
1253 | $this->id = $id; |
---|
1254 | $this->populate(); |
---|
1255 | } |
---|
1256 | } |
---|
1257 | |
---|
1258 | /** |
---|
1259 | * Update or insert notification details into the database. |
---|
1260 | * |
---|
1261 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1262 | * @global wpdb $wpdb WordPress database object |
---|
1263 | * @return bool Success or failure |
---|
1264 | */ |
---|
1265 | function save() { |
---|
1266 | global $bp, $wpdb; |
---|
1267 | |
---|
1268 | // Update |
---|
1269 | if ( !empty( $this->id ) ) { |
---|
1270 | $sql = $wpdb->prepare( "UPDATE {$bp->core->table_name_notifications} SET item_id = %d, secondary_item_id = %d, user_id = %d, component_name = %s, component_action = %d, date_notified = %s, is_new = %d ) WHERE id = %d", $this->item_id, $this->secondary_item_id, $this->user_id, $this->component_name, $this->component_action, $this->date_notified, $this->is_new, $this->id ); |
---|
1271 | |
---|
1272 | // Save |
---|
1273 | } else { |
---|
1274 | $sql = $wpdb->prepare( "INSERT INTO {$bp->core->table_name_notifications} ( item_id, secondary_item_id, user_id, component_name, component_action, date_notified, is_new ) VALUES ( %d, %d, %d, %s, %s, %s, %d )", $this->item_id, $this->secondary_item_id, $this->user_id, $this->component_name, $this->component_action, $this->date_notified, $this->is_new ); |
---|
1275 | } |
---|
1276 | |
---|
1277 | if ( !$result = $wpdb->query( $sql ) ) |
---|
1278 | return false; |
---|
1279 | |
---|
1280 | $this->id = $wpdb->insert_id; |
---|
1281 | |
---|
1282 | return true; |
---|
1283 | } |
---|
1284 | |
---|
1285 | /** Private Methods *******************************************************/ |
---|
1286 | |
---|
1287 | /** |
---|
1288 | * Fetches the notification data from the database. |
---|
1289 | * |
---|
1290 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1291 | * @global wpdb $wpdb WordPress database object |
---|
1292 | */ |
---|
1293 | function populate() { |
---|
1294 | global $bp, $wpdb; |
---|
1295 | |
---|
1296 | if ( $notification = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->core->table_name_notifications} WHERE id = %d", $this->id ) ) ) { |
---|
1297 | $this->item_id = $notification->item_id; |
---|
1298 | $this->secondary_item_id = $notification->secondary_item_id; |
---|
1299 | $this->user_id = $notification->user_id; |
---|
1300 | $this->component_name = $notification->component_name; |
---|
1301 | $this->component_action = $notification->component_action; |
---|
1302 | $this->date_notified = $notification->date_notified; |
---|
1303 | $this->is_new = $notification->is_new; |
---|
1304 | } |
---|
1305 | } |
---|
1306 | |
---|
1307 | /** Static Methods ********************************************************/ |
---|
1308 | |
---|
1309 | function check_access( $user_id, $notification_id ) { |
---|
1310 | global $wpdb, $bp; |
---|
1311 | |
---|
1312 | return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->core->table_name_notifications} WHERE id = %d AND user_id = %d", $notification_id, $user_id ) ); |
---|
1313 | } |
---|
1314 | |
---|
1315 | /** |
---|
1316 | * Fetches all the notifications in the database for a specific user. |
---|
1317 | * |
---|
1318 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1319 | * @global wpdb $wpdb WordPress database object |
---|
1320 | * @param integer $user_id User ID |
---|
1321 | * @param str $status 'is_new' or 'all' |
---|
1322 | * @return array Associative array |
---|
1323 | * @static |
---|
1324 | */ |
---|
1325 | function get_all_for_user( $user_id, $status = 'is_new' ) { |
---|
1326 | global $bp, $wpdb; |
---|
1327 | |
---|
1328 | $is_new = ( 'is_new' == $status ) ? ' AND is_new = 1 ' : ''; |
---|
1329 | |
---|
1330 | return $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->core->table_name_notifications} WHERE user_id = %d {$is_new}", $user_id ) ); |
---|
1331 | } |
---|
1332 | |
---|
1333 | /** |
---|
1334 | * Delete all the notifications for a user based on the component name and action. |
---|
1335 | * |
---|
1336 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1337 | * @global wpdb $wpdb WordPress database object |
---|
1338 | * @param integer $user_id |
---|
1339 | * @param string $component_name |
---|
1340 | * @param string $component_action |
---|
1341 | * @static |
---|
1342 | */ |
---|
1343 | function delete_for_user_by_type( $user_id, $component_name, $component_action ) { |
---|
1344 | global $bp, $wpdb; |
---|
1345 | |
---|
1346 | return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->core->table_name_notifications} WHERE user_id = %d AND component_name = %s AND component_action = %s", $user_id, $component_name, $component_action ) ); |
---|
1347 | } |
---|
1348 | |
---|
1349 | /** |
---|
1350 | * Delete all the notifications that have a specific item id, component name and action. |
---|
1351 | * |
---|
1352 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1353 | * @global wpdb $wpdb WordPress database object |
---|
1354 | * @param integer $user_id The ID of the user who the notifications are for. |
---|
1355 | * @param integer $item_id The item ID of the notifications we wish to delete. |
---|
1356 | * @param string $component_name The name of the component that the notifications we wish to delete. |
---|
1357 | * @param string $component_action The action of the component that the notifications we wish to delete. |
---|
1358 | * @param integer $secondary_item_id (optional) The secondary item id of the notifications that we wish to use to delete. |
---|
1359 | * @static |
---|
1360 | */ |
---|
1361 | function delete_for_user_by_item_id( $user_id, $item_id, $component_name, $component_action, $secondary_item_id = false ) { |
---|
1362 | global $bp, $wpdb; |
---|
1363 | |
---|
1364 | $secondary_item_sql = !empty( $secondary_item_id ) ? $wpdb->prepare( " AND secondary_item_id = %d", $secondary_item_id ) : ''; |
---|
1365 | |
---|
1366 | return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->core->table_name_notifications} WHERE user_id = %d AND item_id = %d AND component_name = %s AND component_action = %s{$secondary_item_sql}", $user_id, $item_id, $component_name, $component_action ) ); |
---|
1367 | } |
---|
1368 | |
---|
1369 | /** |
---|
1370 | * Deletes all the notifications sent by a specific user, by component and action. |
---|
1371 | * |
---|
1372 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1373 | * @global wpdb $wpdb WordPress database object |
---|
1374 | * @param integer $user_id The ID of the user whose sent notifications we wish to delete. |
---|
1375 | * @param string $component_name The name of the component the notification was sent from. |
---|
1376 | * @param string $component_action The action of the component the notification was sent from. |
---|
1377 | * @static |
---|
1378 | */ |
---|
1379 | function delete_from_user_by_type( $user_id, $component_name, $component_action ) { |
---|
1380 | global $bp, $wpdb; |
---|
1381 | |
---|
1382 | return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->core->table_name_notifications} WHERE item_id = %d AND component_name = %s AND component_action = %s", $user_id, $component_name, $component_action ) ); |
---|
1383 | } |
---|
1384 | |
---|
1385 | /** |
---|
1386 | * Deletes all the notifications for all users by item id, and optional secondary item id, and component name and action. |
---|
1387 | * |
---|
1388 | * @global BuddyPress $bp The one true BuddyPress instance |
---|
1389 | * @global wpdb $wpdb WordPress database object |
---|
1390 | * @param string $item_id The item id that they notifications are to be for. |
---|
1391 | * @param string $component_name The component that the notifications are to be from. |
---|
1392 | * @param string $component_action The action that the notificationsa are to be from. |
---|
1393 | * @param string $secondary_item_id Optional secondary item id that the notifications are to have. |
---|
1394 | * @static |
---|
1395 | */ |
---|
1396 | function delete_all_by_type( $item_id, $component_name, $component_action, $secondary_item_id ) { |
---|
1397 | global $bp, $wpdb; |
---|
1398 | |
---|
1399 | if ( $component_action ) |
---|
1400 | $component_action_sql = $wpdb->prepare( "AND component_action = %s", $component_action ); |
---|
1401 | else |
---|
1402 | $component_action_sql = ''; |
---|
1403 | |
---|
1404 | if ( $secondary_item_id ) |
---|
1405 | $secondary_item_sql = $wpdb->prepare( "AND secondary_item_id = %d", $secondary_item_id ); |
---|
1406 | else |
---|
1407 | $secondary_item_sql = ''; |
---|
1408 | |
---|
1409 | return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->core->table_name_notifications} WHERE item_id = %d AND component_name = %s {$component_action_sql} {$secondary_item_sql}", $item_id, $component_name ) ); |
---|
1410 | } |
---|
1411 | } |
---|
1412 | |
---|
1413 | /** |
---|
1414 | * BP_Button |
---|
1415 | * |
---|
1416 | * API to create BuddyPress buttons |
---|
1417 | * |
---|
1418 | * component: Which component this button is for |
---|
1419 | * must_be_logged_in: Button only appears for logged in users |
---|
1420 | * block_self: Button will not appear when viewing your own profile. |
---|
1421 | * wrapper: div|span|p|li|false for no wrapper |
---|
1422 | * wrapper_id: The DOM ID of the button wrapper |
---|
1423 | * wrapper_class: The DOM class of the button wrapper |
---|
1424 | * link_href: The destination link of the button |
---|
1425 | * link_title: Title of the button |
---|
1426 | * link_id: The DOM ID of the button |
---|
1427 | * link_class: The DOM class of the button |
---|
1428 | * link_rel: The DOM rel of the button |
---|
1429 | * link_text: The text of the button |
---|
1430 | * contents: The contents of the button |
---|
1431 | * |
---|
1432 | * @package BuddyPress Core |
---|
1433 | * @since BuddyPress (1.2.6) |
---|
1434 | */ |
---|
1435 | class BP_Button { |
---|
1436 | |
---|
1437 | /** Button properties *****************************************************/ |
---|
1438 | |
---|
1439 | /** |
---|
1440 | * The button ID |
---|
1441 | * |
---|
1442 | * @var integer |
---|
1443 | */ |
---|
1444 | public $id = ''; |
---|
1445 | |
---|
1446 | /** |
---|
1447 | * The component name that button belongs to. |
---|
1448 | * |
---|
1449 | * @var string |
---|
1450 | */ |
---|
1451 | public $component = 'core'; |
---|
1452 | |
---|
1453 | /** |
---|
1454 | * Does the user need to be logged in to see this button? |
---|
1455 | * |
---|
1456 | * @var boolean |
---|
1457 | */ |
---|
1458 | public $must_be_logged_in = true; |
---|
1459 | |
---|
1460 | /** |
---|
1461 | * True or false if the button should not be displayed while viewing your |
---|
1462 | * own profile. |
---|
1463 | * |
---|
1464 | * @var boolean |
---|
1465 | */ |
---|
1466 | public $block_self = true; |
---|
1467 | |
---|
1468 | /** Wrapper ***************************************************************/ |
---|
1469 | |
---|
1470 | /** |
---|
1471 | * What type of DOM element to use for a wrapper. |
---|
1472 | * |
---|
1473 | * |
---|
1474 | * @var mixed div|span|p|li, or false for no wrapper |
---|
1475 | */ |
---|
1476 | public $wrapper = 'div'; |
---|
1477 | |
---|
1478 | /** |
---|
1479 | * The DOM class of the button wrapper |
---|
1480 | * |
---|
1481 | * @var string |
---|
1482 | */ |
---|
1483 | public $wrapper_class = ''; |
---|
1484 | |
---|
1485 | /** |
---|
1486 | * The DOM ID of the button wrapper |
---|
1487 | * |
---|
1488 | * @var string |
---|
1489 | */ |
---|
1490 | public $wrapper_id = ''; |
---|
1491 | |
---|
1492 | /** Button ****************************************************************/ |
---|
1493 | |
---|
1494 | /** |
---|
1495 | * The destination link of the button |
---|
1496 | * |
---|
1497 | * @var string |
---|
1498 | */ |
---|
1499 | public $link_href = ''; |
---|
1500 | |
---|
1501 | /** |
---|
1502 | * The DOM class of the button link |
---|
1503 | * |
---|
1504 | * @var string |
---|
1505 | */ |
---|
1506 | public $link_class = ''; |
---|
1507 | |
---|
1508 | /** |
---|
1509 | * The DOM ID of the button link |
---|
1510 | * |
---|
1511 | * @var string |
---|
1512 | */ |
---|
1513 | public $link_id = ''; |
---|
1514 | |
---|
1515 | /** |
---|
1516 | * The DOM rel value of the button link |
---|
1517 | * |
---|
1518 | * @var string |
---|
1519 | */ |
---|
1520 | public $link_rel = ''; |
---|
1521 | |
---|
1522 | /** |
---|
1523 | * Title of the button link |
---|
1524 | * |
---|
1525 | * @var string |
---|
1526 | */ |
---|
1527 | public $link_title = ''; |
---|
1528 | |
---|
1529 | /** |
---|
1530 | * The contents of the button link |
---|
1531 | * |
---|
1532 | * @var string |
---|
1533 | */ |
---|
1534 | public $link_text = ''; |
---|
1535 | |
---|
1536 | /** HTML result ***********************************************************/ |
---|
1537 | |
---|
1538 | public $contents = ''; |
---|
1539 | |
---|
1540 | /** Methods ***************************************************************/ |
---|
1541 | |
---|
1542 | /** |
---|
1543 | * Builds the button based on class parameters: |
---|
1544 | * |
---|
1545 | * @since BuddyPress (1.2.6) |
---|
1546 | * |
---|
1547 | * @param array $args |
---|
1548 | * @return bool False if not allowed |
---|
1549 | */ |
---|
1550 | public function __construct( $args = '' ) { |
---|
1551 | |
---|
1552 | $r = wp_parse_args( $args, get_class_vars( __CLASS__ ) ); |
---|
1553 | |
---|
1554 | // Required button properties |
---|
1555 | $this->id = $r['id']; |
---|
1556 | $this->component = $r['component']; |
---|
1557 | $this->must_be_logged_in = (bool) $r['must_be_logged_in']; |
---|
1558 | $this->block_self = (bool) $r['block_self']; |
---|
1559 | $this->wrapper = $r['wrapper']; |
---|
1560 | |
---|
1561 | // $id and $component are required |
---|
1562 | if ( empty( $r['id'] ) || empty( $r['component'] ) ) |
---|
1563 | return false; |
---|
1564 | |
---|
1565 | // No button if component is not active |
---|
1566 | if ( ! bp_is_active( $this->component ) ) |
---|
1567 | return false; |
---|
1568 | |
---|
1569 | // No button for guests if must be logged in |
---|
1570 | if ( true == $this->must_be_logged_in && ! is_user_logged_in() ) |
---|
1571 | return false; |
---|
1572 | |
---|
1573 | // No button if viewing your own profile |
---|
1574 | if ( true == $this->block_self && bp_is_my_profile() ) |
---|
1575 | return false; |
---|
1576 | |
---|
1577 | // Wrapper properties |
---|
1578 | if ( false !== $this->wrapper ) { |
---|
1579 | |
---|
1580 | // Wrapper ID |
---|
1581 | if ( !empty( $r['wrapper_id'] ) ) { |
---|
1582 | $this->wrapper_id = ' id="' . $r['wrapper_id'] . '"'; |
---|
1583 | } |
---|
1584 | |
---|
1585 | // Wrapper class |
---|
1586 | if ( !empty( $r['wrapper_class'] ) ) { |
---|
1587 | $this->wrapper_class = ' class="generic-button ' . $r['wrapper_class'] . '"'; |
---|
1588 | } else { |
---|
1589 | $this->wrapper_class = ' class="generic-button"'; |
---|
1590 | } |
---|
1591 | |
---|
1592 | // Set before and after |
---|
1593 | $before = '<' . $r['wrapper'] . $this->wrapper_class . $this->wrapper_id . '>'; |
---|
1594 | $after = '</' . $r['wrapper'] . '>'; |
---|
1595 | |
---|
1596 | // No wrapper |
---|
1597 | } else { |
---|
1598 | $before = $after = ''; |
---|
1599 | } |
---|
1600 | |
---|
1601 | // Link properties |
---|
1602 | if ( !empty( $r['link_id'] ) ) $this->link_id = ' id="' . $r['link_id'] . '"'; |
---|
1603 | if ( !empty( $r['link_href'] ) ) $this->link_href = ' href="' . $r['link_href'] . '"'; |
---|
1604 | if ( !empty( $r['link_title'] ) ) $this->link_title = ' title="' . $r['link_title'] . '"'; |
---|
1605 | if ( !empty( $r['link_rel'] ) ) $this->link_rel = ' rel="' . $r['link_rel'] . '"'; |
---|
1606 | if ( !empty( $r['link_class'] ) ) $this->link_class = ' class="' . $r['link_class'] . '"'; |
---|
1607 | if ( !empty( $r['link_text'] ) ) $this->link_text = $r['link_text']; |
---|
1608 | |
---|
1609 | // Build the button |
---|
1610 | $this->contents = $before . '<a'. $this->link_href . $this->link_title . $this->link_id . $this->link_rel . $this->link_class . '>' . $this->link_text . '</a>' . $after; |
---|
1611 | |
---|
1612 | // Allow button to be manipulated externally |
---|
1613 | $this->contents = apply_filters( 'bp_button_' . $this->component . '_' . $this->id, $this->contents, $this, $before, $after ); |
---|
1614 | } |
---|
1615 | |
---|
1616 | /** |
---|
1617 | * Return contents of button |
---|
1618 | * |
---|
1619 | * @since BuddyPress (1.2.6) |
---|
1620 | * |
---|
1621 | * @return string |
---|
1622 | */ |
---|
1623 | public function contents() { |
---|
1624 | return $this->contents; |
---|
1625 | } |
---|
1626 | |
---|
1627 | /** |
---|
1628 | * Output contents of button |
---|
1629 | * |
---|
1630 | * @since BuddyPress (1.2.6) |
---|
1631 | */ |
---|
1632 | public function display() { |
---|
1633 | if ( !empty( $this->contents ) ) |
---|
1634 | echo $this->contents; |
---|
1635 | } |
---|
1636 | } |
---|
1637 | |
---|
1638 | /** |
---|
1639 | * BP_Embed |
---|
1640 | * |
---|
1641 | * Extends WP_Embed class for use with BuddyPress. |
---|
1642 | * |
---|
1643 | * @package BuddyPress Core |
---|
1644 | * @since BuddyPress (1.5) |
---|
1645 | * @see WP_Embed |
---|
1646 | */ |
---|
1647 | class BP_Embed extends WP_Embed { |
---|
1648 | |
---|
1649 | /** |
---|
1650 | * Constructor |
---|
1651 | * |
---|
1652 | * @global unknown $wp_embed |
---|
1653 | */ |
---|
1654 | function __construct() { |
---|
1655 | global $wp_embed; |
---|
1656 | |
---|
1657 | // Make sure we populate the WP_Embed handlers array. |
---|
1658 | // These are providers that use a regex callback on the URL in question. |
---|
1659 | // Do not confuse with oEmbed providers, which require an external ping. |
---|
1660 | // Used in WP_Embed::shortcode() |
---|
1661 | $this->handlers = $wp_embed->handlers; |
---|
1662 | |
---|
1663 | if ( bp_use_embed_in_activity() ) { |
---|
1664 | add_filter( 'bp_get_activity_content_body', array( &$this, 'autoembed' ), 8 ); |
---|
1665 | add_filter( 'bp_get_activity_content_body', array( &$this, 'run_shortcode' ), 7 ); |
---|
1666 | } |
---|
1667 | |
---|
1668 | if ( bp_use_embed_in_activity_replies() ) { |
---|
1669 | add_filter( 'bp_get_activity_content', array( &$this, 'autoembed' ), 8 ); |
---|
1670 | add_filter( 'bp_get_activity_content', array( &$this, 'run_shortcode' ), 7 ); |
---|
1671 | } |
---|
1672 | |
---|
1673 | if ( bp_use_embed_in_forum_posts() ) { |
---|
1674 | add_filter( 'bp_get_the_topic_post_content', array( &$this, 'autoembed' ), 8 ); |
---|
1675 | add_filter( 'bp_get_the_topic_post_content', array( &$this, 'run_shortcode' ), 7 ); |
---|
1676 | } |
---|
1677 | |
---|
1678 | if ( bp_use_embed_in_private_messages() ) { |
---|
1679 | add_filter( 'bp_get_the_thread_message_content', array( &$this, 'autoembed' ), 8 ); |
---|
1680 | add_filter( 'bp_get_the_thread_message_content', array( &$this, 'run_shortcode' ), 7 ); |
---|
1681 | } |
---|
1682 | |
---|
1683 | do_action_ref_array( 'bp_core_setup_oembed', array( &$this ) ); |
---|
1684 | } |
---|
1685 | |
---|
1686 | /** |
---|
1687 | * The {@link do_shortcode()} callback function. |
---|
1688 | * |
---|
1689 | * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers. |
---|
1690 | * Next, checks the URL against the regex of registered {@link WP_oEmbed} providers if oEmbed discovery is false. |
---|
1691 | * If none of the regex matches and it's enabled, then the URL will be passed to {@link BP_Embed::parse_oembed()} for oEmbed parsing. |
---|
1692 | * |
---|
1693 | * @uses wp_parse_args() |
---|
1694 | * @uses wp_embed_defaults() |
---|
1695 | * @uses current_user_can() |
---|
1696 | * @uses _wp_oembed_get_object() |
---|
1697 | * @uses WP_Embed::maybe_make_link() |
---|
1698 | * |
---|
1699 | * @param array $attr Shortcode attributes. |
---|
1700 | * @param string $url The URL attempting to be embeded. |
---|
1701 | * @return string The embed HTML on success, otherwise the original URL. |
---|
1702 | */ |
---|
1703 | function shortcode( $attr, $url = '' ) { |
---|
1704 | if ( empty( $url ) ) |
---|
1705 | return ''; |
---|
1706 | |
---|
1707 | $rawattr = $attr; |
---|
1708 | $attr = wp_parse_args( $attr, wp_embed_defaults() ); |
---|
1709 | |
---|
1710 | // kses converts & into & and we need to undo this |
---|
1711 | // See http://core.trac.wordpress.org/ticket/11311 |
---|
1712 | $url = str_replace( '&', '&', $url ); |
---|
1713 | |
---|
1714 | // Look for known internal handlers |
---|
1715 | ksort( $this->handlers ); |
---|
1716 | foreach ( $this->handlers as $priority => $handlers ) { |
---|
1717 | foreach ( $handlers as $hid => $handler ) { |
---|
1718 | if ( preg_match( $handler['regex'], $url, $matches ) && is_callable( $handler['callback'] ) ) { |
---|
1719 | if ( false !== $return = call_user_func( $handler['callback'], $matches, $attr, $url, $rawattr ) ) { |
---|
1720 | return apply_filters( 'embed_handler_html', $return, $url, $attr ); |
---|
1721 | } |
---|
1722 | } |
---|
1723 | } |
---|
1724 | } |
---|
1725 | |
---|
1726 | // Get object ID |
---|
1727 | $id = apply_filters( 'embed_post_id', 0 ); |
---|
1728 | |
---|
1729 | // Is oEmbed discovery on? |
---|
1730 | $attr['discover'] = ( apply_filters( 'bp_embed_oembed_discover', false ) && current_user_can( 'unfiltered_html' ) ); |
---|
1731 | |
---|
1732 | // Set up a new WP oEmbed object to check URL with registered oEmbed providers |
---|
1733 | require_once( ABSPATH . WPINC . '/class-oembed.php' ); |
---|
1734 | $oembed_obj = _wp_oembed_get_object(); |
---|
1735 | |
---|
1736 | // If oEmbed discovery is true, skip oEmbed provider check |
---|
1737 | $is_oembed_link = false; |
---|
1738 | if ( !$attr['discover'] ) { |
---|
1739 | foreach ( (array) $oembed_obj->providers as $provider_matchmask => $provider ) { |
---|
1740 | $regex = ( $is_regex = $provider[1] ) ? $provider_matchmask : '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $provider_matchmask ), '#' ) ) . '#i'; |
---|
1741 | |
---|
1742 | if ( preg_match( $regex, $url ) ) |
---|
1743 | $is_oembed_link = true; |
---|
1744 | } |
---|
1745 | |
---|
1746 | // If url doesn't match a WP oEmbed provider, stop parsing |
---|
1747 | if ( !$is_oembed_link ) |
---|
1748 | return $this->maybe_make_link( $url ); |
---|
1749 | } |
---|
1750 | |
---|
1751 | return $this->parse_oembed( $id, $url, $attr, $rawattr ); |
---|
1752 | } |
---|
1753 | |
---|
1754 | /** |
---|
1755 | * Base function so BP components / plugins can parse links to be embedded. |
---|
1756 | * View an example to add support in {@link bp_activity_embed()}. |
---|
1757 | * |
---|
1758 | * @uses apply_filters() Filters cache. |
---|
1759 | * @uses do_action() To save cache. |
---|
1760 | * @uses wp_oembed_get() Connects to oEmbed provider and returns HTML on success. |
---|
1761 | * @uses WP_Embed::maybe_make_link() Process URL for hyperlinking on oEmbed failure. |
---|
1762 | * @param int $id ID to do the caching for. |
---|
1763 | * @param string $url The URL attempting to be embedded. |
---|
1764 | * @param array $attr Shortcode attributes from {@link WP_Embed::shortcode()}. |
---|
1765 | * @param array $rawattr Untouched shortcode attributes from {@link WP_Embed::shortcode()}. |
---|
1766 | * @return string The embed HTML on success, otherwise the original URL. |
---|
1767 | */ |
---|
1768 | function parse_oembed( $id, $url, $attr, $rawattr ) { |
---|
1769 | $id = intval( $id ); |
---|
1770 | |
---|
1771 | if ( $id ) { |
---|
1772 | // Setup the cachekey |
---|
1773 | $cachekey = '_oembed_' . md5( $url . serialize( $attr ) ); |
---|
1774 | |
---|
1775 | // Let components / plugins grab their cache |
---|
1776 | $cache = ''; |
---|
1777 | $cache = apply_filters( 'bp_embed_get_cache', $cache, $id, $cachekey, $url, $attr, $rawattr ); |
---|
1778 | |
---|
1779 | // Grab cache and return it if available |
---|
1780 | if ( !empty( $cache ) ) { |
---|
1781 | return apply_filters( 'bp_embed_oembed_html', $cache, $url, $attr, $rawattr ); |
---|
1782 | |
---|
1783 | // If no cache, ping the oEmbed provider and cache the result |
---|
1784 | } else { |
---|
1785 | $html = wp_oembed_get( $url, $attr ); |
---|
1786 | $cache = ( $html ) ? $html : $url; |
---|
1787 | |
---|
1788 | // Let components / plugins save their cache |
---|
1789 | do_action( 'bp_embed_update_cache', $cache, $cachekey, $id ); |
---|
1790 | |
---|
1791 | // If there was a result, return it |
---|
1792 | if ( $html ) |
---|
1793 | return apply_filters( 'bp_embed_oembed_html', $html, $url, $attr, $rawattr ); |
---|
1794 | } |
---|
1795 | } |
---|
1796 | |
---|
1797 | // Still unknown |
---|
1798 | return $this->maybe_make_link( $url ); |
---|
1799 | } |
---|
1800 | } |
---|
1801 | |
---|
1802 | /** |
---|
1803 | * Create HTML list of BP nav items |
---|
1804 | * |
---|
1805 | * @since BuddyPress (1.7) |
---|
1806 | */ |
---|
1807 | class BP_Walker_Nav_Menu extends Walker_Nav_Menu { |
---|
1808 | /** |
---|
1809 | * @since BuddyPress (1.7) |
---|
1810 | * @var array |
---|
1811 | */ |
---|
1812 | var $db_fields = array( 'id' => 'css_id', 'parent' => 'parent' ); |
---|
1813 | |
---|
1814 | /** |
---|
1815 | * @since BuddyPress (1.7) |
---|
1816 | * @var string |
---|
1817 | */ |
---|
1818 | var $tree_type = array(); |
---|
1819 | |
---|
1820 | /** |
---|
1821 | * Display array of elements hierarchically. |
---|
1822 | * |
---|
1823 | * This method is almost identical to the version in {@link Walker::walk()}. The only change is on one line |
---|
1824 | * which has been commented. An IF was comparing 0 to a non-empty string which was preventing child elements |
---|
1825 | * being grouped under their parent menu element. |
---|
1826 | * |
---|
1827 | * This caused a problem for BuddyPress because our primary/secondary navigations doesn't have a unique numerical |
---|
1828 | * ID that describes a hierarchy (we use a slug). Obviously, WordPress Menus use Posts, and those have ID/post_parent. |
---|
1829 | * |
---|
1830 | * @param array $elements |
---|
1831 | * @param int $max_depth |
---|
1832 | * @return string |
---|
1833 | * @see Walker::walk() |
---|
1834 | * @since BuddyPress (1.7) |
---|
1835 | */ |
---|
1836 | function walk( $elements, $max_depth ) { |
---|
1837 | $args = array_slice( func_get_args(), 2 ); |
---|
1838 | $output = ''; |
---|
1839 | |
---|
1840 | if ( $max_depth < -1 ) // invalid parameter |
---|
1841 | return $output; |
---|
1842 | |
---|
1843 | if ( empty( $elements ) ) // nothing to walk |
---|
1844 | return $output; |
---|
1845 | |
---|
1846 | $id_field = $this->db_fields['id']; |
---|
1847 | $parent_field = $this->db_fields['parent']; |
---|
1848 | |
---|
1849 | // flat display |
---|
1850 | if ( -1 == $max_depth ) { |
---|
1851 | |
---|
1852 | $empty_array = array(); |
---|
1853 | foreach ( $elements as $e ) |
---|
1854 | $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
---|
1855 | |
---|
1856 | return $output; |
---|
1857 | } |
---|
1858 | |
---|
1859 | /* |
---|
1860 | * need to display in hierarchical order |
---|
1861 | * separate elements into two buckets: top level and children elements |
---|
1862 | * children_elements is two dimensional array, eg. |
---|
1863 | * children_elements[10][] contains all sub-elements whose parent is 10. |
---|
1864 | */ |
---|
1865 | $top_level_elements = array(); |
---|
1866 | $children_elements = array(); |
---|
1867 | |
---|
1868 | foreach ( $elements as $e ) { |
---|
1869 | // BuddyPress: changed '==' to '==='. This is the only change from version in Walker::walk(). |
---|
1870 | if ( 0 === $e->$parent_field ) |
---|
1871 | $top_level_elements[] = $e; |
---|
1872 | else |
---|
1873 | $children_elements[$e->$parent_field][] = $e; |
---|
1874 | } |
---|
1875 | |
---|
1876 | /* |
---|
1877 | * when none of the elements is top level |
---|
1878 | * assume the first one must be root of the sub elements |
---|
1879 | */ |
---|
1880 | if ( empty( $top_level_elements ) ) { |
---|
1881 | |
---|
1882 | $first = array_slice( $elements, 0, 1 ); |
---|
1883 | $root = $first[0]; |
---|
1884 | $top_level_elements = array(); |
---|
1885 | $children_elements = array(); |
---|
1886 | |
---|
1887 | foreach ( $elements as $e ) { |
---|
1888 | if ( $root->$parent_field == $e->$parent_field ) |
---|
1889 | $top_level_elements[] = $e; |
---|
1890 | else |
---|
1891 | $children_elements[$e->$parent_field][] = $e; |
---|
1892 | } |
---|
1893 | } |
---|
1894 | |
---|
1895 | foreach ( $top_level_elements as $e ) |
---|
1896 | $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
---|
1897 | |
---|
1898 | /* |
---|
1899 | * if we are displaying all levels, and remaining children_elements is not empty, |
---|
1900 | * then we got orphans, which should be displayed regardless |
---|
1901 | */ |
---|
1902 | if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) { |
---|
1903 | $empty_array = array(); |
---|
1904 | |
---|
1905 | foreach ( $children_elements as $orphans ) |
---|
1906 | foreach ( $orphans as $op ) |
---|
1907 | $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
---|
1908 | } |
---|
1909 | |
---|
1910 | return $output; |
---|
1911 | } |
---|
1912 | |
---|
1913 | /** |
---|
1914 | * Displays the current <li> that we are on. |
---|
1915 | * |
---|
1916 | * @param string $output Passed by reference. Used to append additional content. |
---|
1917 | * @param object $item Menu item data object. |
---|
1918 | * @param int $depth Depth of menu item. Used for padding. Optional, defaults to 0. |
---|
1919 | * @param array $args Optional |
---|
1920 | * @param int $current_page Menu item ID. Optional. |
---|
1921 | * @since BuddyPress (1.7) |
---|
1922 | */ |
---|
1923 | function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { |
---|
1924 | // If we're someway down the tree, indent the HTML with the appropriate number of tabs |
---|
1925 | $indent = $depth ? str_repeat( "\t", $depth ) : ''; |
---|
1926 | |
---|
1927 | // Add HTML classes |
---|
1928 | $class_names = join( ' ', apply_filters( 'bp_nav_menu_css_class', array_filter( $item->class ), $item, $args ) ); |
---|
1929 | $class_names = ! empty( $class_names ) ? ' class="' . esc_attr( $class_names ) . '"' : ''; |
---|
1930 | |
---|
1931 | // Add HTML ID |
---|
1932 | $id = sanitize_html_class( $item->css_id . '-personal-li' ); // Backpat with BP pre-1.7 |
---|
1933 | $id = apply_filters( 'bp_nav_menu_item_id', $id, $item, $args ); |
---|
1934 | $id = ! empty( $id ) ? ' id="' . esc_attr( $id ) . '"' : ''; |
---|
1935 | |
---|
1936 | // Opening tag; closing tag is handled in Walker_Nav_Menu::end_el(). |
---|
1937 | $output .= $indent . '<li' . $id . $class_names . '>'; |
---|
1938 | |
---|
1939 | // Add href attribute |
---|
1940 | $attributes = ! empty( $item->link ) ? ' href="' . esc_attr( esc_url( $item->link ) ) . '"' : ''; |
---|
1941 | |
---|
1942 | // Construct the link |
---|
1943 | $item_output = $args->before; |
---|
1944 | $item_output .= '<a' . $attributes . '>'; |
---|
1945 | $item_output .= $args->link_before . apply_filters( 'the_title', $item->name, 0 ) . $args->link_after; |
---|
1946 | $item_output .= '</a>'; |
---|
1947 | $item_output .= $args->after; |
---|
1948 | |
---|
1949 | // $output is byref |
---|
1950 | $output .= apply_filters( 'bp_walker_nav_menu_start_el', $item_output, $item, $depth, $args ); |
---|
1951 | } |
---|
1952 | } |
---|