[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Functions of BuddyPress's "Nouveau" template pack. 4 * 5 * @since 3.0.0 6 * @version 3.1.0 7 * 8 * @buddypress-template-pack { 9 * Template Pack ID: nouveau 10 * Template Pack Name: BP Nouveau 11 * Version: 1.0.0 12 * WP required version: 4.5.0 13 * BP required version: 3.0.0 14 * Description: A new template pack for BuddyPress! 15 * Text Domain: bp-nouveau 16 * Domain Path: /languages/ 17 * Author: The BuddyPress community 18 * Template Pack Supports: activity, blogs, friends, groups, messages, notifications, settings, xprofile 19 * }} 20 */ 21 22 // Exit if accessed directly. 23 defined( 'ABSPATH' ) || exit; 24 25 /** Theme Setup ***************************************************************/ 26 27 /** 28 * Loads BuddyPress Nouveau Template pack functionality. 29 * 30 * See @link BP_Theme_Compat() for more. 31 * 32 * @since 3.0.0 33 */ 34 class BP_Nouveau extends BP_Theme_Compat { 35 /** 36 * Instance of this class. 37 */ 38 protected static $instance = null; 39 40 /** 41 * Return the instance of this class. 42 * 43 * @since 3.0.0 44 */ 45 public static function get_instance() { 46 if ( null === self::$instance ) { 47 self::$instance = new self; 48 } 49 50 return self::$instance; 51 } 52 53 /** 54 * The BP Nouveau constructor. 55 * 56 * @since 3.0.0 57 */ 58 public function __construct() { 59 parent::start(); 60 61 $this->includes(); 62 $this->setup_support(); 63 } 64 65 /** 66 * BP Nouveau global variables. 67 * 68 * @since 3.0.0 69 */ 70 protected function setup_globals() { 71 $bp = buddypress(); 72 73 foreach ( $bp->theme_compat->packages['nouveau'] as $property => $value ) { 74 $this->{$property} = $value; 75 } 76 77 $this->includes_dir = trailingslashit( $this->dir ) . 'includes/'; 78 $this->directory_nav = new BP_Core_Nav(); 79 } 80 81 /** 82 * Includes! 83 * 84 * @since 3.0.0 85 */ 86 protected function includes() { 87 require $this->includes_dir . 'functions.php'; 88 require $this->includes_dir . 'classes.php'; 89 require $this->includes_dir . 'template-tags.php'; 90 91 // Test suite requires the AJAX functions early. 92 if ( function_exists( 'tests_add_filter' ) ) { 93 require $this->includes_dir . 'ajax.php'; 94 95 // Load AJAX code only on AJAX requests. 96 } else { 97 add_action( 'admin_init', function() { 98 if ( defined( 'DOING_AJAX' ) && true === DOING_AJAX ) { 99 require bp_nouveau()->includes_dir . 'ajax.php'; 100 } 101 }, 0 ); 102 } 103 104 add_action( 'bp_customize_register', function() { 105 if ( bp_is_root_blog() && current_user_can( 'customize' ) ) { 106 require bp_nouveau()->includes_dir . 'customizer.php'; 107 } 108 }, 0 ); 109 110 foreach ( bp_core_get_packaged_component_ids() as $component ) { 111 $component_loader = trailingslashit( $this->includes_dir ) . $component . '/loader.php'; 112 113 if ( ! bp_is_active( $component ) || ! file_exists( $component_loader ) ) { 114 continue; 115 } 116 117 require( $component_loader ); 118 } 119 120 /** 121 * Fires after all of the BuddyPress Nouveau includes have been loaded. Passed by reference. 122 * 123 * @since 3.0.0 124 * 125 * @param BP_Nouveau $value Current BP_Nouveau instance. 126 */ 127 do_action_ref_array( 'bp_nouveau_includes', array( &$this ) ); 128 } 129 130 /** 131 * Setup the Template Pack features support. 132 * 133 * @since 3.0.0 134 */ 135 protected function setup_support() { 136 $width = 1300; 137 $top_offset = 150; 138 139 /** This filter is documented in bp-core/bp-core-avatars.php. */ 140 $avatar_height = apply_filters( 'bp_core_avatar_full_height', $top_offset ); 141 142 if ( $avatar_height > $top_offset ) { 143 $top_offset = $avatar_height; 144 } 145 146 bp_set_theme_compat_feature( $this->id, array( 147 'name' => 'cover_image', 148 'settings' => array( 149 'components' => array( 'members', 'groups' ), 150 'width' => $width, 151 'height' => $top_offset + round( $avatar_height / 2 ), 152 'callback' => 'bp_nouveau_theme_cover_image', 153 'theme_handle' => 'bp-nouveau', 154 ), 155 ) ); 156 } 157 158 /** 159 * Setup the Template Pack common actions. 160 * 161 * @since 3.0.0 162 */ 163 protected function setup_actions() { 164 // Filter BuddyPress template hierarchy and look for page templates. 165 add_filter( 'bp_get_buddypress_template', array( $this, 'theme_compat_page_templates' ), 10, 1 ); 166 167 // Add our "buddypress" div wrapper to theme compat template parts. 168 add_filter( 'bp_replace_the_content', array( $this, 'theme_compat_wrapper' ), 999 ); 169 170 // We need to neutralize the BuddyPress core "bp_core_render_message()" once it has been added. 171 add_action( 'bp_actions', array( $this, 'neutralize_core_template_notices' ), 6 ); 172 173 // Scripts. 174 add_action( 'bp_enqueue_scripts', array( $this, 'register_scripts' ), 2 ); // Register theme JS. 175 remove_action( 'bp_enqueue_scripts', 'bp_core_confirmation_js' ); 176 add_action( 'bp_enqueue_scripts', array( $this, 'enqueue_styles' ) ); // Enqueue theme CSS. 177 add_action( 'bp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); // Enqueue theme JS. 178 add_filter( 'bp_enqueue_scripts', array( $this, 'localize_scripts' ) ); // Enqueue theme script localization. 179 180 // Body no-js class. 181 add_filter( 'body_class', array( $this, 'add_nojs_body_class' ), 20, 1 ); 182 183 // Ajax querystring. 184 add_filter( 'bp_ajax_querystring', 'bp_nouveau_ajax_querystring', 10, 2 ); 185 186 // Register directory nav items. 187 add_action( 'bp_screens', array( $this, 'setup_directory_nav' ), 15 ); 188 189 // Register the Default front pages Dynamic Sidebars. 190 add_action( 'widgets_init', 'bp_nouveau_register_sidebars', 11 ); 191 192 // Register the Primary Object nav widget. 193 add_action( 'bp_widgets_init', array( 'BP_Nouveau_Object_Nav_Widget', 'register_widget' ) ); 194 195 // Set the BP Uri for the Ajax customizer preview. 196 add_filter( 'bp_uri', array( $this, 'customizer_set_uri' ), 10, 1 ); 197 198 /** Override **********************************************************/ 199 200 /** 201 * Fires after all of the BuddyPress theme compat actions have been added. 202 * 203 * @since 3.0.0 204 * 205 * @param BP_Nouveau $this Current BP_Nouveau instance. 206 */ 207 do_action_ref_array( 'bp_theme_compat_actions', array( &$this ) ); 208 } 209 210 /** 211 * Enqueue the template pack css files 212 * 213 * @since 3.0.0 214 */ 215 public function enqueue_styles() { 216 $min = bp_core_get_minified_asset_suffix(); 217 $rtl = ''; 218 219 if ( is_rtl() ) { 220 $rtl = '-rtl'; 221 } 222 223 /** 224 * Filters the BuddyPress Nouveau CSS dependencies. 225 * 226 * @since 3.0.0 227 * 228 * @param array $value Array of style dependencies. Default Dashicons. 229 */ 230 $css_dependencies = apply_filters( 'bp_nouveau_css_dependencies', array( 'dashicons' ) ); 231 232 /** 233 * Filters the styles to enqueue for BuddyPress Nouveau. 234 * 235 * This filter provides a multidimensional array that will map to arguments used for wp_enqueue_style(). 236 * The primary index should have the stylesheet handle to use, and be assigned an array that has indexes for 237 * file location, dependencies, and version. 238 * 239 * @since 3.0.0 240 * 241 * @param array $value Array of styles to enqueue. 242 */ 243 $styles = apply_filters( 'bp_nouveau_enqueue_styles', array( 244 'bp-nouveau' => array( 245 'file' => 'css/buddypress%1$s%2$s.css', 'dependencies' => $css_dependencies, 'version' => $this->version, 246 ), 247 ) ); 248 249 if ( $styles ) { 250 251 foreach ( $styles as $handle => $style ) { 252 if ( ! isset( $style['file'] ) ) { 253 continue; 254 } 255 256 $file = sprintf( $style['file'], $rtl, $min ); 257 258 // Locate the asset if needed. 259 if ( false === strpos( $style['file'], '://' ) ) { 260 $asset = bp_locate_template_asset( $file ); 261 262 if ( empty( $asset['uri'] ) || false === strpos( $asset['uri'], '://' ) ) { 263 continue; 264 } 265 266 $file = $asset['uri']; 267 } 268 269 $data = bp_parse_args( 270 $style, 271 array( 272 'dependencies' => array(), 273 'version' => $this->version, 274 'type' => 'screen', 275 ), 276 'nouveau_enqueue_styles' 277 ); 278 279 wp_enqueue_style( $handle, $file, $data['dependencies'], $data['version'], $data['type'] ); 280 281 if ( $min ) { 282 wp_style_add_data( $handle, 'suffix', $min ); 283 } 284 } 285 } 286 287 // Compatibility stylesheets for specific themes. 288 $theme = get_template(); 289 $companion_stylesheet = bp_locate_template_asset( sprintf( 'css/%1$s%2$s.css', $theme, $min ) ); 290 $companion_handle = 'bp-' . $theme; 291 292 if ( ! is_rtl() && isset( $companion_stylesheet['uri'] ) && $companion_stylesheet['uri'] ) { 293 wp_enqueue_style( $companion_handle, $companion_stylesheet['uri'], array(), $this->version, 'screen' ); 294 295 if ( $min ) { 296 wp_style_add_data( $companion_handle, 'suffix', $min ); 297 } 298 } 299 300 // Compatibility stylesheet for specific themes, RTL-version. 301 if ( is_rtl() ) { 302 $rtl_companion_stylesheet = bp_locate_template_asset( sprintf( 'css/%1$s-rtl%2$s.css', $theme, $min ) ); 303 304 if ( isset( $rtl_companion_stylesheet['uri'] ) ) { 305 $companion_handle .= '-rtl'; 306 wp_enqueue_style( $companion_handle, $rtl_companion_stylesheet['uri'], array(), $this->version, 'screen' ); 307 308 if ( $min ) { 309 wp_style_add_data( $companion_handle, 'suffix', $min ); 310 } 311 } 312 } 313 } 314 315 /** 316 * Register Template Pack JavaScript files 317 * 318 * @since 3.0.0 319 */ 320 public function register_scripts() { 321 $min = bp_core_get_minified_asset_suffix(); 322 $dependencies = bp_core_get_js_dependencies(); 323 $bp_confirm = array_search( 'bp-confirm', $dependencies ); 324 325 unset( $dependencies[ $bp_confirm ] ); 326 327 /** 328 * Filters the scripts to enqueue for BuddyPress Nouveau. 329 * 330 * This filter provides a multidimensional array that will map to arguments used for wp_register_script(). 331 * The primary index should have the script handle to use, and be assigned an array that has indexes for 332 * file location, dependencies, version and if it should load in the footer or not. 333 * 334 * @since 3.0.0 335 * 336 * @param array $value Array of scripts to register. 337 */ 338 $scripts = apply_filters( 'bp_nouveau_register_scripts', array( 339 'bp-nouveau' => array( 340 'file' => 'js/buddypress-nouveau%s.js', 341 'dependencies' => $dependencies, 342 'version' => $this->version, 343 'footer' => true, 344 ), 345 ) ); 346 347 // Bail if no scripts. 348 if ( empty( $scripts ) ) { 349 return; 350 } 351 352 // Add The password verify if needed. 353 if ( bp_is_active( 'settings' ) || bp_get_signup_allowed() ) { 354 /** 355 * BP Nouveau is now directly using the `wp-admin/js/user-profile.js` script. 356 * 357 * Setting the user password is now more consistent with how WordPress handles it. 358 * 359 * @deprecated 5.0.0 360 */ 361 $scripts['bp-nouveau-password-verify'] = array( 362 'file' => 'js/password-verify%s.js', 363 'dependencies' => array( 'bp-nouveau', 'password-strength-meter' ), 364 'footer' => true, 365 ); 366 } 367 368 foreach ( $scripts as $handle => $script ) { 369 if ( ! isset( $script['file'] ) ) { 370 continue; 371 } 372 373 $file = sprintf( $script['file'], $min ); 374 375 // Locate the asset if needed. 376 if ( false === strpos( $script['file'], '://' ) ) { 377 $asset = bp_locate_template_asset( $file ); 378 379 if ( empty( $asset['uri'] ) || false === strpos( $asset['uri'], '://' ) ) { 380 continue; 381 } 382 383 $file = $asset['uri']; 384 } 385 386 $data = bp_parse_args( 387 $script, 388 array( 389 'dependencies' => array(), 390 'version' => $this->version, 391 'footer' => false, 392 ), 393 'nouveau_register_scripts' 394 ); 395 396 wp_register_script( $handle, $file, $data['dependencies'], $data['version'], $data['footer'] ); 397 } 398 } 399 400 /** 401 * Enqueue the required JavaScript files 402 * 403 * @since 3.0.0 404 */ 405 public function enqueue_scripts() { 406 wp_enqueue_script( 'bp-nouveau' ); 407 408 if ( bp_is_register_page() || bp_is_user_settings_general() ) { 409 wp_enqueue_script( 'user-profile' ); 410 } 411 412 if ( is_singular() && bp_is_blog_page() && get_option( 'thread_comments' ) ) { 413 wp_enqueue_script( 'comment-reply' ); 414 } 415 416 /** 417 * Fires after all of the BuddyPress Nouveau scripts have been enqueued. 418 * 419 * @since 3.0.0 420 */ 421 do_action( 'bp_nouveau_enqueue_scripts' ); 422 } 423 424 /** 425 * Adds the no-js class to the body tag. 426 * 427 * This function ensures that the <body> element will have the 'no-js' class by default. If you're 428 * using JavaScript for some visual functionality in your theme, and you want to provide noscript 429 * support, apply those styles to body.no-js. 430 * 431 * The no-js class is removed by the JavaScript created in buddypress.js. 432 * 433 * @since 3.0.0 434 * 435 * @param array $classes Array of classes to append to body tag. 436 * 437 * @return array $classes 438 */ 439 public function add_nojs_body_class( $classes ) { 440 $classes[] = 'no-js'; 441 return array_unique( $classes ); 442 } 443 444 /** 445 * Load localizations for topic script. 446 * 447 * These localizations require information that may not be loaded even by init. 448 * 449 * @since 3.0.0 450 */ 451 public function localize_scripts() { 452 $params = array( 453 'ajaxurl' => bp_core_ajax_url(), 454 'confirm' => __( 'Are you sure?', 'buddypress' ), 455 456 /* translators: %s: number of activity comments */ 457 'show_x_comments' => __( 'Show all %d comments', 'buddypress' ), 458 'unsaved_changes' => __( 'Your profile has unsaved changes. If you leave the page, the changes will be lost.', 'buddypress' ), 459 'object_nav_parent' => '#buddypress', 460 ); 461 462 // If the Object/Item nav are in the sidebar. 463 if ( bp_nouveau_is_object_nav_in_sidebar() ) { 464 $params['object_nav_parent'] = '.buddypress_object_nav'; 465 } 466 467 /** 468 * Filters the supported BuddyPress Nouveau components. 469 * 470 * @since 3.0.0 471 * 472 * @param array $value Array of supported components. 473 */ 474 $supported_objects = (array) apply_filters( 'bp_nouveau_supported_components', bp_core_get_packaged_component_ids() ); 475 $object_nonces = array(); 476 477 foreach ( $supported_objects as $key_object => $object ) { 478 if ( ! bp_is_active( $object ) || 'forums' === $object ) { 479 unset( $supported_objects[ $key_object ] ); 480 continue; 481 } 482 483 $object_nonces[ $object ] = wp_create_nonce( 'bp_nouveau_' . $object ); 484 } 485 486 // Groups require some additional objects. 487 if ( bp_is_active( 'groups' ) ) { 488 $supported_objects = array_merge( $supported_objects, array( 'group_members', 'group_requests' ) ); 489 } 490 491 // Add components & nonces. 492 $params['objects'] = $supported_objects; 493 $params['nonces'] = $object_nonces; 494 495 // Used to transport the settings inside the Ajax requests. 496 if ( is_customize_preview() ) { 497 $params['customizer_settings'] = bp_nouveau_get_temporary_setting( 'any' ); 498 } 499 500 /** 501 * Filters core JavaScript strings for internationalization before AJAX usage. 502 * 503 * @since 3.0.0 504 * 505 * @param array $params Array of key/value pairs for AJAX usage. 506 */ 507 wp_localize_script( 'bp-nouveau', 'BP_Nouveau', apply_filters( 'bp_core_get_js_strings', $params ) ); 508 } 509 510 /** 511 * Filter the default theme compatibility root template hierarchy, and prepend 512 * a page template to the front if it's set. 513 * 514 * @see https://buddypress.trac.wordpress.org/ticket/6065 515 * 516 * @since 3.0.0 517 * 518 * @param array $templates Array of templates. 519 * 520 * @return array 521 */ 522 public function theme_compat_page_templates( $templates = array() ) { 523 /** 524 * Filters whether or not we are looking at a directory to determine if to return early. 525 * 526 * @since 3.0.0 527 * 528 * @param bool $value Whether or not we are viewing a directory. 529 */ 530 if ( true === (bool) apply_filters( 'bp_nouveau_theme_compat_page_templates_directory_only', ! bp_is_directory() ) ) { 531 return $templates; 532 } 533 534 // No page ID yet. 535 $page_id = 0; 536 537 // Get the WordPress Page ID for the current view. 538 foreach ( (array) buddypress()->pages as $component => $bp_page ) { 539 540 // Handles the majority of components. 541 if ( bp_is_current_component( $component ) ) { 542 $page_id = (int) $bp_page->id; 543 } 544 545 // Stop if not on a user page. 546 if ( ! bp_is_user() && ! empty( $page_id ) ) { 547 break; 548 } 549 550 // The Members component requires an explicit check due to overlapping components. 551 if ( bp_is_user() && ( 'members' === $component ) ) { 552 $page_id = (int) $bp_page->id; 553 break; 554 } 555 } 556 557 // Bail if no directory page set. 558 if ( 0 === $page_id ) { 559 return $templates; 560 } 561 562 // Check for page template. 563 $page_template = get_page_template_slug( $page_id ); 564 565 // Add it to the beginning of the templates array so it takes precedence over the default hierarchy. 566 if ( ! empty( $page_template ) ) { 567 568 /** 569 * Check for existence of template before adding it to template 570 * stack to avoid accidentally including an unintended file. 571 * 572 * @see https://buddypress.trac.wordpress.org/ticket/6190 573 */ 574 if ( '' !== locate_template( $page_template ) ) { 575 array_unshift( $templates, $page_template ); 576 } 577 } 578 579 return $templates; 580 } 581 582 /** 583 * Add our special 'buddypress' div wrapper to the theme compat template part. 584 * 585 * @since 3.0.0 586 * 587 * @see bp_buffer_template_part() 588 * 589 * @param string $retval Current template part contents. 590 * 591 * @return string 592 */ 593 public function theme_compat_wrapper( $retval ) { 594 if ( false !== strpos( $retval, '<div id="buddypress"' ) ) { 595 return $retval; 596 } 597 598 // Add our 'buddypress' div wrapper. 599 return sprintf( 600 '<div id="buddypress" class="%1$s">%2$s</div><!-- #buddypress -->%3$s', 601 esc_attr( bp_nouveau_get_container_classes() ), 602 $retval, // Constructed HTML. 603 "\n" 604 ); 605 } 606 607 /** 608 * Define the directory nav items 609 * 610 * @since 3.0.0 611 */ 612 public function setup_directory_nav() { 613 $nav_items = array(); 614 615 if ( bp_is_members_directory() ) { 616 $nav_items = bp_nouveau_get_members_directory_nav_items(); 617 } elseif ( bp_is_activity_directory() ) { 618 $nav_items = bp_nouveau_get_activity_directory_nav_items(); 619 } elseif ( bp_is_groups_directory() ) { 620 $nav_items = bp_nouveau_get_groups_directory_nav_items(); 621 } elseif ( bp_is_blogs_directory() ) { 622 $nav_items = bp_nouveau_get_blogs_directory_nav_items(); 623 } 624 625 if ( empty( $nav_items ) ) { 626 return; 627 } 628 629 foreach ( $nav_items as $nav_item ) { 630 if ( empty( $nav_item['component'] ) || $nav_item['component'] !== bp_current_component() ) { 631 continue; 632 } 633 634 // Define the primary nav for the current component's directory. 635 $this->directory_nav->add_nav( $nav_item ); 636 } 637 } 638 639 /** 640 * We'll handle template notices from BP Nouveau. 641 * 642 * @since 3.0.0 643 */ 644 public function neutralize_core_template_notices() { 645 remove_action( 'template_notices', 'bp_core_render_message' ); 646 } 647 648 /** 649 * Set the BP Uri for the customizer in case of Ajax requests. 650 * 651 * @since 3.0.0 652 * 653 * @param string $path the BP Uri. 654 * @return string the BP Uri. 655 */ 656 public function customizer_set_uri( $path ) { 657 if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { 658 return $path; 659 } 660 661 $uri = parse_url( $path ); 662 663 if ( false === strpos( $uri['path'], 'customize.php' ) ) { 664 return $path; 665 } else { 666 $vars = bp_parse_args( 667 $uri['query'], 668 array(), 669 'customizer_set_uri' 670 ); 671 672 if ( ! empty( $vars['url'] ) ) { 673 $path = str_replace( get_site_url(), '', urldecode( $vars['url'] ) ); 674 } 675 } 676 677 return $path; 678 } 679 } 680 681 /** 682 * Get a unique instance of BP Nouveau 683 * 684 * @since 3.0.0 685 * 686 * @return BP_Nouveau the main instance of the class 687 */ 688 function bp_nouveau() { 689 return BP_Nouveau::get_instance(); 690 } 691 692 /** 693 * Launch BP Nouveau! 694 */ 695 bp_nouveau();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Feb 25 01:01:43 2021 | Cross-referenced by PHPXref 0.7.1 |