Plugin Directory

source: bbpress/trunk/bbpress.php

Last change on this file was 3109477, checked in by johnjamesjacoby, 4 weeks ago

bbPress: merge improvements from 2.6 dev branch into trunk.

File size: 38.2 KB
Line 
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 7268 2024-06-28 22:02:43Z 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.5
27 * Version:           2.7.0-alpha-2
28 */
29
30// Exit if accessed directly
31defined( 'ABSPATH' ) || exit;
32
33if ( ! class_exists( 'bbPress' ) ) :
34/**
35 * Main bbPress Class
36 *
37 * "Word hard. Stay bumble."
38 *
39 * @since 2.0.0 bbPress (r2464)
40 */
41final 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.7.0-alpha-2';
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 */
1048function 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 */
1058if ( 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
1066endif; // class_exists check
Note: See TracBrowser for help on using the repository browser.