PluginProbe
bbPress / 2.6.15
bbPress v2.6.15
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.15, at bbpress.php

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