PluginProbe
bbPress / 2.6.9
bbPress v2.6.9
trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.2.2 All 71 releases
bbpress / bbpress.php

bbpress.php in bbPress 2.6.9, at bbpress.php

1,065 lines 38.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The bbPress Plugin
5 *
6 * bbPress is forum software with a twist from the creators of WordPress.
7 *
8 * $Id: bbpress.php 7228 2021-11-29 15:22:27Z johnjamesjacoby $
9 *
10 * @package bbPress
11 * @subpackage Main
12 */
13
14 /**
15 * Plugin Name: bbPress
16 * Plugin URI: https://bbpress.org
17 * Description: bbPress is forum software with a twist from the creators of WordPress.
18 * Author: The bbPress Contributors
19 * Author URI: https://bbpress.org
20 * Version: 2.6.9
21 * Text Domain: bbpress
22 * Domain Path: /languages/
23 * License: GPLv2 or later (license.txt)
24 * Requires PHP: 5.6.20
25 * Requires at least: 5.0
26 */
27
28 // Exit if accessed directly
29 defined( 'ABSPATH' ) || exit;
30
31 if ( ! class_exists( 'bbPress' ) ) :
32 /**
33 * Main bbPress Class
34 *
35 * "Word hard. Stay bumble."
36 *
37 * @since 2.0.0 bbPress (r2464)
38 */
39 final class bbPress {
40
41 /** Magic *****************************************************************/
42
43 /**
44 * bbPress uses many variables, several of which can be filtered to
45 * customize the way it operates. Most of these variables are stored in a
46 * private array that gets updated with the help of PHP magic methods.
47 *
48 * This is a precautionary measure, to avoid potential errors produced by
49 * unanticipated direct manipulation of run-time data.
50 *
51 * @see bbPress::setup_globals()
52 * @var array
53 */
54 private $data;
55
56 /** Not Magic *************************************************************/
57
58 /**
59 * @var mixed False when not logged in; WP_User object when logged in
60 */
61 public $current_user = false;
62
63 /**
64 * @var stdClass Add-ons append to this (Akismet, BuddyPress, etc...)
65 */
66 public $extend;
67
68 /**
69 * @var array Topic views
70 */
71 public $views = array();
72
73 /**
74 * @var array Overloads get_option()
75 */
76 public $options = array();
77
78 /**
79 * @var array Storage of options not in the database
80 */
81 public $not_options = array();
82
83 /**
84 * @var array Overloads get_user_meta()
85 */
86 public $user_options = array();
87
88 /**
89 * @var array Dynamically initialized user roles
90 */
91 public $roles = array();
92
93 /** Singleton *************************************************************/
94
95 /**
96 * Main bbPress Instance
97 *
98 * bbPress is fun
99 * Please load it only one time
100 * For this, we thank you
101 *
102 * Insures that only one instance of bbPress exists in memory at any one
103 * time. Also prevents needing to define globals all over the place.
104 *
105 * @since 2.1.0 bbPress (r3757)
106 *
107 * @staticvar object $instance
108 * @see bbpress()
109 * @return bbPress The one true bbPress
110 */
111 public static function instance() {
112
113 // Store the instance locally to avoid private static replication
114 static $instance = null;
115
116 // Only run these methods if they haven't been ran previously
117 if ( null === $instance ) {
118 $instance = new bbPress();
119 $instance->setup_environment();
120 $instance->includes();
121 $instance->setup_variables();
122 $instance->setup_actions();
123 }
124
125 // Always return the instance
126 return $instance;
127 }
128
129 /** Magic Methods *********************************************************/
130
131 /**
132 * A dummy constructor to prevent bbPress from being loaded more than once.
133 *
134 * @since 2.0.0 bbPress (r2464)
135 *
136 * @see bbPress::instance()
137 * @see bbpress();
138 */
139 private function __construct() { /* Do nothing here */ }
140
141 /**
142 * A dummy magic method to prevent bbPress from being cloned
143 *
144 * @since 2.0.0 bbPress (r2464)
145 */
146 public function __clone() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bbpress' ), '2.1' ); }
147
148 /**
149 * A dummy magic method to prevent bbPress from being unserialized
150 *
151 * @since 2.0.0 bbPress (r2464)
152 */
153 public function __wakeup() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'bbpress' ), '2.1' ); }
154
155 /**
156 * Magic method for checking the existence of a certain custom field
157 *
158 * @since 2.1.0 bbPress (r3951)
159 */
160 public function __isset( $key ) { return isset( $this->data[ $key ] ); }
161
162 /**
163 * Magic method for getting bbPress variables
164 *
165 * @since 2.1.0 bbPress (r3951)
166 */
167 public function __get( $key ) { return isset( $this->data[ $key ] ) ? $this->data[ $key ] : null; }
168
169 /**
170 * Magic method for setting bbPress variables
171 *
172 * @since 2.1.0 bbPress (r3951)
173 */
174 public function __set( $key , $value ) { $this->data[ $key ] = $value; }
175
176 /**
177 * Magic method for unsetting bbPress variables
178 *
179 * @since 2.3.0 bbPress (r4628)
180 */
181 public function __unset( $key ) {
182 if ( isset( $this->data[ $key ] ) ) {
183 unset( $this->data[ $key ] );
184 }
185 }
186
187 /**
188 * Magic method to prevent notices and errors from invalid method calls
189 *
190 * @since 2.2.0 bbPress (r4252)
191 */
192 public function __call( $name = '', $args = array() ) { unset( $name, $args ); return null; }
193
194 /** Private Methods *******************************************************/
195
196 /**
197 * Setup the environment variables to allow the rest of bbPress to function
198 * more easily.
199 *
200 * @since 2.0.0 bbPress (r2626)
201 *
202 * @access private
203 */
204 private function setup_environment() {
205
206 /** Versions **********************************************************/
207
208 $this->version = '2.6.9';
209 $this->db_version = '263';
210
211 /** Paths *************************************************************/
212
213 // File & base
214 $this->file = __FILE__;
215 $this->basename = apply_filters( 'bbp_plugin_basename', str_replace( array( 'build/', 'src/' ), '', plugin_basename( $this->file ) ) );
216 $this->basepath = apply_filters( 'bbp_plugin_basepath', trailingslashit( dirname( $this->basename ) ) );
217
218 // Path and URL
219 $this->plugin_dir = apply_filters( 'bbp_plugin_dir_path', plugin_dir_path( $this->file ) );
220 $this->plugin_url = apply_filters( 'bbp_plugin_dir_url', plugin_dir_url ( $this->file ) );
221
222 // Includes
223 $this->includes_dir = apply_filters( 'bbp_includes_dir', trailingslashit( $this->plugin_dir . 'includes' ) );
224 $this->includes_url = apply_filters( 'bbp_includes_url', trailingslashit( $this->plugin_url . 'includes' ) );
225
226 // Languages
227 $this->lang_base = apply_filters( 'bbp_lang_base', trailingslashit( $this->basepath . 'languages' ) );
228 $this->lang_dir = apply_filters( 'bbp_lang_dir', trailingslashit( $this->plugin_dir . 'languages' ) );
229
230 // Templates
231 $this->themes_dir = apply_filters( 'bbp_themes_dir', trailingslashit( $this->plugin_dir . 'templates' ) );
232 $this->themes_url = apply_filters( 'bbp_themes_url', trailingslashit( $this->plugin_url . 'templates' ) );
233 }
234
235 /**
236 * Smart defaults to many bbPress specific class variables.
237 *
238 * @since 2.6.0 bbPress (r6330)
239 */
240 private function setup_variables() {
241
242 /** Identifiers *******************************************************/
243
244 // Post type identifiers
245 $this->forum_post_type = apply_filters( 'bbp_forum_post_type', 'forum' );
246 $this->topic_post_type = apply_filters( 'bbp_topic_post_type', 'topic' );
247 $this->topic_tag_tax_id = apply_filters( 'bbp_topic_tag_tax_id', 'topic-tag' );
248 $this->reply_post_type = apply_filters( 'bbp_reply_post_type', 'reply' );
249
250 // Status identifiers
251 $this->spam_status_id = apply_filters( 'bbp_spam_post_status', 'spam' );
252 $this->closed_status_id = apply_filters( 'bbp_closed_post_status', 'closed' );
253 $this->orphan_status_id = apply_filters( 'bbp_orphan_post_status', 'orphan' );
254 $this->public_status_id = apply_filters( 'bbp_public_post_status', 'publish' );
255 $this->pending_status_id = apply_filters( 'bbp_pending_post_status', 'pending' );
256 $this->private_status_id = apply_filters( 'bbp_private_post_status', 'private' );
257 $this->hidden_status_id = apply_filters( 'bbp_hidden_post_status', 'hidden' );
258 $this->trash_status_id = apply_filters( 'bbp_trash_post_status', 'trash' );
259
260 // Other identifiers
261 $this->user_id = apply_filters( 'bbp_user_id', 'bbp_user' );
262 $this->tops_id = apply_filters( 'bbp_tops_id', 'bbp_tops' );
263 $this->reps_id = apply_filters( 'bbp_reps_id', 'bbp_reps' );
264 $this->favs_id = apply_filters( 'bbp_favs_id', 'bbp_favs' );
265 $this->subs_id = apply_filters( 'bbp_subs_id', 'bbp_subs' );
266 $this->view_id = apply_filters( 'bbp_view_id', 'bbp_view' );
267 $this->edit_id = apply_filters( 'bbp_edit_id', 'edit' );
268 $this->paged_id = apply_filters( 'bbp_paged_id', 'paged' );
269 $this->search_id = apply_filters( 'bbp_search_id', 'bbp_search' );
270 $this->engagements_id = apply_filters( 'bbp_engagements_id', 'bbp_engagements' );
271
272 /** Queries ***********************************************************/
273
274 $this->current_view_id = 0; // Current view id
275 $this->current_forum_id = 0; // Current forum id
276 $this->current_topic_id = 0; // Current topic id
277 $this->current_reply_id = 0; // Current reply id
278 $this->current_topic_tag_id = 0; // Current topic tag id
279 $this->current_user_id = 0; // Current topic tag id
280
281 $this->forum_query = new WP_Query(); // Main forum query
282 $this->topic_query = new WP_Query(); // Main topic query
283 $this->reply_query = new WP_Query(); // Main reply query
284 $this->search_query = new WP_Query(); // Main search query
285 $this->user_query = new BBP_User_Query(); // Main user query
286
287 /** Theme Compat ******************************************************/
288
289 $this->theme_compat = new stdClass(); // Base theme compatibility class
290 $this->filters = new stdClass(); // Used when adding/removing filters
291
292 /** Users *************************************************************/
293
294 $this->current_user = new WP_User(); // Currently logged in user
295 $this->displayed_user = new WP_User(); // Currently displayed user
296
297 /** Misc **************************************************************/
298
299 $this->domain = 'bbpress'; // Unique identifier for retrieving translated strings
300 $this->extend = new stdClass(); // Plugins add data here
301 $this->errors = new WP_Error(); // Feedback
302
303 /** Deprecated ********************************************************/
304
305 $this->tab_index = apply_filters( 'bbp_default_tab_index', 100 );
306 }
307
308 /**
309 * Include required files
310 *
311 * @since 2.0.0 bbPress (r2626)
312 *
313 * @access private
314 */
315 private function includes() {
316
317 /** Core **************************************************************/
318
319 require $this->includes_dir . 'core/abstraction.php';
320 require $this->includes_dir . 'core/sub-actions.php';
321 require $this->includes_dir . 'core/functions.php';
322 require $this->includes_dir . 'core/cache.php';
323 require $this->includes_dir . 'core/options.php';
324 require $this->includes_dir . 'core/capabilities.php';
325 require $this->includes_dir . 'core/update.php';
326 require $this->includes_dir . 'core/template-functions.php';
327 require $this->includes_dir . 'core/template-loader.php';
328 require $this->includes_dir . 'core/theme-compat.php';
329
330 /** Components ********************************************************/
331
332 // Common
333 require $this->includes_dir . 'common/ajax.php';
334 require $this->includes_dir . 'common/classes.php';
335 require $this->includes_dir . 'common/engagements.php';
336 require $this->includes_dir . 'common/functions.php';
337 require $this->includes_dir . 'common/formatting.php';
338 require $this->includes_dir . 'common/locale.php';
339 require $this->includes_dir . 'common/locks.php';
340 require $this->includes_dir . 'common/template.php';
341 require $this->includes_dir . 'common/widgets.php';
342 require $this->includes_dir . 'common/shortcodes.php';
343
344 // Forums
345 require $this->includes_dir . 'forums/capabilities.php';
346 require $this->includes_dir . 'forums/functions.php';
347 require $this->includes_dir . 'forums/template.php';
348
349 // Topics
350 require $this->includes_dir . 'topics/capabilities.php';
351 require $this->includes_dir . 'topics/functions.php';
352 require $this->includes_dir . 'topics/template.php';
353
354 // Replies
355 require $this->includes_dir . 'replies/capabilities.php';
356 require $this->includes_dir . 'replies/functions.php';
357 require $this->includes_dir . 'replies/template.php';
358
359 // Search
360 require $this->includes_dir . 'search/functions.php';
361 require $this->includes_dir . 'search/template.php';
362
363 // Users
364 require $this->includes_dir . 'users/capabilities.php';
365 require $this->includes_dir . 'users/engagements.php';
366 require $this->includes_dir . 'users/functions.php';
367 require $this->includes_dir . 'users/template.php';
368 require $this->includes_dir . 'users/options.php';
369 require $this->includes_dir . 'users/signups.php';
370
371 /** Hooks *************************************************************/
372
373 require $this->includes_dir . 'core/extend.php';
374 require $this->includes_dir . 'core/actions.php';
375 require $this->includes_dir . 'core/filters.php';
376
377 /** Admin *************************************************************/
378
379 // Quick admin check and load if needed
380 if ( is_admin() ) {
381 require $this->includes_dir . 'admin/actions.php';
382 }
383 }
384
385 /**
386 * Setup the default hooks and actions
387 *
388 * @since 2.0.0 bbPress (r2644)
389 *
390 * @access private
391 */
392 private function setup_actions() {
393
394 // Add actions to plugin activation and deactivation hooks
395 add_action( 'activate_' . $this->basename, 'bbp_activation' );
396 add_action( 'deactivate_' . $this->basename, 'bbp_deactivation' );
397
398 // If bbPress is being deactivated, do not add any actions
399 if ( bbp_is_deactivation( $this->basename ) ) {
400 return;
401 }
402
403 // Array of bbPress core actions
404 $actions = array(
405 'setup_theme', // Setup the default theme compat
406 'setup_current_user', // Setup currently logged in user
407 'setup_engagements', // Setup user engagements strategy
408 'roles_init', // User roles init
409 'register_meta', // Register meta (forum|topic|reply|user)
410 'register_post_types', // Register post types (forum|topic|reply)
411 'register_post_statuses', // Register post statuses (closed|spam|orphan|hidden)
412 'register_taxonomies', // Register taxonomies (topic-tag)
413 'register_shortcodes', // Register shortcodes (bbp-login)
414 'register_views', // Register the views (no-replies)
415 'register_theme_packages', // Register bundled theme packages (bbp-theme-compat/bbp-themes)
416 'load_textdomain', // Load textdomain (bbpress)
417 'add_rewrite_tags', // Add rewrite tags (view|user|edit|search)
418 'add_rewrite_rules', // Generate rewrite rules (view|edit|paged|search)
419 'add_permastructs' // Add permalink structures (view|user|search)
420 );
421
422 // Add the actions
423 foreach ( $actions as $class_action ) {
424 add_action( 'bbp_' . $class_action, array( $this, $class_action ), 5 );
425 }
426
427 // All bbPress actions are setup (includes bbp-core-hooks.php)
428 do_action_ref_array( 'bbp_after_setup_actions', array( &$this ) );
429 }
430
431 /** Public Methods ********************************************************/
432
433 /**
434 * Register bundled theme packages
435 *
436 * Note that since we currently have complete control over bbp-themes and
437 * the bbp-theme-compat folders, it's fine to hardcode these here. If at a
438 * later date we need to automate this, and API will need to be built.
439 *
440 * @since 2.1.0 bbPress (r3829)
441 */
442 public function register_theme_packages() {
443
444 // Register the basic theme stack. This is really dope.
445 bbp_register_template_stack( 'get_stylesheet_directory', 6 );
446 bbp_register_template_stack( 'get_template_directory', 8 );
447
448 // Register the default theme compatibility package
449 bbp_register_theme_package( array(
450 'id' => 'default',
451 'name' => 'bbPress Default',
452 'version' => bbp_get_version(),
453 'dir' => trailingslashit( $this->themes_dir . 'default' ),
454 'url' => trailingslashit( $this->themes_url . 'default' )
455 ) );
456 }
457
458 /**
459 * Setup the default bbPress theme compatibility location.
460 *
461 * @since 2.1.0 bbPress (r3778)
462 */
463 public function setup_theme() {
464 bbp_setup_theme_compat( bbp_get_theme_package_id() );
465 }
466
467 /**
468 * Load the translation file for current language. Checks the deprecated
469 * languages folder inside the bbPress plugin first, and then the default
470 * WordPress languages folder.
471 *
472 * Note that custom translation files inside the bbPress plugin folder
473 * will be removed on bbPress updates. If you're creating custom
474 * translation files, please use the global language folder.
475 *
476 * @since 2.0.0 bbPress (r2596)
477 */
478 public function load_textdomain() {
479
480 // Define the old directory
481 $old_dir = WP_LANG_DIR . '/bbpress/';
482
483 // Old location, deprecated in 2.6.0
484 if ( is_dir( $old_dir ) ) {
485
486 // Get locale & file-name
487 $type = is_admin() ? get_user_locale() : get_locale();
488 $locale = apply_filters( 'plugin_locale', $type, $this->domain );
489 $mofile = sprintf( '%1$s-%2$s.mo', $this->domain, $locale );
490
491 // Look in global /wp-content/languages/bbpress/ folder
492 load_textdomain( $this->domain, $old_dir . $mofile );
493 }
494
495 // Look in global /wp-content/languages/plugins/
496 load_plugin_textdomain( $this->domain, false, $this->lang_base );
497 }
498
499 /**
500 * Setup the post types for forums, topics and replies
501 *
502 * @since 2.0.0 bbPress (r2597)
503 */
504 public static function register_post_types() {
505
506 /** Forums ************************************************************/
507
508 // Register Forum content type
509 register_post_type(
510 bbp_get_forum_post_type(),
511 apply_filters( 'bbp_register_forum_post_type', array(
512 'labels' => bbp_get_forum_post_type_labels(),
513 'rewrite' => bbp_get_forum_post_type_rewrite(),
514 'supports' => bbp_get_forum_post_type_supports(),
515 'description' => esc_html__( 'bbPress Forums', 'bbpress' ),
516 'capabilities' => bbp_get_forum_caps(),
517 'capability_type' => array( 'forum', 'forums' ),
518 'menu_position' => 555555,
519 'has_archive' => bbp_get_root_slug(),
520 'exclude_from_search' => true,
521 'show_in_nav_menus' => true,
522 'public' => true,
523 'show_ui' => current_user_can( 'bbp_forums_admin' ),
524 'can_export' => true,
525 'hierarchical' => true,
526 'query_var' => true,
527 'menu_icon' => '',
528 'source' => 'bbpress',
529 ) )
530 );
531
532 /** Topics ************************************************************/
533
534 // Register Topic content type
535 register_post_type(
536 bbp_get_topic_post_type(),
537 apply_filters( 'bbp_register_topic_post_type', array(
538 'labels' => bbp_get_topic_post_type_labels(),
539 'rewrite' => bbp_get_topic_post_type_rewrite(),
540 'supports' => bbp_get_topic_post_type_supports(),
541 'description' => esc_html__( 'bbPress Topics', 'bbpress' ),
542 'capabilities' => bbp_get_topic_caps(),
543 'capability_type' => array( 'topic', 'topics' ),
544 'menu_position' => 555555,
545 'has_archive' => ( 'forums' === bbp_show_on_root() ) ? bbp_get_topic_archive_slug() : false,
546 'exclude_from_search' => true,
547 'show_in_nav_menus' => false,
548 'public' => true,
549 'show_ui' => current_user_can( 'bbp_topics_admin' ),
550 'can_export' => true,
551 'hierarchical' => false,
552 'query_var' => true,
553 'menu_icon' => '',
554 'source' => 'bbpress',
555 )
556 ) );
557
558 /** Replies ***********************************************************/
559
560 // Register reply content type
561 register_post_type(
562 bbp_get_reply_post_type(),
563 apply_filters( 'bbp_register_reply_post_type', array(
564 'labels' => bbp_get_reply_post_type_labels(),
565 'rewrite' => bbp_get_reply_post_type_rewrite(),
566 'supports' => bbp_get_reply_post_type_supports(),
567 'description' => esc_html__( 'bbPress Replies', 'bbpress' ),
568 'capabilities' => bbp_get_reply_caps(),
569 'capability_type' => array( 'reply', 'replies' ),
570 'menu_position' => 555555,
571 'exclude_from_search' => true,
572 'has_archive' => false,
573 'show_in_nav_menus' => false,
574 'public' => true,
575 'show_ui' => current_user_can( 'bbp_replies_admin' ),
576 'can_export' => true,
577 'hierarchical' => false,
578 'query_var' => true,
579 'menu_icon' => '',
580 'source' => 'bbpress',
581 ) )
582 );
583 }
584
585 /**
586 * Register the post statuses used by bbPress
587 *
588 * We do some manipulation of the 'trash' status so trashed topics and
589 * replies can be viewed from within the theme.
590 *
591 * @since 2.0.0 bbPress (r2727)
592 */
593 public static function register_post_statuses() {
594
595 // Closed
596 register_post_status(
597 bbp_get_closed_status_id(),
598 apply_filters( 'bbp_register_closed_post_status', array(
599 'label' => _x( 'Closed', 'post', 'bbpress' ),
600 'label_count' => _nx_noop( 'Closed <span class="count">(%s)</span>', 'Closed <span class="count">(%s)</span>', 'post', 'bbpress' ),
601 'public' => true,
602 'show_in_admin_status_list' => true,
603 'show_in_admin_all_list' => true,
604 'source' => 'bbpress'
605 ) )
606 );
607
608 // Spam
609 register_post_status(
610 bbp_get_spam_status_id(),
611 apply_filters( 'bbp_register_spam_post_status', array(
612 'label' => _x( 'Spam', 'post', 'bbpress' ),
613 'label_count' => _nx_noop( 'Spam <span class="count">(%s)</span>', 'Spam <span class="count">(%s)</span>', 'post', 'bbpress' ),
614 'protected' => true,
615 'exclude_from_search' => true,
616 'show_in_admin_status_list' => true,
617 'show_in_admin_all_list' => false,
618 'source' => 'bbpress'
619 ) )
620 );
621
622 // Orphan
623 register_post_status(
624 bbp_get_orphan_status_id(),
625 apply_filters( 'bbp_register_orphan_post_status', array(
626 'label' => _x( 'Orphan', 'post', 'bbpress' ),
627 'label_count' => _nx_noop( 'Orphan <span class="count">(%s)</span>', 'Orphans <span class="count">(%s)</span>', 'post', 'bbpress' ),
628 'protected' => true,
629 'exclude_from_search' => true,
630 'show_in_admin_status_list' => true,
631 'show_in_admin_all_list' => false,
632 'source' => 'bbpress'
633 ) )
634 );
635
636 // Hidden
637 register_post_status(
638 bbp_get_hidden_status_id(),
639 apply_filters( 'bbp_register_hidden_post_status', array(
640 'label' => _x( 'Hidden', 'post', 'bbpress' ),
641 'label_count' => _nx_noop( 'Hidden <span class="count">(%s)</span>', 'Hidden <span class="count">(%s)</span>', 'post', 'bbpress' ),
642 'private' => true,
643 'exclude_from_search' => true,
644 'show_in_admin_status_list' => true,
645 'show_in_admin_all_list' => true,
646 'source' => 'bbpress'
647 ) )
648 );
649
650 /**
651 * Trash fix
652 *
653 * We need to remove the internal arg and change that to
654 * protected so that the users with 'view_trash' cap can view
655 * single trashed topics/replies in the front-end as wp_query
656 * doesn't allow any hack for the trashed topics to be viewed.
657 */
658 global $wp_post_statuses;
659
660 if ( ! empty( $wp_post_statuses['trash'] ) ) {
661
662 // User can view trash so set internal to false
663 if ( current_user_can( 'view_trash' ) ) {
664 $wp_post_statuses['trash']->internal = false;
665 $wp_post_statuses['trash']->protected = true;
666
667 // User cannot view trash so set internal to true
668 } else {
669 $wp_post_statuses['trash']->internal = true;
670 }
671 }
672 }
673
674 /**
675 * Register the topic tag and forum moderator taxonomies
676 *
677 * @since 2.0.0 bbPress (r2464) Added bbp_get_topic_tag_tax_id() taxonomy
678 */
679 public static function register_taxonomies() {
680
681 // Register the topic-tag taxonomy.
682 register_taxonomy(
683 bbp_get_topic_tag_tax_id(),
684 bbp_get_topic_post_type(),
685 apply_filters( 'bbp_register_topic_taxonomy', array(
686 'labels' => bbp_get_topic_tag_tax_labels(),
687 'rewrite' => bbp_get_topic_tag_tax_rewrite(),
688 'capabilities' => bbp_get_topic_tag_caps(),
689 'update_count_callback' => 'bbp_update_topic_tag_count',
690 'query_var' => true,
691 'show_tagcloud' => true,
692 'hierarchical' => false,
693 'show_in_nav_menus' => false,
694 'public' => true,
695 'show_ui' => bbp_allow_topic_tags() && current_user_can( 'bbp_topic_tags_admin' ),
696 'source' => 'bbpress'
697 )
698 ) );
699 }
700
701 /**
702 * Register the bbPress views
703 *
704 * @since 2.0.0 bbPress (r2789)
705 */
706 public static function register_views() {
707
708 // Popular topics
709 bbp_register_view(
710 'popular',
711 esc_html__( 'Most popular topics', 'bbpress' ),
712 apply_filters( 'bbp_register_view_popular', array(
713 'meta_key' => '_bbp_reply_count',
714 'meta_type' => 'NUMERIC',
715 'max_num_pages' => 1,
716 'orderby' => 'meta_value_num',
717 'show_stickies' => false
718 )
719 ) );
720
721 // Topics with no replies
722 bbp_register_view(
723 'no-replies',
724 esc_html__( 'Topics with no replies', 'bbpress' ),
725 apply_filters( 'bbp_register_view_no_replies', array(
726 'meta_key' => '_bbp_reply_count',
727 'meta_type' => 'NUMERIC',
728 'meta_value' => 1,
729 'meta_compare' => '<',
730 'orderby' => '',
731 'show_stickies' => false
732 )
733 ) );
734 }
735
736 /**
737 * Register the bbPress shortcodes
738 *
739 * @since 2.0.0 bbPress (r3031)
740 */
741 public function register_shortcodes() {
742 $this->shortcodes = new BBP_Shortcodes();
743 }
744
745 /**
746 * Register bbPress meta-data
747 *
748 * Counts added in 2.6.0 to avoid negative values
749 *
750 * @since 2.6.0 bbPress (r6300)
751 */
752 public function register_meta() {
753
754 // Define "count" meta-type array
755 $count = array(
756
757 // Counts are always integers
758 'type' => 'integer',
759
760 // Generic count description
761 'description' => esc_html__( 'bbPress Item Count', 'bbpress' ),
762
763 // Counts are single values
764 'single' => true,
765
766 // Counts should be made available in REST
767 'show_in_rest' => true,
768
769 // Never allow counts to go negative
770 'sanitize_callback' => 'bbp_number_not_negative',
771
772 // All users may update count meta data
773 'auth_callback' => '__return_true'
774 );
775
776 /** Post **************************************************************/
777
778 // Counts
779 register_meta( 'post', '_bbp_topic_count', $count );
780 register_meta( 'post', '_bbp_reply_count', $count );
781 register_meta( 'post', '_bbp_total_topic_count', $count );
782 register_meta( 'post', '_bbp_total_reply_count', $count );
783 register_meta( 'post', '_bbp_voice_count', $count );
784 register_meta( 'post', '_bbp_anonymous_reply_count', $count );
785 register_meta( 'post', '_bbp_topic_count_hidden', $count );
786 register_meta( 'post', '_bbp_reply_count_hidden', $count );
787 register_meta( 'post', '_bbp_forum_subforum_count', $count );
788
789 /* User ***************************************************************/
790
791 // Counts
792 register_meta( 'user', '_bbp_topic_count', $count );
793 register_meta( 'user', '_bbp_reply_count', $count );
794
795 // Activity
796 register_meta( 'user', '_bbp_last_posted', array(
797 'type' => 'integer',
798 'description' => esc_html__( 'bbPress User Activity', 'bbpress' ),
799 'single' => true,
800 'show_in_rest' => true,
801 'sanitize_callback' => 'bbp_number_not_negative',
802 'auth_callback' => '__return_true'
803 ) );
804 }
805
806 /**
807 * Setup the currently logged-in user
808 *
809 * @since 2.0.0 bbPress (r2697)
810 */
811 public function setup_current_user() {
812 $this->current_user = wp_get_current_user();
813 }
814
815 /**
816 * Setup the user engagements strategy
817 *
818 * @since 2.6.0 bbPress (r6875)
819 */
820 public function setup_engagements() {
821
822 // Setup the class name
823 $strategy = ucwords( bbp_engagements_strategy() );
824 $class_name = "BBP_User_Engagements_{$strategy}";
825
826 // Setup the engagements interface
827 $this->engagements = new $class_name();
828 }
829
830 /**
831 * Initialize forum-specific roles
832 *
833 * @since 2.6.0
834 */
835 public function roles_init() {
836
837 // Get role IDs
838 $keymaster = bbp_get_keymaster_role();
839 $moderator = bbp_get_moderator_role();
840 $participant = bbp_get_participant_role();
841 $spectator = bbp_get_spectator_role();
842 $blocked = bbp_get_blocked_role();
843
844 // Build the roles into one useful array
845 $this->roles[ $keymaster ] = new WP_Role( 'Keymaster', bbp_get_caps_for_role( $keymaster ) );
846 $this->roles[ $moderator ] = new WP_Role( 'Moderator', bbp_get_caps_for_role( $moderator ) );
847 $this->roles[ $participant ] = new WP_Role( 'Participant', bbp_get_caps_for_role( $participant ) );
848 $this->roles[ $spectator ] = new WP_Role( 'Spectator', bbp_get_caps_for_role( $spectator ) );
849 $this->roles[ $blocked ] = new WP_Role( 'Blocked', bbp_get_caps_for_role( $blocked ) );
850 }
851
852 /** Custom Rewrite Rules **************************************************/
853
854 /**
855 * Add the bbPress-specific rewrite tags
856 *
857 * @since 2.0.0 bbPress (r2753)
858 */
859 public static function add_rewrite_tags() {
860 add_rewrite_tag( '%' . bbp_get_view_rewrite_id() . '%', '([^/]+)' ); // View Page tag
861 add_rewrite_tag( '%' . bbp_get_edit_rewrite_id() . '%', '([1]{1,})' ); // Edit Page tag
862 add_rewrite_tag( '%' . bbp_get_search_rewrite_id() . '%', '([^/]+)' ); // Search Results tag
863 add_rewrite_tag( '%' . bbp_get_user_rewrite_id() . '%', '([^/]+)' ); // User Profile tag
864 add_rewrite_tag( '%' . bbp_get_user_favorites_rewrite_id() . '%', '([1]{1,})' ); // User Favorites tag
865 add_rewrite_tag( '%' . bbp_get_user_subscriptions_rewrite_id() . '%', '([1]{1,})' ); // User Subscriptions tag
866 add_rewrite_tag( '%' . bbp_get_user_engagements_rewrite_id() . '%', '([1]{1,})' ); // User Engagements tag
867 add_rewrite_tag( '%' . bbp_get_user_topics_rewrite_id() . '%', '([1]{1,})' ); // User Topics Tag
868 add_rewrite_tag( '%' . bbp_get_user_replies_rewrite_id() . '%', '([1]{1,})' ); // User Replies Tag
869 }
870
871 /**
872 * Add bbPress-specific rewrite rules for uri's that are not
873 * setup for us by way of custom post types or taxonomies. This includes:
874 * - Front-end editing
875 * - Topic views
876 * - User profiles
877 *
878 * @since 2.0.0 bbPress (r2688)
879 *
880 * @todo Extract into an API
881 */
882 public static function add_rewrite_rules() {
883
884 /** Setup *************************************************************/
885
886 // Add rules to top or bottom?
887 $priority = 'top';
888
889 // Single Slugs
890 $forum_slug = bbp_get_forum_slug();
891 $topic_slug = bbp_get_topic_slug();
892 $reply_slug = bbp_get_reply_slug();
893 $ttag_slug = bbp_get_topic_tag_tax_slug();
894
895 // Archive Slugs
896 $user_slug = bbp_get_user_slug();
897 $view_slug = bbp_get_view_slug();
898 $search_slug = bbp_get_search_slug();
899 $topic_archive_slug = bbp_get_topic_archive_slug();
900 $reply_archive_slug = bbp_get_reply_archive_slug();
901
902 // Tertiary Slugs
903 $feed_slug = 'feed';
904 $edit_slug = bbp_get_edit_slug();
905 $paged_slug = bbp_get_paged_slug();
906 $user_favs_slug = bbp_get_user_favorites_slug();
907 $user_subs_slug = bbp_get_user_subscriptions_slug();
908 $user_engs_slug = bbp_get_user_engagements_slug();
909
910 // Unique rewrite ID's
911 $feed_id = 'feed';
912 $edit_id = bbp_get_edit_rewrite_id();
913 $view_id = bbp_get_view_rewrite_id();
914 $paged_id = bbp_get_paged_rewrite_id();
915 $search_id = bbp_get_search_rewrite_id();
916 $user_id = bbp_get_user_rewrite_id();
917 $user_favs_id = bbp_get_user_favorites_rewrite_id();
918 $user_subs_id = bbp_get_user_subscriptions_rewrite_id();
919 $user_tops_id = bbp_get_user_topics_rewrite_id();
920 $user_reps_id = bbp_get_user_replies_rewrite_id();
921 $user_engs_id = bbp_get_user_engagements_rewrite_id();
922
923 // Rewrite rule matches used repeatedly below
924 $root_rule = '/([^/]+)/?$';
925 $feed_rule = '/([^/]+)/' . $feed_slug . '/?$';
926 $edit_rule = '/([^/]+)/' . $edit_slug . '/?$';
927 $paged_rule = '/([^/]+)/' . $paged_slug . '/?([0-9]{1,})/?$';
928
929 // Search rules (without slug check)
930 $search_root_rule = '/?$';
931 $search_paged_rule = '/' . $paged_slug . '/?([0-9]{1,})/?$';
932
933 /** Add ***************************************************************/
934
935 // User profile rules
936 $tops_rule = '/([^/]+)/' . $topic_archive_slug . '/?$';
937 $reps_rule = '/([^/]+)/' . $reply_archive_slug . '/?$';
938 $favs_rule = '/([^/]+)/' . $user_favs_slug . '/?$';
939 $subs_rule = '/([^/]+)/' . $user_subs_slug . '/?$';
940 $engs_rule = '/([^/]+)/' . $user_engs_slug . '/?$';
941 $tops_paged_rule = '/([^/]+)/' . $topic_archive_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
942 $reps_paged_rule = '/([^/]+)/' . $reply_archive_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
943 $favs_paged_rule = '/([^/]+)/' . $user_favs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
944 $subs_paged_rule = '/([^/]+)/' . $user_subs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
945 $engs_paged_rule = '/([^/]+)/' . $user_engs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
946
947 // Edit Forum|Topic|Reply|Topic-tag
948 add_rewrite_rule( $forum_slug . $edit_rule, 'index.php?' . bbp_get_forum_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
949 add_rewrite_rule( $topic_slug . $edit_rule, 'index.php?' . bbp_get_topic_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
950 add_rewrite_rule( $reply_slug . $edit_rule, 'index.php?' . bbp_get_reply_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
951 add_rewrite_rule( $ttag_slug . $edit_rule, 'index.php?' . bbp_get_topic_tag_tax_id() . '=$matches[1]&' . $edit_id . '=1', $priority );
952
953 // User Pagination|Edit|View
954 add_rewrite_rule( $user_slug . $tops_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_tops_id . '=1&' . $paged_id . '=$matches[2]', $priority );
955 add_rewrite_rule( $user_slug . $reps_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_reps_id . '=1&' . $paged_id . '=$matches[2]', $priority );
956 add_rewrite_rule( $user_slug . $favs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_favs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
957 add_rewrite_rule( $user_slug . $subs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_subs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
958 add_rewrite_rule( $user_slug . $engs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_engs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
959 add_rewrite_rule( $user_slug . $tops_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_tops_id . '=1', $priority );
960 add_rewrite_rule( $user_slug . $reps_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_reps_id . '=1', $priority );
961 add_rewrite_rule( $user_slug . $favs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_favs_id . '=1', $priority );
962 add_rewrite_rule( $user_slug . $subs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_subs_id . '=1', $priority );
963 add_rewrite_rule( $user_slug . $engs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_engs_id . '=1', $priority );
964 add_rewrite_rule( $user_slug . $edit_rule, 'index.php?' . $user_id . '=$matches[1]&' . $edit_id . '=1', $priority );
965 add_rewrite_rule( $user_slug . $root_rule, 'index.php?' . $user_id . '=$matches[1]', $priority );
966
967 // Topic-View Pagination|Feed|View
968 add_rewrite_rule( $view_slug . $paged_rule, 'index.php?' . $view_id . '=$matches[1]&' . $paged_id . '=$matches[2]', $priority );
969 add_rewrite_rule( $view_slug . $feed_rule, 'index.php?' . $view_id . '=$matches[1]&' . $feed_id . '=$matches[2]', $priority );
970 add_rewrite_rule( $view_slug . $root_rule, 'index.php?' . $view_id . '=$matches[1]', $priority );
971
972 // Search All
973 add_rewrite_rule( $search_slug . $search_paged_rule, 'index.php?' . $paged_id .'=$matches[1]', $priority );
974 add_rewrite_rule( $search_slug . $search_root_rule, 'index.php?' . $search_id, $priority );
975 }
976
977 /**
978 * Add permalink structures for new archive-style destinations.
979 *
980 * - Users
981 * - Topic Views
982 * - Search
983 *
984 * @since 2.4.0 bbPress (r4930)
985 */
986 public static function add_permastructs() {
987
988 // Get unique ID's
989 $user_id = bbp_get_user_rewrite_id();
990 $view_id = bbp_get_view_rewrite_id();
991 $search_id = bbp_get_search_rewrite_id();
992
993 // Get root slugs
994 $user_slug = bbp_get_user_slug();
995 $view_slug = bbp_get_view_slug();
996 $search_slug = bbp_get_search_slug();
997
998 // User Permastruct
999 add_permastruct( $user_id, $user_slug . '/%' . $user_id . '%', array(
1000 'with_front' => false,
1001 'ep_mask' => EP_NONE,
1002 'paged' => false,
1003 'feed' => false,
1004 'forcomments' => false,
1005 'walk_dirs' => true,
1006 'endpoints' => false,
1007 ) );
1008
1009 // Topic View Permastruct
1010 add_permastruct( $view_id, $view_slug . '/%' . $view_id . '%', array(
1011 'with_front' => false,
1012 'ep_mask' => EP_NONE,
1013 'paged' => false,
1014 'feed' => false,
1015 'forcomments' => false,
1016 'walk_dirs' => true,
1017 'endpoints' => false,
1018 ) );
1019
1020 // Search Permastruct
1021 add_permastruct( $search_id, $search_slug . '/%' . $search_id . '%', array(
1022 'with_front' => false,
1023 'ep_mask' => EP_NONE,
1024 'paged' => true,
1025 'feed' => false,
1026 'forcomments' => false,
1027 'walk_dirs' => true,
1028 'endpoints' => false,
1029 ) );
1030 }
1031 }
1032
1033 /**
1034 * The main function responsible for returning the one true bbPress Instance
1035 * to functions everywhere.
1036 *
1037 * Use this function like you would a global variable, except without needing
1038 * to declare the global.
1039 *
1040 * Example: <?php $bbp = bbpress(); ?>
1041 *
1042 * @since 2.0.0 bbPress (r2464)
1043 *
1044 * @return bbPress The one true bbPress Instance
1045 */
1046 function bbpress() {
1047 return bbPress::instance();
1048 }
1049
1050 /**
1051 * Hook bbPress early onto the 'plugins_loaded' action.
1052 *
1053 * This gives all other plugins the chance to load before bbPress, to get their
1054 * actions, filters, and overrides setup without bbPress being in the way.
1055 */
1056 if ( defined( 'BBPRESS_LATE_LOAD' ) ) {
1057 add_action( 'plugins_loaded', 'bbpress', (int) BBPRESS_LATE_LOAD );
1058
1059 // "And now here's something we hope you'll really like!"
1060 } else {
1061 bbpress();
1062 }
1063
1064 endif; // class_exists check
1065