PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / trunk
Forumax – AI Powered Advanced Community Forum Plugin vtrunk
2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 2.0.0 2.1.0 All 29 releases
bbp-core / lib / bbpress / bbpress.php

bbpress.php in Forumax – AI Powered Advanced Community Forum Plugin trunk, at lib/bbpress/bbpress.php

1,073 lines 38.4 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 7338 2025-07-02 15:36:03Z 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: 6.9
27 * Version: 2.6.14
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.14';
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 forumax-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 'show_in_rest' => true,
532 'rest_base' => 'forums',
533 'rest_controller_class' => 'WP_REST_Posts_Controller',
534 ) )
535 );
536
537 /** Topics ************************************************************/
538
539 // Register Topic content type
540 register_post_type(
541 bbp_get_topic_post_type(),
542 apply_filters( 'bbp_register_topic_post_type', array(
543 'labels' => bbp_get_topic_post_type_labels(),
544 'rewrite' => bbp_get_topic_post_type_rewrite(),
545 'supports' => bbp_get_topic_post_type_supports(),
546 'description' => esc_html__( 'bbPress Topics', 'bbpress' ),
547 'capabilities' => bbp_get_topic_caps(),
548 'capability_type' => array( 'topic', 'topics' ),
549 'menu_position' => 555555,
550 'has_archive' => ( 'forums' === bbp_show_on_root() ) ? bbp_get_topic_archive_slug() : false,
551 'exclude_from_search' => true,
552 'show_in_nav_menus' => false,
553 'public' => true,
554 'show_ui' => current_user_can( 'bbp_topics_admin' ),
555 'can_export' => true,
556 'hierarchical' => false,
557 'query_var' => true,
558 'menu_icon' => '',
559 'source' => 'bbpress',
560 'show_in_rest' => true,
561 'rest_base' => 'topics',
562 'rest_controller_class' => 'WP_REST_Posts_Controller',
563 )
564 ) );
565
566 /** Replies ***********************************************************/
567
568 // Register reply content type
569 register_post_type(
570 bbp_get_reply_post_type(),
571 apply_filters( 'bbp_register_reply_post_type', array(
572 'labels' => bbp_get_reply_post_type_labels(),
573 'rewrite' => bbp_get_reply_post_type_rewrite(),
574 'supports' => bbp_get_reply_post_type_supports(),
575 'description' => esc_html__( 'bbPress Replies', 'bbpress' ),
576 'capabilities' => bbp_get_reply_caps(),
577 'capability_type' => array( 'reply', 'replies' ),
578 'menu_position' => 555555,
579 'exclude_from_search' => true,
580 'has_archive' => false,
581 'show_in_nav_menus' => false,
582 'public' => true,
583 'show_ui' => current_user_can( 'bbp_replies_admin' ),
584 'can_export' => true,
585 'hierarchical' => false,
586 'query_var' => true,
587 'menu_icon' => '',
588 'source' => 'bbpress',
589 ) )
590 );
591 }
592
593 /**
594 * Register the post statuses used by bbPress
595 *
596 * We do some manipulation of the 'trash' status so trashed topics and
597 * replies can be viewed from within the theme.
598 *
599 * @since 2.0.0 bbPress (r2727)
600 */
601 public static function register_post_statuses() {
602
603 // Closed
604 register_post_status(
605 bbp_get_closed_status_id(),
606 apply_filters( 'bbp_register_closed_post_status', array(
607 'label' => _x( 'Closed', 'post', 'bbpress' ),
608 'label_count' => _nx_noop( 'Closed <span class="count">(%s)</span>', 'Closed <span class="count">(%s)</span>', 'post', 'bbpress' ),
609 'public' => true,
610 'show_in_admin_status_list' => true,
611 'show_in_admin_all_list' => true,
612 'source' => 'bbpress'
613 ) )
614 );
615
616 // Spam
617 register_post_status(
618 bbp_get_spam_status_id(),
619 apply_filters( 'bbp_register_spam_post_status', array(
620 'label' => _x( 'Spam', 'post', 'bbpress' ),
621 'label_count' => _nx_noop( 'Spam <span class="count">(%s)</span>', 'Spam <span class="count">(%s)</span>', 'post', 'bbpress' ),
622 'protected' => true,
623 'exclude_from_search' => true,
624 'show_in_admin_status_list' => true,
625 'show_in_admin_all_list' => false,
626 'source' => 'bbpress'
627 ) )
628 );
629
630 // Orphan
631 register_post_status(
632 bbp_get_orphan_status_id(),
633 apply_filters( 'bbp_register_orphan_post_status', array(
634 'label' => _x( 'Orphan', 'post', 'bbpress' ),
635 'label_count' => _nx_noop( 'Orphan <span class="count">(%s)</span>', 'Orphans <span class="count">(%s)</span>', 'post', 'bbpress' ),
636 'protected' => true,
637 'exclude_from_search' => true,
638 'show_in_admin_status_list' => true,
639 'show_in_admin_all_list' => false,
640 'source' => 'bbpress'
641 ) )
642 );
643
644 // Hidden
645 register_post_status(
646 bbp_get_hidden_status_id(),
647 apply_filters( 'bbp_register_hidden_post_status', array(
648 'label' => _x( 'Hidden', 'post', 'bbpress' ),
649 'label_count' => _nx_noop( 'Hidden <span class="count">(%s)</span>', 'Hidden <span class="count">(%s)</span>', 'post', 'bbpress' ),
650 'private' => true,
651 'exclude_from_search' => true,
652 'show_in_admin_status_list' => true,
653 'show_in_admin_all_list' => true,
654 'source' => 'bbpress'
655 ) )
656 );
657
658 /**
659 * Trash fix
660 *
661 * We need to remove the internal arg and change that to
662 * protected so that the users with 'view_trash' cap can view
663 * single trashed topics/replies in the front-end as wp_query
664 * doesn't allow any hack for the trashed topics to be viewed.
665 */
666 global $wp_post_statuses;
667
668 if ( ! empty( $wp_post_statuses['trash'] ) ) {
669
670 // User can view trash so set internal to false
671 if ( current_user_can( 'view_trash' ) ) {
672 $wp_post_statuses['trash']->internal = false;
673 $wp_post_statuses['trash']->protected = true;
674
675 // User cannot view trash so set internal to true
676 } else {
677 $wp_post_statuses['trash']->internal = true;
678 }
679 }
680 }
681
682 /**
683 * Register the topic tag and forum moderator taxonomies
684 *
685 * @since 2.0.0 bbPress (r2464) Added bbp_get_topic_tag_tax_id() taxonomy
686 */
687 public static function register_taxonomies() {
688
689 // Register the topic-tag taxonomy.
690 register_taxonomy(
691 bbp_get_topic_tag_tax_id(),
692 bbp_get_topic_post_type(),
693 apply_filters( 'bbp_register_topic_taxonomy', array(
694 'labels' => bbp_get_topic_tag_tax_labels(),
695 'rewrite' => bbp_get_topic_tag_tax_rewrite(),
696 'capabilities' => bbp_get_topic_tag_caps(),
697 'update_count_callback' => 'bbp_update_topic_tag_count',
698 'query_var' => true,
699 'show_tagcloud' => true,
700 'hierarchical' => false,
701 'show_in_nav_menus' => false,
702 'public' => true,
703 'show_ui' => bbp_allow_topic_tags() && current_user_can( 'bbp_topic_tags_admin' ),
704 'source' => 'bbpress'
705 )
706 ) );
707 }
708
709 /**
710 * Register the bbPress views
711 *
712 * @since 2.0.0 bbPress (r2789)
713 */
714 public static function register_views() {
715
716 // Popular topics
717 bbp_register_view(
718 'popular',
719 esc_html__( 'Most popular topics', 'bbpress' ),
720 apply_filters( 'bbp_register_view_popular', array(
721 'meta_key' => '_bbp_reply_count',
722 'meta_type' => 'NUMERIC',
723 'max_num_pages' => 1,
724 'orderby' => 'meta_value_num',
725 'show_stickies' => false
726 )
727 ) );
728
729 // Topics with no replies
730 bbp_register_view(
731 'no-replies',
732 esc_html__( 'Topics with no replies', 'bbpress' ),
733 apply_filters( 'bbp_register_view_no_replies', array(
734 'meta_key' => '_bbp_reply_count',
735 'meta_type' => 'NUMERIC',
736 'meta_value' => 1,
737 'meta_compare' => '<',
738 'orderby' => '',
739 'show_stickies' => false
740 )
741 ) );
742 }
743
744 /**
745 * Register the bbPress shortcodes
746 *
747 * @since 2.0.0 bbPress (r3031)
748 */
749 public function register_shortcodes() {
750 $this->shortcodes = new BBP_Shortcodes();
751 }
752
753 /**
754 * Register bbPress meta-data
755 *
756 * Counts added in 2.6.0 to avoid negative values
757 *
758 * @since 2.6.0 bbPress (r6300)
759 */
760 public function register_meta() {
761
762 // Define "count" meta-type array
763 $count = array(
764
765 // Counts are always integers
766 'type' => 'integer',
767
768 // Generic count description
769 'description' => esc_html__( 'bbPress Item Count', 'bbpress' ),
770
771 // Counts are single values
772 'single' => true,
773
774 // Counts should be made available in REST
775 'show_in_rest' => true,
776
777 // Never allow counts to go negative
778 'sanitize_callback' => 'bbp_number_not_negative',
779
780 // All users may update count meta data
781 'auth_callback' => '__return_true'
782 );
783
784 /** Post **************************************************************/
785
786 // Counts
787 register_meta( 'post', '_bbp_topic_count', $count );
788 register_meta( 'post', '_bbp_reply_count', $count );
789 register_meta( 'post', '_bbp_total_topic_count', $count );
790 register_meta( 'post', '_bbp_total_reply_count', $count );
791 register_meta( 'post', '_bbp_voice_count', $count );
792 register_meta( 'post', '_bbp_anonymous_reply_count', $count );
793 register_meta( 'post', '_bbp_topic_count_hidden', $count );
794 register_meta( 'post', '_bbp_reply_count_hidden', $count );
795 register_meta( 'post', '_bbp_forum_subforum_count', $count );
796
797 /* User ***************************************************************/
798
799 // Counts
800 register_meta( 'user', '_bbp_topic_count', $count );
801 register_meta( 'user', '_bbp_reply_count', $count );
802
803 // Activity
804 register_meta( 'user', '_bbp_last_posted', array(
805 'type' => 'integer',
806 'description' => esc_html__( 'bbPress User Activity', 'bbpress' ),
807 'single' => true,
808 'show_in_rest' => true,
809 'sanitize_callback' => 'bbp_number_not_negative',
810 'auth_callback' => '__return_true'
811 ) );
812 }
813
814 /**
815 * Setup the currently logged-in user
816 *
817 * @since 2.0.0 bbPress (r2697)
818 */
819 public function setup_current_user() {
820 $this->current_user = wp_get_current_user();
821 }
822
823 /**
824 * Setup the user engagements strategy
825 *
826 * @since 2.6.0 bbPress (r6875)
827 */
828 public function setup_engagements() {
829
830 // Setup the class name
831 $strategy = ucwords( bbp_engagements_strategy() );
832 $class_name = "BBP_User_Engagements_{$strategy}";
833
834 // Setup the engagements interface
835 $this->engagements = new $class_name();
836 }
837
838 /**
839 * Initialize forum-specific roles
840 *
841 * @since 2.6.0
842 */
843 public function roles_init() {
844
845 // Get role IDs
846 $keymaster = bbp_get_keymaster_role();
847 $moderator = bbp_get_moderator_role();
848 $participant = bbp_get_participant_role();
849 $spectator = bbp_get_spectator_role();
850 $blocked = bbp_get_blocked_role();
851
852 // Build the roles into one useful array
853 $this->roles[ $keymaster ] = new WP_Role( 'Keymaster', bbp_get_caps_for_role( $keymaster ) );
854 $this->roles[ $moderator ] = new WP_Role( 'Moderator', bbp_get_caps_for_role( $moderator ) );
855 $this->roles[ $participant ] = new WP_Role( 'Participant', bbp_get_caps_for_role( $participant ) );
856 $this->roles[ $spectator ] = new WP_Role( 'Spectator', bbp_get_caps_for_role( $spectator ) );
857 $this->roles[ $blocked ] = new WP_Role( 'Blocked', bbp_get_caps_for_role( $blocked ) );
858 }
859
860 /** Custom Rewrite Rules **************************************************/
861
862 /**
863 * Add the bbPress-specific rewrite tags
864 *
865 * @since 2.0.0 bbPress (r2753)
866 */
867 public static function add_rewrite_tags() {
868 add_rewrite_tag( '%' . bbp_get_view_rewrite_id() . '%', '([^/]+)' ); // View Page tag
869 add_rewrite_tag( '%' . bbp_get_edit_rewrite_id() . '%', '([1]{1,})' ); // Edit Page tag
870 add_rewrite_tag( '%' . bbp_get_search_rewrite_id() . '%', '([^/]+)' ); // Search Results tag
871 add_rewrite_tag( '%' . bbp_get_user_rewrite_id() . '%', '([^/]+)' ); // User Profile tag
872 add_rewrite_tag( '%' . bbp_get_user_favorites_rewrite_id() . '%', '([1]{1,})' ); // User Favorites tag
873 add_rewrite_tag( '%' . bbp_get_user_subscriptions_rewrite_id() . '%', '([1]{1,})' ); // User Subscriptions tag
874 add_rewrite_tag( '%' . bbp_get_user_engagements_rewrite_id() . '%', '([1]{1,})' ); // User Engagements tag
875 add_rewrite_tag( '%' . bbp_get_user_topics_rewrite_id() . '%', '([1]{1,})' ); // User Topics Tag
876 add_rewrite_tag( '%' . bbp_get_user_replies_rewrite_id() . '%', '([1]{1,})' ); // User Replies Tag
877 }
878
879 /**
880 * Add bbPress-specific rewrite rules for uri's that are not
881 * setup for us by way of custom post types or taxonomies. This includes:
882 * - Front-end editing
883 * - Topic views
884 * - User profiles
885 *
886 * @since 2.0.0 bbPress (r2688)
887 *
888 * @todo Extract into an API
889 */
890 public static function add_rewrite_rules() {
891
892 /** Setup *************************************************************/
893
894 // Add rules to top or bottom?
895 $priority = 'top';
896
897 // Single Slugs
898 $forum_slug = bbp_get_forum_slug();
899 $topic_slug = bbp_get_topic_slug();
900 $reply_slug = bbp_get_reply_slug();
901 $ttag_slug = bbp_get_topic_tag_tax_slug();
902
903 // Archive Slugs
904 $user_slug = bbp_get_user_slug();
905 $view_slug = bbp_get_view_slug();
906 $search_slug = bbp_get_search_slug();
907 $topic_archive_slug = bbp_get_topic_archive_slug();
908 $reply_archive_slug = bbp_get_reply_archive_slug();
909
910 // Tertiary Slugs
911 $feed_slug = 'feed';
912 $edit_slug = bbp_get_edit_slug();
913 $paged_slug = bbp_get_paged_slug();
914 $user_favs_slug = bbp_get_user_favorites_slug();
915 $user_subs_slug = bbp_get_user_subscriptions_slug();
916 $user_engs_slug = bbp_get_user_engagements_slug();
917
918 // Unique rewrite ID's
919 $feed_id = 'feed';
920 $edit_id = bbp_get_edit_rewrite_id();
921 $view_id = bbp_get_view_rewrite_id();
922 $paged_id = bbp_get_paged_rewrite_id();
923 $search_id = bbp_get_search_rewrite_id();
924 $user_id = bbp_get_user_rewrite_id();
925 $user_favs_id = bbp_get_user_favorites_rewrite_id();
926 $user_subs_id = bbp_get_user_subscriptions_rewrite_id();
927 $user_tops_id = bbp_get_user_topics_rewrite_id();
928 $user_reps_id = bbp_get_user_replies_rewrite_id();
929 $user_engs_id = bbp_get_user_engagements_rewrite_id();
930
931 // Rewrite rule matches used repeatedly below
932 $root_rule = '/([^/]+)/?$';
933 $feed_rule = '/([^/]+)/' . $feed_slug . '/?$';
934 $edit_rule = '/([^/]+)/' . $edit_slug . '/?$';
935 $paged_rule = '/([^/]+)/' . $paged_slug . '/?([0-9]{1,})/?$';
936
937 // Search rules (without slug check)
938 $search_root_rule = '/?$';
939 $search_paged_rule = '/' . $paged_slug . '/?([0-9]{1,})/?$';
940
941 /** Add ***************************************************************/
942
943 // User profile rules
944 $tops_rule = '/([^/]+)/' . $topic_archive_slug . '/?$';
945 $reps_rule = '/([^/]+)/' . $reply_archive_slug . '/?$';
946 $favs_rule = '/([^/]+)/' . $user_favs_slug . '/?$';
947 $subs_rule = '/([^/]+)/' . $user_subs_slug . '/?$';
948 $engs_rule = '/([^/]+)/' . $user_engs_slug . '/?$';
949 $tops_paged_rule = '/([^/]+)/' . $topic_archive_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
950 $reps_paged_rule = '/([^/]+)/' . $reply_archive_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
951 $favs_paged_rule = '/([^/]+)/' . $user_favs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
952 $subs_paged_rule = '/([^/]+)/' . $user_subs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
953 $engs_paged_rule = '/([^/]+)/' . $user_engs_slug . '/' . $paged_slug . '/?([0-9]{1,})/?$';
954
955 // Edit Forum|Topic|Reply|Topic-tag
956 add_rewrite_rule( $forum_slug . $edit_rule, 'index.php?' . bbp_get_forum_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
957 add_rewrite_rule( $topic_slug . $edit_rule, 'index.php?' . bbp_get_topic_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
958 add_rewrite_rule( $reply_slug . $edit_rule, 'index.php?' . bbp_get_reply_post_type() . '=$matches[1]&' . $edit_id . '=1', $priority );
959 add_rewrite_rule( $ttag_slug . $edit_rule, 'index.php?' . bbp_get_topic_tag_tax_id() . '=$matches[1]&' . $edit_id . '=1', $priority );
960
961 // User Pagination|Edit|View
962 add_rewrite_rule( $user_slug . $tops_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_tops_id . '=1&' . $paged_id . '=$matches[2]', $priority );
963 add_rewrite_rule( $user_slug . $reps_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_reps_id . '=1&' . $paged_id . '=$matches[2]', $priority );
964 add_rewrite_rule( $user_slug . $favs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_favs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
965 add_rewrite_rule( $user_slug . $subs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_subs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
966 add_rewrite_rule( $user_slug . $engs_paged_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_engs_id . '=1&' . $paged_id . '=$matches[2]', $priority );
967 add_rewrite_rule( $user_slug . $tops_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_tops_id . '=1', $priority );
968 add_rewrite_rule( $user_slug . $reps_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_reps_id . '=1', $priority );
969 add_rewrite_rule( $user_slug . $favs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_favs_id . '=1', $priority );
970 add_rewrite_rule( $user_slug . $subs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_subs_id . '=1', $priority );
971 add_rewrite_rule( $user_slug . $engs_rule, 'index.php?' . $user_id . '=$matches[1]&' . $user_engs_id . '=1', $priority );
972 add_rewrite_rule( $user_slug . $edit_rule, 'index.php?' . $user_id . '=$matches[1]&' . $edit_id . '=1', $priority );
973 add_rewrite_rule( $user_slug . $root_rule, 'index.php?' . $user_id . '=$matches[1]', $priority );
974
975 // Topic-View Pagination|Feed|View
976 add_rewrite_rule( $view_slug . $paged_rule, 'index.php?' . $view_id . '=$matches[1]&' . $paged_id . '=$matches[2]', $priority );
977 add_rewrite_rule( $view_slug . $feed_rule, 'index.php?' . $view_id . '=$matches[1]&' . $feed_id . '=$matches[2]', $priority );
978 add_rewrite_rule( $view_slug . $root_rule, 'index.php?' . $view_id . '=$matches[1]', $priority );
979
980 // Search All
981 add_rewrite_rule( $search_slug . $search_paged_rule, 'index.php?' . $paged_id .'=$matches[1]', $priority );
982 add_rewrite_rule( $search_slug . $search_root_rule, 'index.php?' . $search_id, $priority );
983 }
984
985 /**
986 * Add permalink structures for new archive-style destinations.
987 *
988 * - Users
989 * - Topic Views
990 * - Search
991 *
992 * @since 2.4.0 bbPress (r4930)
993 */
994 public static function add_permastructs() {
995
996 // Get unique ID's
997 $user_id = bbp_get_user_rewrite_id();
998 $view_id = bbp_get_view_rewrite_id();
999 $search_id = bbp_get_search_rewrite_id();
1000
1001 // Get root slugs
1002 $user_slug = bbp_get_user_slug();
1003 $view_slug = bbp_get_view_slug();
1004 $search_slug = bbp_get_search_slug();
1005
1006 // User Permastruct
1007 add_permastruct( $user_id, $user_slug . '/%' . $user_id . '%', array(
1008 'with_front' => false,
1009 'ep_mask' => EP_NONE,
1010 'paged' => false,
1011 'feed' => false,
1012 'forcomments' => false,
1013 'walk_dirs' => true,
1014 'endpoints' => false,
1015 ) );
1016
1017 // Topic View Permastruct
1018 add_permastruct( $view_id, $view_slug . '/%' . $view_id . '%', array(
1019 'with_front' => false,
1020 'ep_mask' => EP_NONE,
1021 'paged' => false,
1022 'feed' => false,
1023 'forcomments' => false,
1024 'walk_dirs' => true,
1025 'endpoints' => false,
1026 ) );
1027
1028 // Search Permastruct
1029 add_permastruct( $search_id, $search_slug . '/%' . $search_id . '%', array(
1030 'with_front' => false,
1031 'ep_mask' => EP_NONE,
1032 'paged' => true,
1033 'feed' => false,
1034 'forcomments' => false,
1035 'walk_dirs' => true,
1036 'endpoints' => false,
1037 ) );
1038 }
1039 }
1040
1041 /**
1042 * The main function responsible for returning the one true bbPress Instance
1043 * to functions everywhere.
1044 *
1045 * Use this function like you would a global variable, except without needing
1046 * to declare the global.
1047 *
1048 * Example: <?php $bbp = bbpress(); ?>
1049 *
1050 * @since 2.0.0 bbPress (r2464)
1051 *
1052 * @return bbPress The one true bbPress Instance
1053 */
1054 function bbpress() {
1055 return bbPress::instance();
1056 }
1057
1058 /**
1059 * Hook bbPress early onto the 'plugins_loaded' action.
1060 *
1061 * This gives all other plugins the chance to load before bbPress, to get their
1062 * actions, filters, and overrides setup without bbPress being in the way.
1063 */
1064 if ( defined( 'BBPRESS_LATE_LOAD' ) ) {
1065 add_action( 'plugins_loaded', 'bbpress', (int) BBPRESS_LATE_LOAD );
1066
1067 // "And now here's something we hope you'll really like!"
1068 } else {
1069 bbpress();
1070 }
1071
1072 endif; // class_exists check
1073