|
1 <?php |
|
2 |
|
3 /** |
|
4 * bbPress Template Functions |
|
5 * |
|
6 * This file contains functions necessary to mirror the WordPress core template |
|
7 * loading process. Many of those functions are not filterable, and even then |
|
8 * would not be robust enough to predict where bbPress templates might exist. |
|
9 * |
|
10 * @package bbPress |
|
11 * @subpackage TemplateFunctions |
|
12 */ |
|
13 |
|
14 // Exit if accessed directly |
|
15 if ( !defined( 'ABSPATH' ) ) exit; |
|
16 |
|
17 /** |
|
18 * Adds bbPress theme support to any active WordPress theme |
|
19 * |
|
20 * @since bbPress (r3032) |
|
21 * |
|
22 * @param string $slug |
|
23 * @param string $name Optional. Default null |
|
24 * @uses bbp_locate_template() |
|
25 * @uses load_template() |
|
26 * @uses get_template_part() |
|
27 */ |
|
28 function bbp_get_template_part( $slug, $name = null ) { |
|
29 |
|
30 // Execute code for this part |
|
31 do_action( 'get_template_part_' . $slug, $slug, $name ); |
|
32 |
|
33 // Setup possible parts |
|
34 $templates = array(); |
|
35 if ( isset( $name ) ) |
|
36 $templates[] = $slug . '-' . $name . '.php'; |
|
37 $templates[] = $slug . '.php'; |
|
38 |
|
39 // Allow template parst to be filtered |
|
40 $templates = apply_filters( 'bbp_get_template_part', $templates, $slug, $name ); |
|
41 |
|
42 // Return the part that is found |
|
43 return bbp_locate_template( $templates, true, false ); |
|
44 } |
|
45 |
|
46 /** |
|
47 * Retrieve the name of the highest priority template file that exists. |
|
48 * |
|
49 * Searches in the child theme before parent theme so that themes which |
|
50 * inherit from a parent theme can just overload one file. If the template is |
|
51 * not found in either of those, it looks in the theme-compat folder last. |
|
52 * |
|
53 * @since bbPres (r3618) |
|
54 * |
|
55 * @param string|array $template_names Template file(s) to search for, in order. |
|
56 * @param bool $load If true the template file will be loaded if it is found. |
|
57 * @param bool $require_once Whether to require_once or require. Default true. |
|
58 * Has no effect if $load is false. |
|
59 * @return string The template filename if one is located. |
|
60 */ |
|
61 function bbp_locate_template( $template_names, $load = false, $require_once = true ) { |
|
62 |
|
63 // No file found yet |
|
64 $located = false; |
|
65 $template_locations = bbp_get_template_stack(); |
|
66 |
|
67 // Try to find a template file |
|
68 foreach ( (array) $template_names as $template_name ) { |
|
69 |
|
70 // Continue if template is empty |
|
71 if ( empty( $template_name ) ) |
|
72 continue; |
|
73 |
|
74 // Trim off any slashes from the template name |
|
75 $template_name = ltrim( $template_name, '/' ); |
|
76 |
|
77 // Loop through template stack |
|
78 foreach ( (array) $template_locations as $template_location ) { |
|
79 |
|
80 // Continue if $template_location is empty |
|
81 if ( empty( $template_location ) ) |
|
82 continue; |
|
83 |
|
84 // Check child theme first |
|
85 if ( file_exists( trailingslashit( $template_location ) . $template_name ) ) { |
|
86 $located = trailingslashit( $template_location ) . $template_name; |
|
87 break 2; |
|
88 } |
|
89 } |
|
90 } |
|
91 |
|
92 // Maybe load the template if one was located |
|
93 if ( ( true == $load ) && !empty( $located ) ) |
|
94 load_template( $located, $require_once ); |
|
95 |
|
96 return $located; |
|
97 } |
|
98 |
|
99 /** |
|
100 * This is really cool. This function registers a new template stack location, |
|
101 * using WordPress's built in filters API. |
|
102 * |
|
103 * This allows for templates to live in places beyond just the parent/child |
|
104 * relationship, to allow for custom template locations. Used in conjunction |
|
105 * with bbp_locate_template(), this allows for easy template overrides. |
|
106 * |
|
107 * @since bbPress (r4323) |
|
108 * |
|
109 * @param string $location Callback function that returns the |
|
110 * @param int $priority |
|
111 */ |
|
112 function bbp_register_template_stack( $location_callback = '', $priority = 10 ) { |
|
113 |
|
114 // Bail if no location, or function does not exist |
|
115 if ( empty( $location_callback ) || ! function_exists( $location_callback ) ) |
|
116 return false; |
|
117 |
|
118 // Add location callback to template stack |
|
119 add_filter( 'bbp_template_stack', $location_callback, (int) $priority ); |
|
120 } |
|
121 |
|
122 /** |
|
123 * Call the functions added to the 'bbp_template_stack' filter hook, and return |
|
124 * an array of the template locations. |
|
125 * |
|
126 * @see bbp_register_template_stack() |
|
127 * |
|
128 * @since bbPress (r4323) |
|
129 * |
|
130 * @global array $wp_filter Stores all of the filters |
|
131 * @global array $merged_filters Merges the filter hooks using this function. |
|
132 * @global array $wp_current_filter stores the list of current filters with the current one last |
|
133 * |
|
134 * @return array The filtered value after all hooked functions are applied to it. |
|
135 */ |
|
136 function bbp_get_template_stack() { |
|
137 global $wp_filter, $merged_filters, $wp_current_filter; |
|
138 |
|
139 // Setup some default variables |
|
140 $tag = 'bbp_template_stack'; |
|
141 $args = $stack = array(); |
|
142 |
|
143 // Add 'bbp_template_stack' to the current filter array |
|
144 $wp_current_filter[] = $tag; |
|
145 |
|
146 // Sort |
|
147 if ( ! isset( $merged_filters[ $tag ] ) ) { |
|
148 ksort( $wp_filter[$tag] ); |
|
149 $merged_filters[ $tag ] = true; |
|
150 } |
|
151 |
|
152 // Ensure we're always at the beginning of the filter array |
|
153 reset( $wp_filter[ $tag ] ); |
|
154 |
|
155 // Loop through 'bbp_template_stack' filters, and call callback functions |
|
156 do { |
|
157 foreach( (array) current( $wp_filter[$tag] ) as $the_ ) { |
|
158 if ( ! is_null( $the_['function'] ) ) { |
|
159 $args[1] = $stack; |
|
160 $stack[] = call_user_func_array( $the_['function'], array_slice( $args, 1, (int) $the_['accepted_args'] ) ); |
|
161 } |
|
162 } |
|
163 } while ( next( $wp_filter[$tag] ) !== false ); |
|
164 |
|
165 // Remove 'bbp_template_stack' from the current filter array |
|
166 array_pop( $wp_current_filter ); |
|
167 |
|
168 // Remove empties and duplicates |
|
169 $stack = array_unique( array_filter( $stack ) ); |
|
170 |
|
171 return (array) apply_filters( 'bbp_get_template_stack', $stack ) ; |
|
172 } |
|
173 |
|
174 /** |
|
175 * Retrieve path to a template |
|
176 * |
|
177 * Used to quickly retrieve the path of a template without including the file |
|
178 * extension. It will also check the parent theme and theme-compat theme with |
|
179 * the use of {@link bbp_locate_template()}. Allows for more generic template |
|
180 * locations without the use of the other get_*_template() functions. |
|
181 * |
|
182 * @since bbPress (r3629) |
|
183 * |
|
184 * @param string $type Filename without extension. |
|
185 * @param array $templates An optional list of template candidates |
|
186 * @uses bbp_set_theme_compat_templates() |
|
187 * @uses bbp_locate_template() |
|
188 * @uses bbp_set_theme_compat_template() |
|
189 * @return string Full path to file. |
|
190 */ |
|
191 function bbp_get_query_template( $type, $templates = array() ) { |
|
192 $type = preg_replace( '|[^a-z0-9-]+|', '', $type ); |
|
193 |
|
194 if ( empty( $templates ) ) |
|
195 $templates = array( "{$type}.php" ); |
|
196 |
|
197 // Filter possible templates, try to match one, and set any bbPress theme |
|
198 // compat properties so they can be cross-checked later. |
|
199 $templates = apply_filters( "bbp_get_{$type}_template", $templates ); |
|
200 $templates = bbp_set_theme_compat_templates( $templates ); |
|
201 $template = bbp_locate_template( $templates ); |
|
202 $template = bbp_set_theme_compat_template( $template ); |
|
203 |
|
204 return apply_filters( "bbp_{$type}_template", $template ); |
|
205 } |
|
206 |
|
207 /** |
|
208 * Get the possible subdirectories to check for templates in |
|
209 * |
|
210 * @since bbPress (r3738) |
|
211 * @param array $templates Templates we are looking for |
|
212 * @return array Possible subfolders to look in |
|
213 */ |
|
214 function bbp_get_template_locations( $templates = array() ) { |
|
215 $locations = array( |
|
216 'bbpress', |
|
217 'forums', |
|
218 '' |
|
219 ); |
|
220 return apply_filters( 'bbp_get_template_locations', $locations, $templates ); |
|
221 } |
|
222 |
|
223 /** |
|
224 * Add template locations to template files being searched for |
|
225 * |
|
226 * @since bbPress (r3738) |
|
227 * |
|
228 * @param array $templates |
|
229 * @return array() |
|
230 */ |
|
231 function bbp_add_template_locations( $templates = array() ) { |
|
232 $retval = array(); |
|
233 |
|
234 // Get alternate locations |
|
235 $locations = bbp_get_template_locations( $templates ); |
|
236 |
|
237 // Loop through locations and templates and combine |
|
238 foreach ( (array) $locations as $location ) |
|
239 foreach ( (array) $templates as $template ) |
|
240 $retval[] = ltrim( trailingslashit( $location ) . $template, '/' ); |
|
241 |
|
242 return apply_filters( 'bbp_add_template_locations', array_unique( $retval ), $templates ); |
|
243 } |
|
244 |
|
245 /** |
|
246 * Add checks for bbPress conditions to parse_query action |
|
247 * |
|
248 * If it's a user page, WP_Query::bbp_is_single_user is set to true. |
|
249 * If it's a user edit page, WP_Query::bbp_is_single_user_edit is set to true |
|
250 * and the the 'wp-admin/includes/user.php' file is included. |
|
251 * In addition, on user/user edit pages, WP_Query::home is set to false & query |
|
252 * vars 'bbp_user_id' with the displayed user id and 'author_name' with the |
|
253 * displayed user's nicename are added. |
|
254 * |
|
255 * If it's a forum edit, WP_Query::bbp_is_forum_edit is set to true |
|
256 * If it's a topic edit, WP_Query::bbp_is_topic_edit is set to true |
|
257 * If it's a reply edit, WP_Query::bbp_is_reply_edit is set to true. |
|
258 * |
|
259 * If it's a view page, WP_Query::bbp_is_view is set to true |
|
260 * |
|
261 * @since bbPress (r2688) |
|
262 * |
|
263 * @param WP_Query $posts_query |
|
264 * |
|
265 * @uses get_query_var() To get {@link WP_Query} query var |
|
266 * @uses is_email() To check if the string is an email |
|
267 * @uses get_user_by() To try to get the user by email and nicename |
|
268 * @uses get_userdata() to get the user data |
|
269 * @uses current_user_can() To check if the current user can edit the user |
|
270 * @uses is_user_member_of_blog() To check if user profile page exists |
|
271 * @uses WP_Query::set_404() To set a 404 status |
|
272 * @uses apply_filters() Calls 'enable_edit_any_user_configuration' with true |
|
273 * @uses bbp_get_view_query_args() To get the view query args |
|
274 * @uses bbp_get_forum_post_type() To get the forum post type |
|
275 * @uses bbp_get_topic_post_type() To get the topic post type |
|
276 * @uses bbp_get_reply_post_type() To get the reply post type |
|
277 * @uses remove_action() To remove the auto save post revision action |
|
278 */ |
|
279 function bbp_parse_query( $posts_query ) { |
|
280 |
|
281 // Bail if $posts_query is not the main loop |
|
282 if ( ! $posts_query->is_main_query() ) |
|
283 return; |
|
284 |
|
285 // Bail if filters are suppressed on this query |
|
286 if ( true == $posts_query->get( 'suppress_filters' ) ) |
|
287 return; |
|
288 |
|
289 // Bail if in admin |
|
290 if ( is_admin() ) |
|
291 return; |
|
292 |
|
293 // Get query variables |
|
294 $bbp_view = $posts_query->get( bbp_get_view_rewrite_id() ); |
|
295 $bbp_user = $posts_query->get( bbp_get_user_rewrite_id() ); |
|
296 $is_edit = $posts_query->get( bbp_get_edit_rewrite_id() ); |
|
297 |
|
298 // It is a user page - We'll also check if it is user edit |
|
299 if ( !empty( $bbp_user ) ) { |
|
300 |
|
301 // Not a user_id so try email and slug |
|
302 if ( !is_numeric( $bbp_user ) ) { |
|
303 |
|
304 // Email was passed |
|
305 if ( is_email( $bbp_user ) ) { |
|
306 $bbp_user = get_user_by( 'email', $bbp_user ); |
|
307 |
|
308 // Try nicename |
|
309 } else { |
|
310 $bbp_user = get_user_by( 'slug', $bbp_user ); |
|
311 } |
|
312 |
|
313 // If we were successful, set to ID |
|
314 if ( is_object( $bbp_user ) ) { |
|
315 $bbp_user = $bbp_user->ID; |
|
316 } |
|
317 } |
|
318 |
|
319 // Cast as int, just in case |
|
320 $bbp_user = (int) $bbp_user; |
|
321 |
|
322 // 404 and bail if user does not have a profile |
|
323 if ( ! bbp_user_has_profile( $bbp_user ) ) { |
|
324 $posts_query->set_404(); |
|
325 return; |
|
326 } |
|
327 |
|
328 /** User Exists *******************************************************/ |
|
329 |
|
330 $is_favs = $posts_query->get( bbp_get_user_favorites_rewrite_id() ); |
|
331 $is_subs = $posts_query->get( bbp_get_user_subscriptions_rewrite_id() ); |
|
332 $is_topics = $posts_query->get( bbp_get_user_topics_rewrite_id() ); |
|
333 $is_replies = $posts_query->get( bbp_get_user_replies_rewrite_id() ); |
|
334 |
|
335 // View or edit? |
|
336 if ( !empty( $is_edit ) ) { |
|
337 |
|
338 // We are editing a profile |
|
339 $posts_query->bbp_is_single_user_edit = true; |
|
340 |
|
341 // Load the core WordPress contact methods |
|
342 if ( !function_exists( '_wp_get_user_contactmethods' ) ) { |
|
343 include_once( ABSPATH . 'wp-includes/registration.php' ); |
|
344 } |
|
345 |
|
346 // Load the edit_user functions |
|
347 if ( !function_exists( 'edit_user' ) ) { |
|
348 require_once( ABSPATH . 'wp-admin/includes/user.php' ); |
|
349 } |
|
350 |
|
351 // Load the grant/revoke super admin functions |
|
352 if ( is_multisite() && !function_exists( 'revoke_super_admin' ) ) { |
|
353 require_once( ABSPATH . 'wp-admin/includes/ms.php' ); |
|
354 } |
|
355 |
|
356 // Editing a user |
|
357 $posts_query->bbp_is_edit = true; |
|
358 |
|
359 // User favorites |
|
360 } elseif ( ! empty( $is_favs ) ) { |
|
361 $posts_query->bbp_is_single_user_favs = true; |
|
362 |
|
363 // User subscriptions |
|
364 } elseif ( ! empty( $is_subs ) ) { |
|
365 $posts_query->bbp_is_single_user_subs = true; |
|
366 |
|
367 // User topics |
|
368 } elseif ( ! empty( $is_topics ) ) { |
|
369 $posts_query->bbp_is_single_user_topics = true; |
|
370 |
|
371 // User topics |
|
372 } elseif ( ! empty( $is_replies ) ) { |
|
373 $posts_query->bbp_is_single_user_replies = true; |
|
374 |
|
375 // User profile |
|
376 } else { |
|
377 $posts_query->bbp_is_single_user_profile = true; |
|
378 } |
|
379 |
|
380 // Looking at a single user |
|
381 $posts_query->bbp_is_single_user = true; |
|
382 |
|
383 // Make sure 404 is not set |
|
384 $posts_query->is_404 = false; |
|
385 |
|
386 // Correct is_home variable |
|
387 $posts_query->is_home = false; |
|
388 |
|
389 // Get the user data |
|
390 $user = get_userdata( $bbp_user ); |
|
391 |
|
392 // User is looking at their own profile |
|
393 if ( get_current_user_id() == $user->ID ) { |
|
394 $posts_query->bbp_is_single_user_home = true; |
|
395 } |
|
396 |
|
397 // Set bbp_user_id for future reference |
|
398 $posts_query->set( 'bbp_user_id', $user->ID ); |
|
399 |
|
400 // Set author_name as current user's nicename to get correct posts |
|
401 $posts_query->set( 'author_name', $user->user_nicename ); |
|
402 |
|
403 // Set the displayed user global to this user |
|
404 bbpress()->displayed_user = $user; |
|
405 |
|
406 // View Page |
|
407 } elseif ( !empty( $bbp_view ) ) { |
|
408 |
|
409 // Check if the view exists by checking if there are query args are set |
|
410 $view_args = bbp_get_view_query_args( $bbp_view ); |
|
411 |
|
412 // Bail if view args is false (view isn't registered) |
|
413 if ( false === $view_args ) { |
|
414 $posts_query->set_404(); |
|
415 return; |
|
416 } |
|
417 |
|
418 // Correct is_home variable |
|
419 $posts_query->is_home = false; |
|
420 |
|
421 // We are in a custom topic view |
|
422 $posts_query->bbp_is_view = true; |
|
423 |
|
424 // Forum/Topic/Reply Edit Page |
|
425 } elseif ( !empty( $is_edit ) ) { |
|
426 |
|
427 // Get the post type from the main query loop |
|
428 $post_type = $posts_query->get( 'post_type' ); |
|
429 |
|
430 // Check which post_type we are editing, if any |
|
431 if ( !empty( $post_type ) ) { |
|
432 switch( $post_type ) { |
|
433 |
|
434 // We are editing a forum |
|
435 case bbp_get_forum_post_type() : |
|
436 $posts_query->bbp_is_forum_edit = true; |
|
437 $posts_query->bbp_is_edit = true; |
|
438 break; |
|
439 |
|
440 // We are editing a topic |
|
441 case bbp_get_topic_post_type() : |
|
442 $posts_query->bbp_is_topic_edit = true; |
|
443 $posts_query->bbp_is_edit = true; |
|
444 break; |
|
445 |
|
446 // We are editing a reply |
|
447 case bbp_get_reply_post_type() : |
|
448 $posts_query->bbp_is_reply_edit = true; |
|
449 $posts_query->bbp_is_edit = true; |
|
450 break; |
|
451 } |
|
452 |
|
453 // We are editing a topic tag |
|
454 } elseif ( bbp_is_topic_tag() ) { |
|
455 $posts_query->bbp_is_topic_tag_edit = true; |
|
456 $posts_query->bbp_is_edit = true; |
|
457 } |
|
458 |
|
459 // We save post revisions on our own |
|
460 remove_action( 'pre_post_update', 'wp_save_post_revision' ); |
|
461 |
|
462 // Topic tag page |
|
463 } elseif ( bbp_is_topic_tag() ) { |
|
464 $posts_query->set( 'bbp_topic_tag', get_query_var( 'term' ) ); |
|
465 $posts_query->set( 'post_type', bbp_get_topic_post_type() ); |
|
466 $posts_query->set( 'posts_per_page', bbp_get_topics_per_page() ); |
|
467 } |
|
468 } |