[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/src/includes/topics/ -> template.php (source)

   1  <?php
   2  
   3  /**
   4   * bbPress Topic Template Tags
   5   *
   6   * @package bbPress
   7   * @subpackage TemplateTags
   8   */
   9  
  10  // Exit if accessed directly
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /** Post Type *****************************************************************/
  14  
  15  /**
  16   * Output the unique id of the custom post type for topics
  17   *
  18   * @since 2.0.0 bbPress (r2857)
  19   */
  20  function bbp_topic_post_type() {
  21      echo bbp_get_topic_post_type();
  22  }
  23      /**
  24       * Return the unique id of the custom post type for topics
  25       *
  26       * @since 2.0.0 bbPress (r2857)
  27       *
  28       * @return string The unique topic post type id
  29       */
  30  	function bbp_get_topic_post_type() {
  31  
  32          // Filter & return
  33          return apply_filters( 'bbp_get_topic_post_type', bbpress()->topic_post_type );
  34      }
  35  
  36  /**
  37   * Return array of labels used by the topic post type
  38   *
  39   * @since 2.5.0 bbPress (r5129)
  40   *
  41   * @return array
  42   */
  43  function bbp_get_topic_post_type_labels() {
  44  
  45      // Filter & return
  46      return (array) apply_filters( 'bbp_get_topic_post_type_labels', array(
  47          'name'                     => esc_attr__( 'Topics',                     'bbpress' ),
  48          'menu_name'                => esc_attr__( 'Topics',                     'bbpress' ),
  49          'singular_name'            => esc_attr__( 'Topic',                      'bbpress' ),
  50          'all_items'                => esc_attr__( 'All Topics',                 'bbpress' ),
  51          'add_new'                  => esc_attr__( 'Add New',                    'bbpress' ),
  52          'add_new_item'             => esc_attr__( 'Create New Topic',           'bbpress' ),
  53          'edit'                     => esc_attr__( 'Edit',                       'bbpress' ),
  54          'edit_item'                => esc_attr__( 'Edit Topic',                 'bbpress' ),
  55          'new_item'                 => esc_attr__( 'New Topic',                  'bbpress' ),
  56          'view'                     => esc_attr__( 'View Topic',                 'bbpress' ),
  57          'view_item'                => esc_attr__( 'View Topic',                 'bbpress' ),
  58          'view_items'               => esc_attr__( 'View Topics',                'bbpress' ),
  59          'search_items'             => esc_attr__( 'Search Topics',              'bbpress' ),
  60          'not_found'                => esc_attr__( 'No topics found',            'bbpress' ),
  61          'not_found_in_trash'       => esc_attr__( 'No topics found in Trash',   'bbpress' ),
  62          'filter_items_list'        => esc_attr__( 'Filter topics list',         'bbpress' ),
  63          'items_list'               => esc_attr__( 'Topics list',                'bbpress' ),
  64          'items_list_navigation'    => esc_attr__( 'Topics list navigation',     'bbpress' ),
  65          'parent_item_colon'        => esc_attr__( 'Forum:',                     'bbpress' ),
  66          'archives'                 => esc_attr__( 'Forum Topics',               'bbpress' ),
  67          'attributes'               => esc_attr__( 'Topic Attributes',           'bbpress' ),
  68          'insert_into_item'         => esc_attr__( 'Insert into topic',          'bbpress' ),
  69          'uploaded_to_this_item'    => esc_attr__( 'Uploaded to this topic',     'bbpress' ),
  70          'featured_image'           => esc_attr__( 'Topic Image',                'bbpress' ),
  71          'set_featured_image'       => esc_attr__( 'Set topic image',            'bbpress' ),
  72          'remove_featured_image'    => esc_attr__( 'Remove topic image',         'bbpress' ),
  73          'use_featured_image'       => esc_attr__( 'Use as topic image',         'bbpress' ),
  74          'item_published'           => esc_attr__( 'Topic published.',           'bbpress' ),
  75          'item_published_privately' => esc_attr__( 'Topic published privately.', 'bbpress' ),
  76          'item_reverted_to_draft'   => esc_attr__( 'Topic reverted to draft.',   'bbpress' ),
  77          'item_scheduled'           => esc_attr__( 'Topic scheduled.',           'bbpress' ),
  78          'item_updated'             => esc_attr__( 'Topic updated.',             'bbpress' )
  79      ) );
  80  }
  81  
  82  /**
  83   * Return array of topic post type rewrite settings
  84   *
  85   * @since 2.5.0 bbPress (r5129)
  86   *
  87   * @return array
  88   */
  89  function bbp_get_topic_post_type_rewrite() {
  90  
  91      // Filter & return
  92      return (array) apply_filters( 'bbp_get_topic_post_type_rewrite', array(
  93          'slug'       => bbp_get_topic_slug(),
  94          'with_front' => false
  95      ) );
  96  }
  97  
  98  /**
  99   * Return array of features the topic post type supports
 100   *
 101   * @since 2.5.0 bbPress (r5129)
 102   *
 103   * @return array
 104   */
 105  function bbp_get_topic_post_type_supports() {
 106  
 107      // Filter & return
 108      return (array) apply_filters( 'bbp_get_topic_post_type_supports', array(
 109          'title',
 110          'editor',
 111          'revisions'
 112      ) );
 113  }
 114  
 115  /**
 116   * The plugin version of bbPress comes with two topic display options:
 117   * - Traditional: Topics are included in the reply loop (default)
 118   * - New Style: Topics appear as "lead" posts, ahead of replies
 119   *
 120   * @since 2.0.0 bbPress (r2954)
 121   *
 122   * @param $show_lead Optional. Default false
 123   * @return bool Yes if the topic appears as a lead, otherwise false
 124   */
 125  function bbp_show_lead_topic( $show_lead = false ) {
 126  
 127      // Never separate the lead topic in feeds
 128      if ( is_feed() ) {
 129          return false;
 130      }
 131  
 132      // Filter & return
 133      return (bool) apply_filters( 'bbp_show_lead_topic', (bool) $show_lead );
 134  }
 135  
 136  /** Topic Loop ****************************************************************/
 137  
 138  /**
 139   * The main topic loop. WordPress makes this easy for us
 140   *
 141   * @since 2.0.0 bbPress (r2485)
 142   *
 143   * @param array $args All the arguments supported by {@link WP_Query}
 144   * @return object Multidimensional array of topic information
 145   */
 146  function bbp_has_topics( $args = array() ) {
 147  
 148      /** Defaults **************************************************************/
 149  
 150      // Other defaults
 151      $default_topic_search  = bbp_sanitize_search_request( 'ts' );
 152      $default_show_stickies = (bool) ( bbp_is_single_forum() || bbp_is_topic_archive() ) && ( false === $default_topic_search );
 153      $default_post_parent   = bbp_is_single_forum() ? bbp_get_forum_id() : 'any';
 154  
 155      // Default argument array
 156      $default = array(
 157          'post_type'      => bbp_get_topic_post_type(), // Narrow query down to bbPress topics
 158          'post_parent'    => $default_post_parent,      // Forum ID
 159          'meta_key'       => '_bbp_last_active_time',   // Make sure topic has some last activity time
 160          'meta_type'      => 'DATETIME',
 161          'orderby'        => 'meta_value',              // 'meta_value', 'author', 'date', 'title', 'modified', 'parent', rand',
 162          'order'          => 'DESC',                    // 'ASC', 'DESC'
 163          'posts_per_page' => bbp_get_topics_per_page(), // Topics per page
 164          'paged'          => bbp_get_paged(),           // Page Number
 165          'show_stickies'  => $default_show_stickies,    // Ignore sticky topics?
 166          'max_num_pages'  => false,                     // Maximum number of pages to show
 167  
 168          // Conditionally prime the cache for related posts
 169          'update_post_family_cache' => true
 170      );
 171  
 172      // Only add 's' arg if searching for topics
 173      // See https://bbpress.trac.wordpress.org/ticket/2607
 174      if ( ! empty( $default_topic_search ) ) {
 175          $default['s'] = $default_topic_search;
 176      }
 177  
 178      // What are the default allowed statuses (based on user caps)
 179      if ( bbp_get_view_all( 'edit_others_topics' ) ) {
 180  
 181          // Default view=all statuses
 182          $post_statuses = array_keys( bbp_get_topic_statuses() );
 183  
 184          // Add support for private status
 185          if ( current_user_can( 'read_private_topics' ) ) {
 186              $post_statuses[] = bbp_get_private_status_id();
 187          }
 188  
 189          // Join post statuses together
 190          $default['post_status'] = $post_statuses;
 191  
 192      // Lean on the 'perm' query var value of 'readable' to provide statuses
 193      } else {
 194          $default['perm'] = 'readable';
 195      }
 196  
 197      // Maybe query for topic tags
 198      if ( bbp_is_topic_tag() ) {
 199          $default['term']     = bbp_get_topic_tag_slug();
 200          $default['taxonomy'] = bbp_get_topic_tag_tax_id();
 201      }
 202  
 203      /** Setup *****************************************************************/
 204  
 205      // Parse arguments against default values
 206      $r = bbp_parse_args( $args, $default, 'has_topics' );
 207  
 208      // Get bbPress
 209      $bbp = bbpress();
 210  
 211      // Call the query
 212      $bbp->topic_query = new WP_Query( $r );
 213  
 214      // Maybe prime last active posts
 215      if ( ! empty( $r['update_post_family_cache'] ) ) {
 216          bbp_update_post_family_caches( $bbp->topic_query->posts );
 217      }
 218  
 219      // Set post_parent back to 0 if originally set to 'any'
 220      if ( 'any' === $r['post_parent'] ) {
 221          $r['post_parent'] = 0;
 222      }
 223  
 224      // Limited the number of pages shown
 225      if ( ! empty( $r['max_num_pages'] ) ) {
 226          $bbp->topic_query->max_num_pages = (int) $r['max_num_pages'];
 227      }
 228  
 229      /** Stickies **************************************************************/
 230  
 231      // Put sticky posts at the top of the posts array
 232      if ( ! empty( $r['show_stickies'] ) && ( $r['paged'] <= 1 ) ) {
 233          bbp_add_sticky_topics( $bbp->topic_query, $r );
 234      }
 235  
 236      // If no limit to posts per page, set it to the current post_count
 237      if ( -1 === $r['posts_per_page'] ) {
 238          $r['posts_per_page'] = $bbp->topic_query->post_count;
 239      }
 240  
 241      // Add pagination values to query object
 242      $bbp->topic_query->posts_per_page = (int) $r['posts_per_page'];
 243      $bbp->topic_query->paged          = (int) $r['paged'];
 244  
 245      // Only add pagination if query returned results
 246      if ( ( ! empty( $bbp->topic_query->post_count ) || ! empty( $bbp->topic_query->found_posts ) ) && ! empty( $bbp->topic_query->posts_per_page ) ) {
 247  
 248          // Limit the number of topics shown based on maximum allowed pages
 249          if ( ( ! empty( $r['max_num_pages'] ) ) && ( $bbp->topic_query->found_posts > ( $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count ) ) ) {
 250              $bbp->topic_query->found_posts = $bbp->topic_query->max_num_pages * $bbp->topic_query->post_count;
 251          }
 252  
 253          // Total topics for pagination boundaries
 254          $total_pages = ( $bbp->topic_query->posts_per_page === $bbp->topic_query->found_posts )
 255              ? 1
 256              : ceil( $bbp->topic_query->found_posts / $bbp->topic_query->posts_per_page );
 257  
 258          // Maybe add view-all args
 259          $add_args = bbp_get_view_all()
 260              ? array( 'view' => 'all' )
 261              : false;
 262  
 263          // Pagination settings with filter
 264          $bbp_topic_pagination = apply_filters( 'bbp_topic_pagination', array(
 265              'base'      => bbp_get_topics_pagination_base( $r['post_parent'] ),
 266              'format'    => '',
 267              'total'     => $total_pages,
 268              'current'   => $bbp->topic_query->paged,
 269              'prev_text' => is_rtl() ? '&rarr;' : '&larr;',
 270              'next_text' => is_rtl() ? '&larr;' : '&rarr;',
 271              'mid_size'  => 1,
 272              'add_args'  => $add_args,
 273          ) );
 274  
 275          // Add pagination to query object
 276          $bbp->topic_query->pagination_links = bbp_paginate_links( $bbp_topic_pagination );
 277      }
 278  
 279      // Filter & return
 280      return apply_filters( 'bbp_has_topics', $bbp->topic_query->have_posts(), $bbp->topic_query );
 281  }
 282  
 283  /**
 284   * Whether there are more topics available in the loop
 285   *
 286   * @since 2.0.0 bbPress (r2485)
 287   *
 288   * @return object Topic information
 289   */
 290  function bbp_topics() {
 291  
 292      // Put into variable to check against next
 293      $have_posts = bbpress()->topic_query->have_posts();
 294  
 295      // Reset the post data when finished
 296      if ( empty( $have_posts ) ) {
 297          wp_reset_postdata();
 298      }
 299  
 300      return $have_posts;
 301  }
 302  
 303  /**
 304   * Loads up the current topic in the loop
 305   *
 306   * @since 2.0.0 bbPress (r2485)
 307   *
 308   * @return object Topic information
 309   */
 310  function bbp_the_topic() {
 311      return bbpress()->topic_query->the_post();
 312  }
 313  
 314  /**
 315   * Add sticky topics to a topics query object
 316   *
 317   * @since 2.6.0 bbPress (r6402)
 318   *
 319   * @param WP_Query $query
 320   * @param array    $args
 321   */
 322  function bbp_add_sticky_topics( &$query, $args = array() ) {
 323  
 324      // Bail if intercepted
 325      $intercept = bbp_maybe_intercept( __FUNCTION__, func_get_args() );
 326      if ( bbp_is_intercepted( $intercept ) ) {
 327          return $intercept;
 328      }
 329  
 330      // Parse arguments against what gets used locally
 331      $r = bbp_parse_args( $args, array(
 332          'post_parent'         => 0,
 333          'post_parent__not_in' => array(),
 334          'post__not_in'        => array(),
 335          'post_status'         => '',
 336          'perm'                => ''
 337      ), 'add_sticky_topics' );
 338  
 339      // Get super stickies and stickies in this forum
 340      $super_stickies = bbp_get_super_stickies();
 341      $forum_stickies = ! empty( $r['post_parent'] )
 342          ? bbp_get_stickies( $r['post_parent'] )
 343          : array();
 344  
 345      // Merge stickies (supers first) and remove duplicates
 346      $stickies = array_filter( array_unique( array_merge( $super_stickies, $forum_stickies ) ) );
 347  
 348      // Bail if no stickies
 349      if ( empty( $stickies ) ) {
 350          return;
 351      }
 352  
 353      // If any posts have been excluded specifically, Ignore those that are sticky.
 354      if ( ! empty( $r['post__not_in'] ) ) {
 355          $stickies = array_diff( $stickies, $r['post__not_in'] );
 356      }
 357  
 358      // Default sticky posts array
 359      $sticky_topics = array();
 360  
 361      // Loop through posts
 362      foreach ( $query->posts as $key => $post ) {
 363  
 364          // Looking for stickies in this query loop, and stash & unset them
 365          if ( in_array( $post->ID, $stickies, true ) ) {
 366              $sticky_topics[] = $post;
 367              unset( $query->posts[ $key ] );
 368          }
 369      }
 370  
 371      // Remove queried stickies from stickies array
 372      if ( ! empty( $sticky_topics ) ) {
 373          $stickies = array_diff( $stickies, wp_list_pluck( $sticky_topics, 'ID' ) );
 374      }
 375  
 376      // Fetch all stickies that were not in the query
 377      if ( ! empty( $stickies ) ) {
 378  
 379          // Query to use in get_posts to get sticky posts
 380          $sticky_query = array(
 381              'post_type'   => bbp_get_topic_post_type(),
 382              'post_parent' => 'any',
 383              'meta_key'    => '_bbp_last_active_time',
 384              'meta_type'   => 'DATETIME',
 385              'orderby'     => 'meta_value',
 386              'order'       => 'DESC',
 387              'include'     => $stickies
 388          );
 389  
 390          // Conditionally exclude private/hidden forum ID's
 391          $exclude_forum_ids = bbp_exclude_forum_ids( 'array' );
 392  
 393          // Maybe remove the current forum from excluded forum IDs
 394          if ( ! empty( $r['post_parent' ] ) ) {
 395              unset( $exclude_forum_ids[ $r['post_parent' ] ] );
 396          }
 397  
 398          // Maybe exclude specific forums
 399          if ( ! empty( $exclude_forum_ids ) ) {
 400              $sticky_query['post_parent__not_in'] = $exclude_forum_ids;
 401          }
 402  
 403          // Allowed statuses, or lean on the 'perm' argument (probably 'readable')
 404          $sticky_query['post_status'] = bbp_get_view_all( 'edit_others_topics' )
 405              ? $r['post_status']
 406              : $r['perm'];
 407  
 408          // Get unqueried stickies
 409          $_posts = get_posts( $sticky_query );
 410          if ( ! empty( $_posts ) ) {
 411  
 412              // Merge the stickies topics with the query topics .
 413              $sticky_topics = array_merge( $sticky_topics, $_posts );
 414  
 415              // Get a count of the visible stickies
 416              $sticky_count = count( $_posts );
 417  
 418              // Adjust loop and counts for new sticky positions
 419              $query->found_posts = (int) $query->found_posts + (int) $sticky_count;
 420              $query->post_count  = (int) $query->post_count  + (int) $sticky_count;
 421          }
 422      }
 423  
 424      // Bail if no sticky topics empty or not an array
 425      if ( empty( $sticky_topics ) || ! is_array( $sticky_topics ) ) {
 426          return;
 427      }
 428  
 429      // Default ordered stickies array
 430      $ordered_stickies = array(
 431          'supers' => array(),
 432          'forums' => array()
 433      );
 434  
 435      // Separate supers from forums
 436      foreach ( $sticky_topics as $post ) {
 437          if ( in_array( $post->ID, $super_stickies, true ) ) {
 438              $ordered_stickies['supers'][] = $post;
 439          } elseif ( in_array( $post->ID, $forum_stickies, true ) ) {
 440              $ordered_stickies['forums'][] = $post;
 441          }
 442      }
 443  
 444      // Merge supers and forums, supers first
 445      $sticky_topics = array_merge( $ordered_stickies['supers'], $ordered_stickies['forums'] );
 446  
 447      // Update queried posts
 448      $query->posts = array_merge( $sticky_topics, array_values( $query->posts ) );
 449  }
 450  
 451  /**
 452   * Output the topic id
 453   *
 454   * @since 2.0.0 bbPress (r2485)
 455   */
 456  function bbp_topic_id( $topic_id = 0) {
 457      echo bbp_get_topic_id( $topic_id );
 458  }
 459      /**
 460       * Return the topic id
 461       *
 462       * @since 2.0.0 bbPress (r2485)
 463       *
 464       * @param $topic_id Optional. Used to check emptiness
 465       * @return int The topic id
 466       */
 467  	function bbp_get_topic_id( $topic_id = 0 ) {
 468          $bbp      = bbpress();
 469          $wp_query = bbp_get_wp_query();
 470  
 471          // Easy empty checking
 472          if ( ! empty( $topic_id ) && is_numeric( $topic_id ) ) {
 473              $bbp_topic_id = $topic_id;
 474  
 475          // Currently inside a topic loop
 476          } elseif ( ! empty( $bbp->topic_query->in_the_loop ) && isset( $bbp->topic_query->post->ID ) ) {
 477              $bbp_topic_id = $bbp->topic_query->post->ID;
 478  
 479          // Currently inside a search loop
 480          } elseif ( ! empty( $bbp->search_query->in_the_loop ) && isset( $bbp->search_query->post->ID ) && bbp_is_topic( $bbp->search_query->post->ID ) ) {
 481              $bbp_topic_id = $bbp->search_query->post->ID;
 482  
 483          // Currently viewing/editing a topic, likely alone
 484          } elseif ( ( bbp_is_single_topic() || bbp_is_topic_edit() ) && ! empty( $bbp->current_topic_id ) ) {
 485              $bbp_topic_id = $bbp->current_topic_id;
 486  
 487          // Currently viewing/editing a topic, likely in a loop
 488          } elseif ( ( bbp_is_single_topic() || bbp_is_topic_edit() ) && isset( $wp_query->post->ID ) ) {
 489              $bbp_topic_id = $wp_query->post->ID;
 490  
 491          // Currently viewing/editing a reply
 492          } elseif ( bbp_is_single_reply() || bbp_is_reply_edit() ) {
 493              $bbp_topic_id = bbp_get_reply_topic_id();
 494  
 495          // Fallback
 496          } else {
 497              $bbp_topic_id = 0;
 498          }
 499  
 500          // Filter & return
 501          return (int) apply_filters( 'bbp_get_topic_id', (int) $bbp_topic_id, $topic_id );
 502      }
 503  
 504  /**
 505   * Gets a topic
 506   *
 507   * @since 2.0.0 bbPress (r2787)
 508   *
 509   * @return mixed Null if error or topic (in specified form) if success
 510   */
 511  function bbp_get_topic( $topic, $output = OBJECT, $filter = 'raw' ) {
 512  
 513      // Maybe get ID from empty or int
 514      if ( empty( $topic ) || is_numeric( $topic ) ) {
 515          $topic = bbp_get_topic_id( $topic );
 516      }
 517  
 518      // Bail if no post object
 519      $topic = get_post( $topic, OBJECT, $filter );
 520      if ( empty( $topic ) ) {
 521          return $topic;
 522      }
 523  
 524      // Bail if not correct post type
 525      if ( $topic->post_type !== bbp_get_topic_post_type() ) {
 526          return null;
 527      }
 528  
 529      // Default return value is OBJECT
 530      $retval = $topic;
 531  
 532      // Array A
 533      if ( $output === ARRAY_A ) {
 534          $retval = get_object_vars( $topic );
 535  
 536      // Array N
 537      } elseif ( $output === ARRAY_N ) {
 538          $retval = array_values( get_object_vars( $topic ) );
 539      }
 540  
 541      // Filter & return
 542      return apply_filters( 'bbp_get_topic', $retval, $topic, $output, $filter );
 543  }
 544  
 545  /**
 546   * Output the link to the topic in the topic loop
 547   *
 548   * @since 2.0.0 bbPress (r2485)
 549   *
 550   * @param int $topic_id Optional. Topic id
 551   * @param string $redirect_to Optional. Pass a redirect value for use with
 552   *                              shortcodes and other fun things.
 553   */
 554  function bbp_topic_permalink( $topic_id = 0, $redirect_to = '' ) {
 555      echo esc_url( bbp_get_topic_permalink( $topic_id, $redirect_to ) );
 556  }
 557      /**
 558       * Return the link to the topic
 559       *
 560       * @since 2.0.0 bbPress (r2485)
 561       *
 562       * @param int $topic_id Optional. Topic id
 563       * @param string $redirect_to Optional. Pass a redirect value for use with
 564       *                              shortcodes and other fun things.
 565       * @return string Permanent link to topic
 566       */
 567  	function bbp_get_topic_permalink( $topic_id = 0, $redirect_to = '' ) {
 568          $topic_id = bbp_get_topic_id( $topic_id );
 569  
 570          // Use the redirect address
 571          if ( ! empty( $redirect_to ) ) {
 572              $topic_permalink = esc_url_raw( $redirect_to );
 573  
 574          // Use the topic permalink
 575          } else {
 576              $topic_permalink = get_permalink( $topic_id );
 577          }
 578  
 579          // Filter & return
 580          return apply_filters( 'bbp_get_topic_permalink', $topic_permalink, $topic_id );
 581      }
 582  
 583  /**
 584   * Output the title of the topic
 585   *
 586   * @since 2.0.0 bbPress (r2485)
 587   *
 588   * @param int $topic_id Optional. Topic id
 589   */
 590  function bbp_topic_title( $topic_id = 0 ) {
 591      echo bbp_get_topic_title( $topic_id );
 592  }
 593      /**
 594       * Return the title of the topic
 595       *
 596       * @since 2.0.0 bbPress (r2485)
 597       *
 598       * @param int $topic_id Optional. Topic id
 599       * @return string Title of topic
 600       */
 601  	function bbp_get_topic_title( $topic_id = 0 ) {
 602          $topic_id = bbp_get_topic_id( $topic_id );
 603          $title    = get_the_title( $topic_id );
 604  
 605          // Filter & return
 606          return apply_filters( 'bbp_get_topic_title', $title, $topic_id );
 607      }
 608  
 609  /**
 610   * Output the topic archive title
 611   *
 612   * @since 2.0.0 bbPress (r3249)
 613   *
 614   * @param string $title Default text to use as title
 615   */
 616  function bbp_topic_archive_title( $title = '' ) {
 617      echo bbp_get_topic_archive_title( $title );
 618  }
 619      /**
 620       * Return the topic archive title
 621       *
 622       * @since 2.0.0 bbPress (r3249)
 623       *
 624       * @param string $title Default text to use as title
 625       *
 626       * @return string The topic archive title
 627       */
 628  	function bbp_get_topic_archive_title( $title = '' ) {
 629  
 630          // If no title was passed
 631          if ( empty( $title ) ) {
 632  
 633              // Set root text to page title
 634              $page = bbp_get_page_by_path( bbp_get_topic_archive_slug() );
 635              if ( ! empty( $page ) ) {
 636                  $title = get_the_title( $page->ID );
 637  
 638              // Default to topic post type name label
 639              } else {
 640                  $tto   = get_post_type_object( bbp_get_topic_post_type() );
 641                  $title = $tto->labels->name;
 642              }
 643          }
 644  
 645          // Filter & return
 646          return apply_filters( 'bbp_get_topic_archive_title', $title );
 647      }
 648  
 649  /**
 650   * Output the content of the topic
 651   *
 652   * @since 2.0.0 bbPress (r2780)
 653   *
 654   * @param int $topic_id Optional. Topic id
 655   */
 656  function bbp_topic_content( $topic_id = 0 ) {
 657      echo bbp_get_topic_content( $topic_id );
 658  }
 659      /**
 660       * Return the content of the topic
 661       *
 662       * @since 2.0.0 bbPress (r2780)
 663       *
 664       * @param int $topic_id Optional. Topic id
 665       * @return string Content of the topic
 666       */
 667  	function bbp_get_topic_content( $topic_id = 0 ) {
 668          $topic_id = bbp_get_topic_id( $topic_id );
 669  
 670          // Check if password is required
 671          if ( post_password_required( $topic_id ) ) {
 672              return get_the_password_form();
 673          }
 674  
 675          $content = get_post_field( 'post_content', $topic_id );
 676  
 677          // Filter & return
 678          return apply_filters( 'bbp_get_topic_content', $content, $topic_id );
 679      }
 680  
 681  /**
 682   * Output the excerpt of the topic
 683   *
 684   * @since 2.0.0 bbPress (r2780)
 685   *
 686   * @param int $topic_id Optional. Topic id
 687   * @param int $length Optional. Length of the excerpt. Defaults to 100 letters
 688   */
 689  function bbp_topic_excerpt( $topic_id = 0, $length = 100 ) {
 690      echo bbp_get_topic_excerpt( $topic_id, $length );
 691  }
 692      /**
 693       * Return the excerpt of the topic
 694       *
 695       * @since 2.0.0 bbPress (r2780)
 696       *
 697       * @param int $topic_id Optional. topic id
 698       * @param int $length Optional. Length of the excerpt. Defaults to 100
 699       *                     letters
 700       * @return string topic Excerpt
 701       */
 702  	function bbp_get_topic_excerpt( $topic_id = 0, $length = 100 ) {
 703          $topic_id = bbp_get_topic_id( $topic_id );
 704          $length   = (int) $length;
 705          $excerpt  = get_post_field( 'post_excerpt', $topic_id );
 706  
 707          if ( empty( $excerpt ) ) {
 708              $excerpt = bbp_get_topic_content( $topic_id );
 709          }
 710  
 711          $excerpt = trim( strip_tags( $excerpt ) );
 712  
 713          // Multibyte support
 714          if ( function_exists( 'mb_strlen' ) ) {
 715              $excerpt_length = mb_strlen( $excerpt );
 716          } else {
 717              $excerpt_length = strlen( $excerpt );
 718          }
 719  
 720          if ( ! empty( $length ) && ( $excerpt_length > $length ) ) {
 721              $excerpt  = mb_substr( $excerpt, 0, $length - 1 );
 722              $excerpt .= '&hellip;';
 723          }
 724  
 725          // Filter & return
 726          return apply_filters( 'bbp_get_topic_excerpt', $excerpt, $topic_id, $length );
 727      }
 728  
 729  /**
 730   * Output the post date and time of a topic
 731   *
 732   * @since 2.2.0 bbPress (r4155)
 733   *
 734   * @param int $topic_id Optional. Topic id.
 735   * @param bool $humanize Optional. Humanize output using time_since
 736   * @param bool $gmt Optional. Use GMT
 737   */
 738  function bbp_topic_post_date( $topic_id = 0, $humanize = false, $gmt = false ) {
 739      echo bbp_get_topic_post_date( $topic_id, $humanize, $gmt );
 740  }
 741      /**
 742       * Return the post date and time of a topic
 743       *
 744       * @since 2.2.0 bbPress (r4155)
 745       *
 746       * @param int $topic_id Optional. Topic id.
 747       * @param bool $humanize Optional. Humanize output using time_since
 748       * @param bool $gmt Optional. Use GMT
 749       * @return string
 750       */
 751  	function bbp_get_topic_post_date( $topic_id = 0, $humanize = false, $gmt = false ) {
 752          $topic_id = bbp_get_topic_id( $topic_id );
 753  
 754          // 4 days, 4 hours ago
 755          if ( ! empty( $humanize ) ) {
 756              $gmt_s  = ! empty( $gmt ) ? 'G' : 'U';
 757              $date   = get_post_time( $gmt_s, $gmt, $topic_id );
 758              $time   = false; // For filter below
 759              $result = bbp_get_time_since( $date );
 760  
 761          // August 4, 2012 at 2:37 pm
 762          } else {
 763              $date   = get_post_time( get_option( 'date_format' ), $gmt, $topic_id, true );
 764              $time   = get_post_time( get_option( 'time_format' ), $gmt, $topic_id, true );
 765              $result = sprintf( _x( '%1$s at %2$s', 'date at time', 'bbpress' ), $date, $time );
 766          }
 767  
 768          // Filter & return
 769          return apply_filters( 'bbp_get_topic_post_date', $result, $topic_id, $humanize, $gmt, $date, $time );
 770      }
 771  
 772  /**
 773   * Output pagination links of a topic within the topic loop
 774   *
 775   * @since 2.0.0 bbPress (r2966)
 776   *
 777   * @param array $args See {@link bbp_get_topic_pagination()}
 778   */
 779  function bbp_topic_pagination( $args = array() ) {
 780      echo bbp_get_topic_pagination( $args );
 781  }
 782      /**
 783       * Returns pagination links of a topic within the topic loop
 784       *
 785       * @since 2.0.0 bbPress (r2966)
 786       *
 787       * @param array $args This function supports these arguments:
 788       *  - topic_id: Topic id
 789       *  - before: Before the links
 790       *  - after: After the links
 791       * @return string Pagination links
 792       */
 793  	function bbp_get_topic_pagination( $args = array() ) {
 794  
 795          // Bail if threading replies
 796          if ( bbp_thread_replies() ) {
 797              return;
 798          }
 799  
 800          // Parse arguments against default values
 801          $r = bbp_parse_args( $args, array(
 802              'topic_id' => bbp_get_topic_id(),
 803              'before'   => '<span class="bbp-topic-pagination">',
 804              'after'    => '</span>',
 805          ), 'get_topic_pagination' );
 806  
 807          // Slug must be checked for topics that have never been approved/published
 808          $has_slug = bbp_get_topic( $r['topic_id'] )->post_name;
 809  
 810          // If pretty permalinks are enabled, make our pagination pretty
 811          $base = ! empty( $has_slug ) && bbp_use_pretty_urls() && bbp_is_topic_public( $r['topic_id'] )
 812              ? trailingslashit( get_permalink( $r['topic_id'] ) ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' )
 813              : add_query_arg( 'paged', '%#%', get_permalink( $r['topic_id'] ) );
 814  
 815          // Get total and add 1 if topic is included in the reply loop
 816          $total = bbp_get_topic_reply_count( $r['topic_id'], true );
 817  
 818          // Bump if topic is in loop
 819          if ( ! bbp_show_lead_topic() ) {
 820              $total++;
 821          }
 822  
 823          // Total for pagination boundaries
 824          $total_pages = ceil( $total / bbp_get_replies_per_page() );
 825  
 826          // Maybe add view-all args
 827          $add_args = bbp_get_view_all( 'edit_others_replies' )
 828              ? array( 'view' => 'all' )
 829              : false;
 830  
 831          // Pagination settings with filter
 832          $bbp_topic_pagination = apply_filters( 'bbp_get_topic_pagination', array(
 833              'base'      => $base,
 834              'total'     => $total_pages,
 835              'current'   => 0,
 836              'prev_next' => false,
 837              'mid_size'  => 2,
 838              'end_size'  => 2,
 839              'add_args'  => $add_args
 840          ) );
 841  
 842          // Add pagination to query object
 843          $pagination_links = bbp_paginate_links( $bbp_topic_pagination );
 844  
 845          // Maybe add before and after to pagination links
 846          if ( ! empty( $pagination_links ) ) {
 847              $pagination_links = $r['before'] . $pagination_links . $r['after'];
 848          }
 849  
 850          // Filter & return
 851          return apply_filters( 'bbp_get_topic_pagination', $pagination_links, $args );
 852      }
 853  
 854  /**
 855   * Append revisions to the topic content
 856   *
 857   * @since 2.0.0 bbPress (r2782)
 858   *
 859   * @param string $content Optional. Content to which we need to append the revisions to
 860   * @param int $topic_id Optional. Topic id
 861   * @return string Content with the revisions appended
 862   */
 863  function bbp_topic_content_append_revisions( $content = '', $topic_id = 0 ) {
 864  
 865      // Bail if in admin or feed
 866      if ( is_admin() || is_feed() ) {
 867          return;
 868      }
 869  
 870      // Validate the ID
 871      $topic_id = bbp_get_topic_id( $topic_id );
 872  
 873      // Filter & return
 874      return apply_filters( 'bbp_topic_append_revisions', $content . bbp_get_topic_revision_log( $topic_id ), $content, $topic_id );
 875  }
 876  
 877  /**
 878   * Output the revision log of the topic
 879   *
 880   * @since 2.0.0 bbPress (r2782)
 881   *
 882   * @param int $topic_id Optional. Topic id
 883   */
 884  function bbp_topic_revision_log( $topic_id = 0 ) {
 885      echo bbp_get_topic_revision_log( $topic_id );
 886  }
 887      /**
 888       * Return the formatted revision log of the topic
 889       *
 890       * @since 2.0.0 bbPress (r2782)
 891       *
 892       * @param int $topic_id Optional. Topic id
 893       * @return string Revision log of the topic
 894       */
 895  	function bbp_get_topic_revision_log( $topic_id = 0 ) {
 896  
 897          // Create necessary variables
 898          $topic_id     = bbp_get_topic_id( $topic_id );
 899          $revision_log = bbp_get_topic_raw_revision_log( $topic_id );
 900  
 901          if ( empty( $topic_id ) || empty( $revision_log ) || ! is_array( $revision_log ) ) {
 902              return false;
 903          }
 904  
 905          $revisions = bbp_get_topic_revisions( $topic_id );
 906          if ( empty( $revisions ) ) {
 907              return false;
 908          }
 909  
 910          $retval = "\n\n" . '<ul id="bbp-topic-revision-log-' . esc_attr( $topic_id ) . '" class="bbp-topic-revision-log">' . "\n\n";
 911  
 912          // Loop through revisions
 913          foreach ( (array) $revisions as $revision ) {
 914  
 915              if ( empty( $revision_log[ $revision->ID ] ) ) {
 916                  $author_id = $revision->post_author;
 917                  $reason    = '';
 918              } else {
 919                  $author_id = $revision_log[ $revision->ID ]['author'];
 920                  $reason    = $revision_log[ $revision->ID ]['reason'];
 921              }
 922  
 923              $author = bbp_get_author_link( array( 'size' => 14, 'link_text' => bbp_get_topic_author_display_name( $revision->ID ), 'post_id' => $revision->ID ) );
 924              $since  = bbp_get_time_since( bbp_convert_date( $revision->post_modified ) );
 925  
 926              $retval .= "\t" . '<li id="bbp-topic-revision-log-' . esc_attr( $topic_id ) . '-item-' . esc_attr( $revision->ID ) . '" class="bbp-topic-revision-log-item">' . "\n";
 927              if ( ! empty( $reason ) ) {
 928                  $retval .= "\t\t" . sprintf( esc_html__( 'This topic was modified %1$s by %2$s. Reason: %3$s', 'bbpress' ), esc_html( $since ), $author, esc_html( $reason ) ) . "\n";
 929              } else {
 930                  $retval .= "\t\t" . sprintf( esc_html__( 'This topic was modified %1$s by %2$s.',              'bbpress' ), esc_html( $since ), $author ) . "\n";
 931              }
 932              $retval .= "\t" . '</li>' . "\n";
 933          }
 934  
 935          $retval .= "\n" . '</ul>' . "\n\n";
 936  
 937          // Filter & return
 938          return apply_filters( 'bbp_get_topic_revision_log', $retval, $topic_id );
 939      }
 940          /**
 941           * Return the raw revision log of the topic
 942           *
 943           * @since 2.0.0 bbPress (r2782)
 944           *
 945           * @param int $topic_id Optional. Topic id
 946           * @return string Raw revision log of the topic
 947           */
 948  		function bbp_get_topic_raw_revision_log( $topic_id = 0 ) {
 949              $topic_id = bbp_get_topic_id( $topic_id );
 950  
 951              $revision_log = get_post_meta( $topic_id, '_bbp_revision_log', true );
 952              $revision_log = ! empty( $revision_log )
 953                  ? $revision_log
 954                  : array();
 955  
 956              // Filter & return
 957              return apply_filters( 'bbp_get_topic_raw_revision_log', $revision_log, $topic_id );
 958          }
 959  
 960  /**
 961   * Return the revisions of the topic
 962   *
 963   * @since 2.0.0 bbPress (r2782)
 964   *
 965   * @param int $topic_id Optional. Topic id
 966   * @return string Topic revisions
 967   */
 968  function bbp_get_topic_revisions( $topic_id = 0 ) {
 969      $topic_id  = bbp_get_topic_id( $topic_id );
 970      $revisions = wp_get_post_revisions( $topic_id, array( 'order' => 'ASC' ) );
 971  
 972      // Filter & return
 973      return apply_filters( 'bbp_get_topic_revisions', $revisions, $topic_id );
 974  }
 975  
 976  /**
 977   * Return the revision count of the topic
 978   *
 979   * @since 2.0.0 bbPress (r2782)
 980   *
 981   * @param int $topic_id Optional. Topic id
 982   * @return string Topic revision count
 983   */
 984  function bbp_get_topic_revision_count( $topic_id = 0, $integer = false ) {
 985      $topic_id = bbp_get_topic_id( $topic_id );
 986      $count    = count( bbp_get_topic_revisions( $topic_id ) );
 987      $filter   = ( true === $integer )
 988          ? 'bbp_get_topic_revision_count_int'
 989          : 'bbp_get_topic_revision_count';
 990  
 991      return apply_filters( $filter, $count, $topic_id );
 992  }
 993  
 994  /**
 995   * Is the topic a sticky or super sticky?
 996   *
 997   * @since 2.0.0 bbPress (r2754)
 998   *
 999   * @param int $topic_id Optional. Topic id
1000   * @param int $check_super Optional. If set to true and if the topic is not a
1001   *                           normal sticky, it is checked if it is a super
1002   *                           sticky or not. Defaults to true.
1003   * @return bool True if sticky or super sticky, false if not.
1004   */
1005  function bbp_is_topic_sticky( $topic_id = 0, $check_super = true ) {
1006      $topic_id = bbp_get_topic_id( $topic_id );
1007      $forum_id = bbp_get_topic_forum_id( $topic_id );
1008      $stickies = bbp_get_stickies( $forum_id );
1009      $retval   = in_array( $topic_id, $stickies, true );
1010  
1011      // Maybe check super stickies
1012      if ( ( false === $retval ) && ( true === $check_super ) ) {
1013          $retval = bbp_is_topic_super_sticky( $topic_id );
1014      }
1015  
1016      // Filter & return
1017      return (bool) apply_filters( 'bbp_is_topic_sticky', $retval, $topic_id, $check_super );
1018  }
1019  
1020  /**
1021   * Is the topic a super sticky?
1022   *
1023   * @since 2.0.0 bbPress (r2754)
1024   *
1025   * @param int $topic_id Optional. Topic id
1026   * @return bool True if super sticky, false if not.
1027   */
1028  function bbp_is_topic_super_sticky( $topic_id = 0 ) {
1029      $topic_id = bbp_get_topic_id( $topic_id );
1030      $stickies = bbp_get_super_stickies( $topic_id );
1031      $retval   = in_array( $topic_id, $stickies, true );
1032  
1033      // Filter & return
1034      return (bool) apply_filters( 'bbp_is_topic_super_sticky', $retval, $topic_id );
1035  }
1036  
1037  /**
1038   * Output the status of the topic
1039   *
1040   * @since 2.0.0 bbPress (r2667)
1041   *
1042   * @param int $topic_id Optional. Topic id
1043   */
1044  function bbp_topic_status( $topic_id = 0 ) {
1045      echo bbp_get_topic_status( $topic_id );
1046  }
1047      /**
1048       * Return the status of the topic
1049       *
1050       * @since 2.0.0 bbPress (r2667)
1051       *
1052       * @param int $topic_id Optional. Topic id
1053       * @return string Status of topic
1054       */
1055  	function bbp_get_topic_status( $topic_id = 0 ) {
1056          $topic_id = bbp_get_topic_id( $topic_id );
1057  
1058          // Filter & return
1059          return apply_filters( 'bbp_get_topic_status', get_post_status( $topic_id ), $topic_id );
1060      }
1061  
1062  /**
1063   * Is the topic closed to new replies?
1064   *
1065   * @since 2.0.0 bbPress (r2746)
1066   *
1067   * @param int $topic_id Optional. Topic id
1068   *
1069   * @return bool True if closed, false if not.
1070   */
1071  function bbp_is_topic_closed( $topic_id = 0 ) {
1072      $topic_id     = bbp_get_topic_id( $topic_id );
1073      $status       = bbp_get_closed_status_id();
1074      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1075  
1076      // Filter & return
1077      return (bool) apply_filters( 'bbp_is_topic_closed', $topic_status, $topic_id );
1078  }
1079  
1080  /**
1081   * Is the topic open to new replies?
1082   *
1083   * @since 2.0.0 bbPress (r2727)
1084   *
1085   * @param int $topic_id Optional. Topic id
1086   *
1087   * @return bool True if open, false if closed.
1088   */
1089  function bbp_is_topic_open( $topic_id = 0 ) {
1090      return ! bbp_is_topic_closed( $topic_id );
1091  }
1092  
1093  /**
1094   * Is the topic publicly viewable?
1095   *
1096   * See bbp_get_public_topic_statuses() for public statuses.
1097   *
1098   * @since 2.6.0 bbPress (r6383)
1099   *
1100   * @param int $topic_id Optional. Topic id
1101   * @return bool True if public, false if not.
1102   */
1103  function bbp_is_topic_public( $topic_id = 0 ) {
1104      $topic_id  = bbp_get_topic_id( $topic_id );
1105      $status    = bbp_get_topic_status( $topic_id );
1106      $public    = bbp_get_public_topic_statuses();
1107      $is_public = in_array( $status, $public, true );
1108  
1109      // Filter & return
1110      return (bool) apply_filters( 'bbp_is_topic_public', $is_public, $topic_id );
1111  }
1112  
1113  /**
1114   * Does the topic have a published status?
1115   *
1116   * @since 2.0.0 bbPress (r3496)
1117   *
1118   * @param int $topic_id Optional. Topic id
1119   * @return bool True if published, false if not.
1120   */
1121  function bbp_is_topic_published( $topic_id = 0 ) {
1122      $topic_id     = bbp_get_topic_id( $topic_id );
1123      $status       = bbp_get_public_status_id();
1124      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1125  
1126      // Filter & return
1127      return (bool) apply_filters( 'bbp_is_topic_published', $topic_status, $topic_id );
1128  }
1129  
1130  /**
1131   * Is the topic marked as spam?
1132   *
1133   * @since 2.0.0 bbPress (r2727)
1134   *
1135   * @param int $topic_id Optional. Topic id
1136   * @return bool True if spam, false if not.
1137   */
1138  function bbp_is_topic_spam( $topic_id = 0 ) {
1139      $topic_id     = bbp_get_topic_id( $topic_id );
1140      $status       = bbp_get_spam_status_id();
1141      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1142  
1143      // Filter & return
1144      return (bool) apply_filters( 'bbp_is_topic_spam', $topic_status, $topic_id );
1145  }
1146  
1147  /**
1148   * Is the topic trashed?
1149   *
1150   * @since 2.0.0 bbPress (r2888)
1151   *
1152   * @param int $topic_id Optional. Topic id
1153   * @return bool True if trashed, false if not.
1154   */
1155  function bbp_is_topic_trash( $topic_id = 0 ) {
1156      $topic_id     = bbp_get_topic_id( $topic_id );
1157      $status       = bbp_get_trash_status_id();
1158      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1159  
1160      // Filter & return
1161      return (bool) apply_filters( 'bbp_is_topic_trash', $topic_status, $topic_id );
1162  }
1163  
1164  /**
1165   * Is the topic pending?
1166   *
1167   * @since 2.6.0 bbPress (r5504)
1168   *
1169   * @param int $topic_id Optional. Topic id
1170   * @return bool True if pending, false if not.
1171   */
1172  function bbp_is_topic_pending( $topic_id = 0 ) {
1173      $topic_id     = bbp_get_topic_id( $topic_id );
1174      $status       = bbp_get_pending_status_id();
1175      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1176  
1177      // Filter & return
1178      return (bool) apply_filters( 'bbp_is_topic_pending', $topic_status, $topic_id );
1179  }
1180  
1181  /**
1182   * Is the topic private?
1183   *
1184   * @since 2.6.0 bbPress (r5504)
1185   *
1186   * @param int $topic_id Optional. Topic id
1187   * @return bool True if private, false if not.
1188   */
1189  function bbp_is_topic_private( $topic_id = 0 ) {
1190      $topic_id     = bbp_get_topic_id( $topic_id );
1191      $status       = bbp_get_private_status_id();
1192      $topic_status = ( bbp_get_topic_status( $topic_id ) === $status );
1193  
1194      // Filter & return
1195      return (bool) apply_filters( 'bbp_is_topic_private', $topic_status, $topic_id );
1196  }
1197  
1198  /**
1199   * Is the posted by an anonymous user?
1200   *
1201   * @since 2.0.0 bbPress (r2753)
1202   *
1203   * @param int $topic_id Optional. Topic id
1204   * @return bool True if the post is by an anonymous user, false if not.
1205   */
1206  function bbp_is_topic_anonymous( $topic_id = 0 ) {
1207      $topic_id = bbp_get_topic_id( $topic_id );
1208      $retval   = false;
1209  
1210      if ( ! bbp_get_topic_author_id( $topic_id ) ) {
1211          $retval = true;
1212  
1213      } elseif ( get_post_meta( $topic_id, '_bbp_anonymous_name',  true ) ) {
1214          $retval = true;
1215  
1216      } elseif ( get_post_meta( $topic_id, '_bbp_anonymous_email', true ) ) {
1217          $retval = true;
1218      }
1219  
1220      // Filter & return
1221      return (bool) apply_filters( 'bbp_is_topic_anonymous', $retval, $topic_id );
1222  }
1223  
1224  /**
1225   * Deprecated. Use bbp_topic_author_display_name() instead.
1226   *
1227   * Output the author of the topic.
1228   *
1229   * @since 2.0.0 bbPress (r2590)
1230   *
1231   * @deprecated 2.5.0 bbPress (r5119)
1232   *
1233   * @param int $topic_id Optional. Topic id
1234   */
1235  function bbp_topic_author( $topic_id = 0 ) {
1236      echo bbp_get_topic_author( $topic_id );
1237  }
1238      /**
1239       * Deprecated. Use bbp_get_topic_author_display_name() instead.
1240       *
1241       * Return the author of the topic
1242       *
1243       * @since 2.0.0 bbPress (r2590)
1244       *
1245       * @deprecated 2.5.0 bbPress (r5119)
1246       *
1247       * @param int $topic_id Optional. Topic id
1248       * @return string Author of topic
1249       */
1250  	function bbp_get_topic_author( $topic_id = 0 ) {
1251          $topic_id = bbp_get_topic_id( $topic_id );
1252  
1253          if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1254              $author = get_the_author_meta( 'display_name', bbp_get_topic_author_id( $topic_id ) );
1255          } else {
1256              $author = get_post_meta( $topic_id, '_bbp_anonymous_name', true );
1257          }
1258  
1259          // Filter & return
1260          return apply_filters( 'bbp_get_topic_author', $author, $topic_id );
1261      }
1262  
1263  /**
1264   * Output the author ID of the topic
1265   *
1266   * @since 2.0.0 bbPress (r2590)
1267   *
1268   * @param int $topic_id Optional. Topic id
1269   */
1270  function bbp_topic_author_id( $topic_id = 0 ) {
1271      echo bbp_get_topic_author_id( $topic_id );
1272  }
1273      /**
1274       * Return the author ID of the topic
1275       *
1276       * @since 2.0.0 bbPress (r2590)
1277       *
1278       * @param int $topic_id Optional. Topic id
1279       * @return string Author of topic
1280       */
1281  	function bbp_get_topic_author_id( $topic_id = 0 ) {
1282          $topic_id  = bbp_get_topic_id( $topic_id );
1283          $author_id = get_post_field( 'post_author', $topic_id );
1284  
1285          // Filter & return
1286          return (int) apply_filters( 'bbp_get_topic_author_id', (int) $author_id, $topic_id );
1287      }
1288  
1289  /**
1290   * Output the author display_name of the topic
1291   *
1292   * @since 2.0.0 bbPress (r2590)
1293   *
1294   * @param int $topic_id Optional. Topic id
1295   */
1296  function bbp_topic_author_display_name( $topic_id = 0 ) {
1297      echo bbp_get_topic_author_display_name( $topic_id );
1298  }
1299      /**
1300       * Return the author display_name of the topic
1301       *
1302       * @since 2.0.0 bbPress (r2485)
1303       *
1304       * @param int $topic_id Optional. Topic id
1305       * @return string Topic's author's display name
1306       */
1307  	function bbp_get_topic_author_display_name( $topic_id = 0 ) {
1308          $topic_id = bbp_get_topic_id( $topic_id );
1309  
1310          // Check for anonymous user
1311          if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1312  
1313              // Get the author ID
1314              $author_id = bbp_get_topic_author_id( $topic_id );
1315  
1316              // Try to get a display name
1317              $author_name = get_the_author_meta( 'display_name', $author_id );
1318  
1319              // Fall back to user login
1320              if ( empty( $author_name ) ) {
1321                  $author_name = get_the_author_meta( 'user_login', $author_id );
1322              }
1323  
1324          // User does not have an account
1325          } else {
1326              $author_name = get_post_meta( $topic_id, '_bbp_anonymous_name', true );
1327          }
1328  
1329          // Fallback if nothing could be found
1330          if ( empty( $author_name ) ) {
1331              $author_name = bbp_get_fallback_display_name( $topic_id );
1332          }
1333  
1334          // Encode possible UTF8 display names
1335          if ( seems_utf8( $author_name ) === false ) {
1336              $author_name = utf8_encode( $author_name );
1337          }
1338  
1339          // Filter & return
1340          return apply_filters( 'bbp_get_topic_author_display_name', $author_name, $topic_id );
1341      }
1342  
1343  /**
1344   * Output the author avatar of the topic
1345   *
1346   * @since 2.0.0 bbPress (r2590)
1347   *
1348   * @param int $topic_id Optional. Topic id
1349   * @param int $size Optional. Avatar size. Defaults to 40
1350   */
1351  function bbp_topic_author_avatar( $topic_id = 0, $size = 40 ) {
1352      echo bbp_get_topic_author_avatar( $topic_id, $size );
1353  }
1354      /**
1355       * Return the author avatar of the topic
1356       *
1357       * @since 2.0.0 bbPress (r2590)
1358       *
1359       * @param int $topic_id Optional. Topic id
1360       * @param int $size Optional. Avatar size. Defaults to 40
1361       * @return string Avatar of the author of the topic
1362       */
1363  	function bbp_get_topic_author_avatar( $topic_id = 0, $size = 40 ) {
1364          $author_avatar = '';
1365  
1366          $topic_id = bbp_get_topic_id( $topic_id );
1367          if ( ! empty( $topic_id ) ) {
1368              if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1369                  $author_avatar = get_avatar( bbp_get_topic_author_id( $topic_id ), $size );
1370              } else {
1371                  $author_avatar = get_avatar( get_post_meta( $topic_id, '_bbp_anonymous_email', true ), $size );
1372              }
1373          }
1374  
1375          // Filter & return
1376          return apply_filters( 'bbp_get_topic_author_avatar', $author_avatar, $topic_id, $size );
1377      }
1378  
1379  /**
1380   * Output the author link of the topic
1381   *
1382   * @since 2.0.0 bbPress (r2717)
1383   *
1384   * @param mixed|int $args If it is an integer, it is used as topic_id. Optional.
1385   */
1386  function bbp_topic_author_link( $args = array() ) {
1387      echo bbp_get_topic_author_link( $args );
1388  }
1389      /**
1390       * Return the author link of the topic
1391       *
1392       * @since 2.0.0 bbPress (r2717)
1393       *
1394       * @param mixed|int $args If it is an integer, it is used as topic id.
1395       *                         Optional.
1396       * @return string Author link of topic
1397       */
1398  	function bbp_get_topic_author_link( $args = array() ) {
1399  
1400          // Parse arguments against default values
1401          $r = bbp_parse_args( $args, array(
1402              'post_id'    => 0,
1403              'link_title' => '',
1404              'type'       => 'both',
1405              'size'       => 80,
1406              'sep'        => '',
1407              'show_role'  => false
1408          ), 'get_topic_author_link' );
1409  
1410          // Default return value
1411          $author_link = '';
1412  
1413          // Used as topic_id
1414          $topic_id = is_numeric( $args )
1415              ? bbp_get_topic_id( $args )
1416              : bbp_get_topic_id( $r['post_id'] );
1417  
1418          // Topic ID is good
1419          if ( ! empty( $topic_id ) ) {
1420  
1421              // Get some useful topic information
1422              $author_url = bbp_get_topic_author_url( $topic_id );
1423              $anonymous  = bbp_is_topic_anonymous( $topic_id );
1424  
1425              // Tweak link title if empty
1426              if ( empty( $r['link_title'] ) ) {
1427                  $author = bbp_get_topic_author_display_name( $topic_id );
1428                  $title  = empty( $anonymous )
1429                      ? esc_attr__( "View %s's profile",  'bbpress' )
1430                      : esc_attr__( "Visit %s's website", 'bbpress' );
1431  
1432                  $link_title = sprintf( $title, $author );
1433  
1434              // Use what was passed if not
1435              } else {
1436                  $link_title = $r['link_title'];
1437              }
1438  
1439              // Setup title and author_links array
1440              $author_links = array();
1441              $link_title   = ! empty( $link_title )
1442                  ? ' title="' . esc_attr( $link_title ) . '"'
1443                  : '';
1444  
1445              // Get avatar (unescaped, because HTML)
1446              if ( ( 'avatar' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1447                  $author_links['avatar'] = bbp_get_topic_author_avatar( $topic_id, $r['size'] );
1448              }
1449  
1450              // Get display name (escaped, because never HTML)
1451              if ( ( 'name' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1452                  $author_links['name'] = esc_html( bbp_get_topic_author_display_name( $topic_id ) );
1453              }
1454  
1455              // Empty array
1456              $links  = array();
1457              $sprint = '<span %1$s>%2$s</span>';
1458  
1459              // Wrap each link
1460              foreach ( $author_links as $link => $link_text ) {
1461                  $link_class = ' class="bbp-author-' . esc_attr( $link ) . '"';
1462                  $links[]    = sprintf( $sprint, $link_class, $link_text );
1463              }
1464  
1465              // Juggle
1466              $author_links = $links;
1467              unset( $links );
1468  
1469              // Filter sections
1470              $sections = apply_filters( 'bbp_get_topic_author_links', $author_links, $r, $args );
1471  
1472              // Assemble sections into author link
1473              $author_link = implode( $r['sep'], $sections );
1474  
1475              // Only wrap in link if profile exists
1476              if ( empty( $anonymous ) && bbp_user_has_profile( bbp_get_topic_author_id( $topic_id ) ) ) {
1477                  $author_link = sprintf( '<a href="%1$s"%2$s%3$s>%4$s</a>', esc_url( $author_url ), $link_title, ' class="bbp-author-link"', $author_link );
1478              }
1479  
1480              // Role is not linked
1481              if ( true === $r['show_role'] ) {
1482                  $author_link .= bbp_get_topic_author_role( array( 'topic_id' => $topic_id ) );
1483              }
1484          }
1485  
1486          // Filter & return
1487          return apply_filters( 'bbp_get_topic_author_link', $author_link, $r, $args );
1488      }
1489  
1490  /**
1491   * Output the author url of the topic
1492   *
1493   * @since 2.0.0 bbPress (r2590)
1494   *
1495   * @param int $topic_id Optional. Topic id
1496   */
1497  function bbp_topic_author_url( $topic_id = 0 ) {
1498      echo esc_url( bbp_get_topic_author_url( $topic_id ) );
1499  }
1500  
1501      /**
1502       * Return the author url of the topic
1503       *
1504       * @since 2.0.0 bbPress (r2590)
1505       *
1506       * @param int $topic_id Optional. Topic id
1507       * @return string Author URL of topic
1508       */
1509  	function bbp_get_topic_author_url( $topic_id = 0 ) {
1510          $topic_id = bbp_get_topic_id( $topic_id );
1511  
1512          // Check for anonymous user or non-existant user
1513          if ( ! bbp_is_topic_anonymous( $topic_id ) && bbp_user_has_profile( bbp_get_topic_author_id( $topic_id ) ) ) {
1514              $author_url = bbp_get_user_profile_url( bbp_get_topic_author_id( $topic_id ) );
1515          } else {
1516              $author_url = get_post_meta( $topic_id, '_bbp_anonymous_website', true );
1517  
1518              // Set empty author_url as empty string
1519              if ( empty( $author_url ) ) {
1520                  $author_url = '';
1521              }
1522          }
1523  
1524          // Filter & return
1525          return apply_filters( 'bbp_get_topic_author_url', $author_url, $topic_id );
1526      }
1527  
1528  /**
1529   * Output the topic author email address
1530   *
1531   * @since 2.0.0 bbPress (r3445)
1532   *
1533   * @param int $topic_id Optional. Reply id
1534   */
1535  function bbp_topic_author_email( $topic_id = 0 ) {
1536      echo bbp_get_topic_author_email( $topic_id );
1537  }
1538      /**
1539       * Return the topic author email address
1540       *
1541       * @since 2.0.0 bbPress (r3445)
1542       *
1543       * @param int $topic_id Optional. Reply id
1544       * @return string Topic author email address
1545       */
1546  	function bbp_get_topic_author_email( $topic_id = 0 ) {
1547          $topic_id = bbp_get_topic_id( $topic_id );
1548  
1549          // Not anonymous user
1550          if ( ! bbp_is_topic_anonymous( $topic_id ) ) {
1551  
1552              // Use topic author email address
1553              $user_id      = bbp_get_topic_author_id( $topic_id );
1554              $user         = get_userdata( $user_id );
1555              $author_email = ! empty( $user->user_email ) ? $user->user_email : '';
1556  
1557          // Anonymous
1558          } else {
1559  
1560              // Get email from post meta
1561              $author_email = get_post_meta( $topic_id, '_bbp_anonymous_email', true );
1562  
1563              // Sanity check for missing email address
1564              if ( empty( $author_email ) ) {
1565                  $author_email = '';
1566              }
1567          }
1568  
1569          // Filter & return
1570          return apply_filters( 'bbp_get_topic_author_email', $author_email, $topic_id );
1571      }
1572  
1573  /**
1574   * Output the topic author role
1575   *
1576   * @since 2.1.0 bbPress (r3860)
1577   *
1578   * @param array $args Optional.
1579   */
1580  function bbp_topic_author_role( $args = array() ) {
1581      echo bbp_get_topic_author_role( $args );
1582  }
1583      /**
1584       * Return the topic author role
1585       *
1586       * @since 2.1.0 bbPress (r3860)
1587       *
1588       * @param array $args Optional.
1589       * @return string topic author role
1590       */
1591  	function bbp_get_topic_author_role( $args = array() ) {
1592  
1593          // Parse arguments against default values
1594          $r = bbp_parse_args( $args, array(
1595              'topic_id' => 0,
1596              'class'    => false,
1597              'before'   => '<div class="bbp-author-role">',
1598              'after'    => '</div>'
1599          ), 'get_topic_author_role' );
1600  
1601          $topic_id = bbp_get_topic_id( $r['topic_id'] );
1602          $role     = bbp_get_user_display_role( bbp_get_topic_author_id( $topic_id ) );
1603  
1604          // Backwards compatibilty with old 'class' argument
1605          if ( ! empty( $r['class'] ) ) {
1606              $author_role = sprintf( '%1$s<div class="%2$s">%3$s</div>%4$s', $r['before'], $r['class'], $role, $r['after'] );
1607  
1608          // Simpler before & after arguments
1609          // https://bbpress.trac.wordpress.org/ticket/2557
1610          } else {
1611              $author_role = $r['before'] . $role . $r['after'];
1612          }
1613  
1614          // Filter & return
1615          return apply_filters( 'bbp_get_topic_author_role', $author_role, $r );
1616      }
1617  
1618  
1619  /**
1620   * Output the title of the forum a topic belongs to
1621   *
1622   * @since 2.0.0 bbPress (r2485)
1623   *
1624   * @param int $topic_id Optional. Topic id
1625   */
1626  function bbp_topic_forum_title( $topic_id = 0 ) {
1627      echo bbp_get_topic_forum_title( $topic_id );
1628  }
1629      /**
1630       * Return the title of the forum a topic belongs to
1631       *
1632       * @since 2.0.0 bbPress (r2485)
1633       *
1634       * @param int $topic_id Optional. Topic id
1635       * @return string Topic forum title
1636       */
1637  	function bbp_get_topic_forum_title( $topic_id = 0 ) {
1638          $topic_id = bbp_get_topic_id( $topic_id );
1639          $forum_id = bbp_get_topic_forum_id( $topic_id );
1640  
1641          // Filter & return
1642          return apply_filters( 'bbp_get_topic_forum', bbp_get_forum_title( $forum_id ), $topic_id, $forum_id );
1643      }
1644  
1645  /**
1646   * Output the forum id a topic belongs to
1647   *
1648   * @since 2.0.0 bbPress (r2491)
1649   *
1650   * @param int $topic_id Optional. Topic id
1651   */
1652  function bbp_topic_forum_id( $topic_id = 0 ) {
1653      echo bbp_get_topic_forum_id( $topic_id );
1654  }
1655      /**
1656       * Return the forum id a topic belongs to
1657       *
1658       * @since 2.0.0 bbPress (r2491)
1659       *
1660       * @param int $topic_id Optional. Topic id
1661       * @return int Topic forum id
1662       */
1663  	function bbp_get_topic_forum_id( $topic_id = 0 ) {
1664          $topic_id = bbp_get_topic_id( $topic_id );
1665          $forum_id = (int) get_post_field( 'post_parent', $topic_id );
1666  
1667          // Meta-data fallback
1668          if ( empty( $forum_id ) ) {
1669              $forum_id = (int) get_post_meta( $topic_id, '_bbp_forum_id', true );
1670          }
1671  
1672          // Filter
1673          if ( ! empty( $forum_id ) ) {
1674              $forum_id = (int) bbp_get_forum_id( $forum_id );
1675          }
1676  
1677          // Filter & return
1678          return (int) apply_filters( 'bbp_get_topic_forum_id', $forum_id, $topic_id );
1679      }
1680  
1681  /**
1682   * Output the topics last active ID
1683   *
1684   * @since 2.0.0 bbPress (r2860)
1685   *
1686   * @param int $topic_id Optional. Forum id
1687   */
1688  function bbp_topic_last_active_id( $topic_id = 0 ) {
1689      echo bbp_get_topic_last_active_id( $topic_id );
1690  }
1691      /**
1692       * Return the topics last active ID
1693       *
1694       * @since 2.0.0 bbPress (r2860)
1695       *
1696       * @param int $topic_id Optional. Forum id
1697       * @return int Forum's last active id
1698       */
1699  	function bbp_get_topic_last_active_id( $topic_id = 0 ) {
1700          $topic_id  = bbp_get_topic_id( $topic_id );
1701          $active_id = (int) get_post_meta( $topic_id, '_bbp_last_active_id', true );
1702  
1703          // Filter & return
1704          return (int) apply_filters( 'bbp_get_topic_last_active_id', $active_id, $topic_id );
1705      }
1706  
1707  /**
1708   * Output the topics last update date/time (aka freshness)
1709   *
1710   * @since 2.0.0 bbPress (r2625)
1711   *
1712   * @param int $topic_id Optional. Topic id
1713   */
1714  function bbp_topic_last_active_time( $topic_id = 0 ) {
1715      echo bbp_get_topic_last_active_time( $topic_id );
1716  }
1717      /**
1718       * Return the topics last update date/time (aka freshness)
1719       *
1720       * @since 2.0.0 bbPress (r2625)
1721       *
1722       * @param int $topic_id Optional. Topic id
1723       * @return string Topic freshness
1724       */
1725  	function bbp_get_topic_last_active_time( $topic_id = 0 ) {
1726          $topic_id = bbp_get_topic_id( $topic_id );
1727  
1728          // Try to get the most accurate freshness time possible
1729          $last_active = get_post_meta( $topic_id, '_bbp_last_active_time', true );
1730          if ( empty( $last_active ) ) {
1731              $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1732              if ( ! empty( $reply_id ) ) {
1733                  $last_active = get_post_field( 'post_date', $reply_id );
1734              } else {
1735                  $last_active = get_post_field( 'post_date', $topic_id );
1736              }
1737          }
1738  
1739          $last_active = ! empty( $last_active ) ? bbp_get_time_since( bbp_convert_date( $last_active ) ) : '';
1740  
1741          // Filter & return
1742          return apply_filters( 'bbp_get_topic_last_active', $last_active, $topic_id );
1743      }
1744  
1745  /** Topic Subscriptions *******************************************************/
1746  
1747  /**
1748   * Output the topic subscription link
1749   *
1750   * @since 2.5.0 bbPress (r5156)
1751   * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1752   */
1753  function bbp_topic_subscription_link( $args = array() ) {
1754      echo bbp_get_topic_subscription_link( $args );
1755  }
1756  
1757      /**
1758       * Get the topic subscription link
1759       *
1760       * A custom wrapper for bbp_get_user_subscribe_link()
1761       *
1762       * @since 2.5.0 bbPress (r5156)
1763       * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1764       */
1765  	function bbp_get_topic_subscription_link( $args = array() ) {
1766  
1767          // Defaults
1768          $retval      = false;
1769          $user_id     = bbp_get_current_user_id();
1770          $redirect_to = bbp_is_subscriptions()
1771              ? bbp_get_subscriptions_permalink( $user_id )
1772              : '';
1773  
1774          // Parse the arguments
1775          $r = bbp_parse_args( $args, array(
1776              'user_id'     => $user_id,
1777              'object_id'   => bbp_get_topic_id(),
1778              'object_type' => 'post',
1779              'before'      => '&nbsp;|&nbsp;',
1780              'after'       => '',
1781              'subscribe'   => esc_html__( 'Subscribe',   'bbpress' ),
1782              'unsubscribe' => esc_html__( 'Unsubscribe', 'bbpress' ),
1783              'redirect_to' => $redirect_to
1784          ), 'get_topic_subscribe_link' );
1785  
1786          // Get the link
1787          $retval = bbp_get_user_subscribe_link( $r );
1788  
1789          // Filter & return
1790          return apply_filters( 'bbp_get_topic_subscribe_link', $retval, $r, $args );
1791      }
1792  
1793  /** Topic Favorites ***********************************************************/
1794  
1795  /**
1796   * Output the topic favorite link
1797   *
1798   * @since 2.5.0 bbPress (r5156)
1799   * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1800   */
1801  function bbp_topic_favorite_link( $args = array() ) {
1802      echo bbp_get_topic_favorite_link( $args );
1803  }
1804  
1805      /**
1806       * Get the forum favorite link
1807       *
1808       * A custom wrapper for bbp_get_user_favorites_link()
1809       *
1810       * @since 2.5.0 bbPress (r5156)
1811       * @since 2.6.0 bbPress (r6308) Add 'redirect_to' support
1812       */
1813  	function bbp_get_topic_favorite_link( $args = array() ) {
1814  
1815          // No link
1816          $retval      = false;
1817          $user_id     = bbp_get_current_user_id();
1818          $redirect_to = bbp_is_favorites()
1819              ? bbp_get_favorites_permalink( $user_id )
1820              : '';
1821  
1822          // Parse the arguments
1823          $r = bbp_parse_args( $args, array(
1824              'user_id'     => $user_id,
1825              'object_id'   => bbp_get_topic_id(),
1826              'object_type' => 'post',
1827              'before'      => '',
1828              'after'       => '',
1829              'favorite'    => esc_html__( 'Favorite',   'bbpress' ),
1830              'favorited'   => esc_html__( 'Unfavorite', 'bbpress' ),
1831              'redirect_to' => $redirect_to
1832          ), 'get_topic_favorite_link' );
1833  
1834          // Get the link
1835          $retval = bbp_get_user_favorites_link( $r );
1836  
1837          // Filter & return
1838          return apply_filters( 'bbp_get_topic_favorite_link', $retval, $r, $args );
1839      }
1840  
1841  /** Topic Last Reply **********************************************************/
1842  
1843  /**
1844   * Output the id of the topics last reply
1845   *
1846   * @since 2.0.0 bbPress (r2625)
1847   *
1848   * @param int $topic_id Optional. Topic id
1849   */
1850  function bbp_topic_last_reply_id( $topic_id = 0 ) {
1851      echo bbp_get_topic_last_reply_id( $topic_id );
1852  }
1853      /**
1854       * Return the id of the topics last reply
1855       *
1856       * @since 2.0.0 bbPress (r2625)
1857       *
1858       * @param int $topic_id Optional. Topic id
1859       * @return int Topic last reply id
1860       */
1861  	function bbp_get_topic_last_reply_id( $topic_id = 0 ) {
1862          $topic_id = bbp_get_topic_id( $topic_id );
1863          $reply_id = (int) get_post_meta( $topic_id, '_bbp_last_reply_id', true );
1864  
1865          // Filter & return
1866          return (int) apply_filters( 'bbp_get_topic_last_reply_id', $reply_id, $topic_id );
1867      }
1868  
1869  /**
1870   * Output the title of the last reply inside a topic
1871   *
1872   * @since 2.0.0 bbPress (r2753)
1873   *
1874   * @param int $topic_id Optional. Topic id
1875   */
1876  function bbp_topic_last_reply_title( $topic_id = 0 ) {
1877      echo bbp_get_topic_last_reply_title( $topic_id );
1878  }
1879      /**
1880       * Return the title of the last reply inside a topic
1881       *
1882       * @since 2.0.0 bbPress (r2753)
1883       * @since 2.6.0 bbPress https://bbpress.trac.wordpress.org/ticket/3039
1884       *
1885       * @param int $topic_id Optional. Topic id
1886       * @return string Topic last reply title
1887       */
1888  	function bbp_get_topic_last_reply_title( $topic_id = 0 ) {
1889          $topic_id = bbp_get_topic_id( $topic_id );
1890          $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1891          $retval   = bbp_get_reply_title( $reply_id );
1892  
1893          // Misspelled. Use 'bbp_get_topic_last_reply_title' hook instead.
1894          $retval = apply_filters( 'bbp_get_topic_last_topic_title', $retval, $topic_id, $reply_id );
1895  
1896          // Filter & return
1897          return apply_filters( 'bbp_get_topic_last_reply_title', $retval, $topic_id, $reply_id );
1898      }
1899  
1900  /**
1901   * Output the link to the last reply in a topic
1902   *
1903   * @since 2.0.0 bbPress (r2464)
1904   *
1905   * @param int $topic_id Optional. Topic id
1906   */
1907  function bbp_topic_last_reply_permalink( $topic_id = 0 ) {
1908      echo esc_url( bbp_get_topic_last_reply_permalink( $topic_id ) );
1909  }
1910      /**
1911       * Return the link to the last reply in a topic
1912       *
1913       * @since 2.0.0 bbPress (r2464)
1914       *
1915       * @param int $topic_id Optional. Topic id
1916       * @return string Permanent link to the reply
1917       */
1918  	function bbp_get_topic_last_reply_permalink( $topic_id = 0 ) {
1919          $topic_id = bbp_get_topic_id( $topic_id );
1920          $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1921          $retval   = bbp_get_reply_permalink( $reply_id );
1922  
1923          // Filter & return
1924          return apply_filters( 'bbp_get_topic_last_reply_permalink', $retval, $topic_id, $reply_id );
1925      }
1926  
1927  /**
1928   * Output the link to the last reply in a topic
1929   *
1930   * @since 2.0.0 bbPress (r2683)
1931   *
1932   * @param int $topic_id Optional. Topic id
1933   */
1934  function bbp_topic_last_reply_url( $topic_id = 0 ) {
1935      echo esc_url( bbp_get_topic_last_reply_url( $topic_id ) );
1936  }
1937      /**
1938       * Return the link to the last reply in a topic
1939       *
1940       * @since 2.0.0 bbPress (r2683)
1941       *
1942       * @param int $topic_id Optional. Topic id
1943       * @return string Topic last reply url
1944       */
1945  	function bbp_get_topic_last_reply_url( $topic_id = 0 ) {
1946          $topic_id = bbp_get_topic_id( $topic_id );
1947          $reply_id = bbp_get_topic_last_reply_id( $topic_id );
1948  
1949          if ( ! empty( $reply_id ) && ( $reply_id !== $topic_id ) ) {
1950              $reply_url = bbp_get_reply_url( $reply_id );
1951          } else {
1952              $reply_url = bbp_get_topic_permalink( $topic_id );
1953          }
1954  
1955          // Filter & return
1956          return apply_filters( 'bbp_get_topic_last_reply_url', $reply_url, $topic_id, $reply_id );
1957      }
1958  
1959  /**
1960   * Output link to the most recent activity inside a topic, complete with link
1961   * attributes and content.
1962   *
1963   * @since 2.0.0 bbPress (r2625)
1964   *
1965   * @param int $topic_id Optional. Topic id
1966   */
1967  function bbp_topic_freshness_link( $topic_id = 0 ) {
1968      echo bbp_get_topic_freshness_link( $topic_id );
1969  }
1970      /**
1971       * Returns link to the most recent activity inside a topic, complete
1972       * with link attributes and content.
1973       *
1974       * @since 2.0.0 bbPress (r2625)
1975       *
1976       * @param int $topic_id Optional. Topic id
1977       * @return string Topic freshness link
1978       */
1979  	function bbp_get_topic_freshness_link( $topic_id = 0 ) {
1980          $topic_id   = bbp_get_topic_id( $topic_id );
1981          $link_url   = bbp_get_topic_last_reply_url( $topic_id );
1982          $title      = bbp_get_topic_last_reply_title( $topic_id );
1983          $time_since = bbp_get_topic_last_active_time( $topic_id );
1984  
1985          if ( ! empty( $time_since ) ) {
1986              $anchor = '<a href="' . esc_url( $link_url ) . '" title="' . esc_attr( $title ) . '">' . esc_html( $time_since ) . '</a>';
1987          } else {
1988              $anchor = esc_html__( 'No Replies', 'bbpress' );
1989          }
1990  
1991          // Filter & return
1992          return apply_filters( 'bbp_get_topic_freshness_link', $anchor, $topic_id, $time_since, $link_url, $title );
1993      }
1994  
1995  /**
1996   * Output the replies link of the topic
1997   *
1998   * @since 2.0.0 bbPress (r2740)
1999   *
2000   * @param int $topic_id Optional. Topic id
2001   */
2002  function bbp_topic_replies_link( $topic_id = 0 ) {
2003      echo bbp_get_topic_replies_link( $topic_id );
2004  }
2005  
2006      /**
2007       * Return the replies link of the topic
2008       *
2009       * @since 2.0.0 bbPress (r2740)
2010       *
2011       * @param int $topic_id Optional. Topic id
2012       */
2013  	function bbp_get_topic_replies_link( $topic_id = 0 ) {
2014          $topic_id = bbp_get_topic_id( $topic_id );
2015          $link     = bbp_get_topic_permalink( $topic_id );
2016          $replies  = sprintf( _n( '%s reply', '%s replies', bbp_get_topic_reply_count( $topic_id, true ), 'bbpress' ), bbp_get_topic_reply_count( $topic_id, false ) );
2017  
2018          // First link never has view=all
2019          $retval = bbp_get_view_all( 'edit_others_replies' )
2020              ? "<a href='" . esc_url( bbp_remove_view_all( $link ) ) . "'>" . esc_html( $replies ) . '</a>'
2021              : $replies;
2022  
2023          // Any deleted replies?
2024          $deleted_int = bbp_get_topic_reply_count_hidden( $topic_id, true  );
2025  
2026          // This topic has hidden replies
2027          if ( ! empty( $deleted_int ) && current_user_can( 'edit_others_replies' ) ) {
2028  
2029              // Hidden replies
2030              $deleted_num = bbp_get_topic_reply_count_hidden( $topic_id, false );
2031              $extra       = ' ' . sprintf( _n( '(+%s hidden)', '(+%s hidden)', $deleted_int, 'bbpress' ), $deleted_num );
2032  
2033              // Hidden link
2034              $retval .= ! bbp_get_view_all( 'edit_others_replies' )
2035                  ? " <a href='" . esc_url( bbp_add_view_all( $link, true ) ) . "'>" . esc_html( $extra ) . '</a>'
2036                  : " {$extra}";
2037          }
2038  
2039          // Filter & return
2040          return apply_filters( 'bbp_get_topic_replies_link', $retval, $topic_id );
2041      }
2042  
2043  /**
2044   * Output total reply count of a topic
2045   *
2046   * @since 2.0.0 bbPress (r2485)
2047   *
2048   * @param int $topic_id Optional. Topic id
2049   * @param boolean $integer Optional. Whether or not to format the result
2050   */
2051  function bbp_topic_reply_count( $topic_id = 0, $integer = false ) {
2052      echo bbp_get_topic_reply_count( $topic_id, $integer );
2053  }
2054      /**
2055       * Return total reply count of a topic
2056       *
2057       * @since 2.0.0 bbPress (r2485)
2058       *
2059       * @param int $topic_id Optional. Topic id
2060       * @param boolean $integer Optional. Whether or not to format the result
2061       * @return int Reply count
2062       */
2063  	function bbp_get_topic_reply_count( $topic_id = 0, $integer = false ) {
2064          $topic_id = bbp_get_topic_id( $topic_id );
2065          $replies  = (int) get_post_meta( $topic_id, '_bbp_reply_count', true );
2066          $filter   = ( true === $integer )
2067              ? 'bbp_get_topic_reply_count_int'
2068              : 'bbp_get_topic_reply_count';
2069  
2070          return apply_filters( $filter, $replies, $topic_id );
2071      }
2072  
2073  /**
2074   * Output total post count of a topic
2075   *
2076   * @since 2.0.0 bbPress (r2954)
2077   *
2078   * @param int $topic_id Optional. Topic id
2079   * @param boolean $integer Optional. Whether or not to format the result
2080   */
2081  function bbp_topic_post_count( $topic_id = 0, $integer = false ) {
2082      echo bbp_get_topic_post_count( $topic_id, $integer );
2083  }
2084      /**
2085       * Return total post count of a topic
2086       *
2087       * @since 2.0.0 bbPress (r2954)
2088       *
2089       * @param int $topic_id Optional. Topic id
2090       * @param boolean $integer Optional. Whether or not to format the result
2091       * @return int Post count
2092       */
2093  	function bbp_get_topic_post_count( $topic_id = 0, $integer = false ) {
2094          $topic_id = bbp_get_topic_id( $topic_id );
2095          $replies  = ( (int) get_post_meta( $topic_id, '_bbp_reply_count', true ) ) + 1;
2096          $filter   = ( true === $integer )
2097              ? 'bbp_get_topic_post_count_int'
2098              : 'bbp_get_topic_post_count';
2099  
2100          return apply_filters( $filter, $replies, $topic_id );
2101      }
2102  
2103  /**
2104   * Output total hidden reply count of a topic (hidden includes trashed and
2105   * spammed replies)
2106   *
2107   * @since 2.0.0 bbPress (r2740)
2108   *
2109   * @param int $topic_id Optional. Topic id
2110   * @param boolean $integer Optional. Whether or not to format the result
2111   */
2112  function bbp_topic_reply_count_hidden( $topic_id = 0, $integer = false ) {
2113      echo bbp_get_topic_reply_count_hidden( $topic_id, $integer );
2114  }
2115      /**
2116       * Return total hidden reply count of a topic (hidden includes trashed
2117       * and spammed replies)
2118       *
2119       * @since 2.0.0 bbPress (r2740)
2120       *
2121       * @param int $topic_id Optional. Topic id
2122       * @param boolean $integer Optional. Whether or not to format the result
2123       * @return int Topic hidden reply count
2124       */
2125  	function bbp_get_topic_reply_count_hidden( $topic_id = 0, $integer = false ) {
2126          $topic_id = bbp_get_topic_id( $topic_id );
2127          $replies  = (int) get_post_meta( $topic_id, '_bbp_reply_count_hidden', true );
2128          $filter   = ( true === $integer )
2129              ? 'bbp_get_topic_reply_count_hidden_int'
2130              : 'bbp_get_topic_reply_count_hidden';
2131  
2132          return apply_filters( $filter, $replies, $topic_id );
2133      }
2134  
2135  /**
2136   * Output total voice count of a topic
2137   *
2138   * @since 2.0.0 bbPress (r2567)
2139   *
2140   * @param int $topic_id Optional. Topic id
2141   */
2142  function bbp_topic_voice_count( $topic_id = 0, $integer = false ) {
2143      echo bbp_get_topic_voice_count( $topic_id, $integer );
2144  }
2145      /**
2146       * Return total voice count of a topic
2147       *
2148       * @since 2.0.0 bbPress (r2567)
2149       *
2150       * @param int $topic_id Optional. Topic id
2151       * @return int Voice count of the topic
2152       */
2153  	function bbp_get_topic_voice_count( $topic_id = 0, $integer = false ) {
2154          $topic_id = bbp_get_topic_id( $topic_id );
2155          $voices   = (int) get_post_meta( $topic_id, '_bbp_voice_count', true );
2156          $filter   = ( true === $integer )
2157              ? 'bbp_get_topic_voice_count_int'
2158              : 'bbp_get_topic_voice_count';
2159  
2160          return apply_filters( $filter, $voices, $topic_id );
2161      }
2162  
2163  /**
2164   * Output a the tags of a topic
2165   *
2166   * @since 2.0.0 bbPress (r2688)
2167   *
2168   * @param int $topic_id Optional. Topic id
2169   * @param array $args See {@link bbp_get_topic_tag_list()}
2170   */
2171  function bbp_topic_tag_list( $topic_id = 0, $args = array() ) {
2172      echo bbp_get_topic_tag_list( $topic_id, $args );
2173  }
2174      /**
2175       * Return the tags of a topic
2176       *
2177       * @since 2.0.0 bbPress (r2688)
2178       *
2179       * @param int $topic_id Optional. Topic id
2180       * @param array $args This function supports these arguments:
2181       *  - before: Before the tag list
2182       *  - sep: Tag separator
2183       *  - after: After the tag list
2184       * @return string Tag list of the topic
2185       */
2186  	function bbp_get_topic_tag_list( $topic_id = 0, $args = array() ) {
2187  
2188          // Bail if topic-tags are off
2189          if ( ! bbp_allow_topic_tags() ) {
2190              return '';
2191          }
2192  
2193          // Parse arguments against default values
2194          $r = bbp_parse_args( $args, array(
2195              'before' => '<div class="bbp-topic-tags"><p>' . esc_html__( 'Tagged:', 'bbpress' ) . '&nbsp;',
2196              'sep'    => ', ',
2197              'after'  => '</p></div>',
2198              'none'   => ''
2199          ), 'get_topic_tag_list' );
2200  
2201          $topic_id = bbp_get_topic_id( $topic_id );
2202  
2203          // Topic is spammed, so display pre-spam terms
2204          if ( bbp_is_topic_spam( $topic_id ) ) {
2205  
2206              // Get pre-spam terms
2207              $terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
2208  
2209              // If terms exist, implode them and compile the return value
2210              if ( ! empty( $terms ) ) {
2211                  $terms = $r['before'] . implode( $r['sep'], $terms ) . $r['after'];
2212              }
2213  
2214          // Topic is not spam so display a clickable term list
2215          } else {
2216              $terms = get_the_term_list( $topic_id, bbp_get_topic_tag_tax_id(), $r['before'], $r['sep'], $r['after'] );
2217          }
2218  
2219          // No terms so return none string
2220          if ( ! empty( $terms ) ) {
2221              $retval = $terms;
2222          } else {
2223              $retval = $r['none'];
2224          }
2225  
2226          return $retval;
2227      }
2228  
2229  /**
2230   * Output the row class of a topic
2231   *
2232   * @since 2.0.0 bbPress (r2667)
2233   *
2234   * @param int $topic_id Optional. Topic id
2235   * @param array Extra classes you can pass when calling this function
2236   */
2237  function bbp_topic_class( $topic_id = 0, $classes = array() ) {
2238      echo bbp_get_topic_class( $topic_id, $classes );
2239  }
2240      /**
2241       * Return the row class of a topic
2242       *
2243       * @since 2.0.0 bbPress (r2667)
2244       *
2245       * @param int $topic_id Optional. Topic id
2246       * @param array Extra classes you can pass when calling this function
2247       * @return string Row class of a topic
2248       */
2249  	function bbp_get_topic_class( $topic_id = 0, $classes = array() ) {
2250          $bbp       = bbpress();
2251          $topic_id  = bbp_get_topic_id( $topic_id );
2252          $forum_id  = bbp_get_topic_forum_id( $topic_id );
2253          $author_id = bbp_get_topic_author_id( $topic_id );
2254          $classes   = array_filter( (array) $classes );
2255          $count     = isset( $bbp->topic_query->current_post )
2256              ? (int) $bbp->topic_query->current_post
2257              : 1;
2258  
2259          //  Stripes
2260          $even_odd = ( $count % 2 )
2261              ? 'even'
2262              : 'odd';
2263  
2264          // Forum moderator replied to topic
2265          $forum_moderator = ( bbp_is_user_forum_moderator( $author_id, $forum_id ) === $author_id )
2266              ? 'forum-mod'
2267              : '';
2268  
2269          // Is this topic a sticky?
2270          $sticky = bbp_is_topic_sticky( $topic_id, false )
2271              ? 'sticky'
2272              : '';
2273  
2274          // Is this topic a super-sticky?
2275          $super_sticky = bbp_is_topic_super_sticky( $topic_id  )
2276              ? 'super-sticky'
2277              : '';
2278  
2279          // Get topic classes
2280          $topic_classes = array(
2281              'loop-item-'        . $count,
2282              'user-id-'          . $author_id,
2283              'bbp-parent-forum-' . $forum_id,
2284              $even_odd,
2285              $forum_moderator,
2286              $sticky,
2287              $super_sticky
2288          );
2289  
2290          // Run the topic classes through the post-class filters, which also
2291          // handles the escaping of each individual class.
2292          $post_classes = get_post_class( array_merge( $classes, $topic_classes ), $topic_id );
2293  
2294          // Filter
2295          $new_classes  = apply_filters( 'bbp_get_topic_class', $post_classes, $topic_id, $classes );
2296  
2297          // Return
2298          return 'class="' . implode( ' ', $new_classes ) . '"';
2299      }
2300  
2301  /** Topic Admin Links *********************************************************/
2302  
2303  /**
2304   * Output admin links for topic
2305   *
2306   * @param array $args See {@link bbp_get_topic_admin_links()}
2307   */
2308  function bbp_topic_admin_links( $args = array() ) {
2309      echo bbp_get_topic_admin_links( $args );
2310  }
2311      /**
2312       * Return admin links for topic.
2313       *
2314       * Move topic functionality is handled by the edit topic page.
2315       *
2316       * @param array $args This function supports these arguments:
2317       *  - id: Optional. Topic id
2318       *  - before: Before the links
2319       *  - after: After the links
2320       *  - sep: Links separator
2321       *  - links: Topic admin links array
2322       * @return string Topic admin links
2323       */
2324  	function bbp_get_topic_admin_links( $args = array() ) {
2325  
2326          // Parse arguments against default values
2327          $r = bbp_parse_args( $args, array(
2328              'id'     => bbp_get_topic_id(),
2329              'before' => '<span class="bbp-admin-links">',
2330              'after'  => '</span>',
2331              'sep'    => ' | ',
2332              'links'  => array()
2333          ), 'get_topic_admin_links' );
2334  
2335          if ( empty( $r['links'] ) ) {
2336              $r['links'] = apply_filters( 'bbp_topic_admin_links', array(
2337                  'edit'    => bbp_get_topic_edit_link   ( $r ),
2338                  'merge'   => bbp_get_topic_merge_link  ( $r ),
2339                  'close'   => bbp_get_topic_close_link  ( $r ),
2340                  'stick'   => bbp_get_topic_stick_link  ( $r ),
2341                  'trash'   => bbp_get_topic_trash_link  ( $r ),
2342                  'spam'    => bbp_get_topic_spam_link   ( $r ),
2343                  'approve' => bbp_get_topic_approve_link( $r ),
2344                  'reply'   => bbp_get_topic_reply_link  ( $r )
2345              ), $r['id'] );
2346          }
2347  
2348          // See if links need to be unset
2349          $topic_status = bbp_get_topic_status( $r['id'] );
2350          if ( in_array( $topic_status, bbp_get_non_public_topic_statuses(), true ) ) {
2351  
2352              // Close link shouldn't be visible on trashed/spammed/pending topics
2353              unset( $r['links']['close'] );
2354  
2355              // Spam link shouldn't be visible on trashed topics
2356              if ( bbp_get_trash_status_id() === $topic_status ) {
2357                  unset( $r['links']['spam'] );
2358  
2359              // Trash link shouldn't be visible on spam topics
2360              } elseif ( bbp_get_spam_status_id() === $topic_status ) {
2361                  unset( $r['links']['trash'] );
2362              }
2363          }
2364  
2365          // Process the admin links
2366          $links  = implode( $r['sep'], array_filter( $r['links'] ) );
2367          $retval = $r['before'] . $links . $r['after'];
2368  
2369          // Filter & return
2370          return apply_filters( 'bbp_get_topic_admin_links', $retval, $r, $args );
2371      }
2372  
2373  /**
2374   * Output the edit link of the topic
2375   *
2376   * @since 2.0.0 bbPress (r2727)
2377   *
2378   * @param array $args See {@link bbp_get_topic_edit_link()}
2379   */
2380  function bbp_topic_edit_link( $args = array() ) {
2381      echo bbp_get_topic_edit_link( $args );
2382  }
2383  
2384      /**
2385       * Return the edit link of the topic
2386       *
2387       * @since 2.0.0 bbPress (r2727)
2388       *
2389       * @param array $args This function supports these args:
2390       *  - id: Optional. Topic id
2391       *  - link_before: Before the link
2392       *  - link_after: After the link
2393       *  - edit_text: Edit text
2394       * @return string Topic edit link
2395       */
2396  	function bbp_get_topic_edit_link( $args = array() ) {
2397  
2398          // Parse arguments against default values
2399          $r = bbp_parse_args( $args, array(
2400              'id'           => 0,
2401              'link_before'  => '',
2402              'link_after'   => '',
2403              'edit_text'    => esc_html__( 'Edit', 'bbpress' )
2404          ), 'get_topic_edit_link' );
2405  
2406          // Get the topic
2407          $topic = bbp_get_topic( $r['id'] );
2408  
2409          // Bypass check if user has caps
2410          if ( ! current_user_can( 'edit_others_topics' ) ) {
2411  
2412              // User cannot edit or it is past the lock time
2413              if ( empty( $topic ) || ! current_user_can( 'edit_topic', $topic->ID ) || bbp_past_edit_lock( $topic->post_date_gmt ) ) {
2414                  return;
2415              }
2416          }
2417  
2418          // Get uri
2419          $uri = bbp_get_topic_edit_url( $topic->ID );
2420  
2421          // Bail if no uri
2422          if ( empty( $uri ) ) {
2423              return;
2424          }
2425  
2426          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-edit-link">' . $r['edit_text'] . '</a>' . $r['link_after'];
2427  
2428          // Filter & return
2429          return apply_filters( 'bbp_get_topic_edit_link', $retval, $r, $args );
2430      }
2431  
2432  /**
2433   * Output URL to the topic edit page
2434   *
2435   * @since 2.0.0 bbPress (r2753)
2436   *
2437   * @param int $topic_id Optional. Topic id
2438   */
2439  function bbp_topic_edit_url( $topic_id = 0 ) {
2440      echo esc_url( bbp_get_topic_edit_url( $topic_id ) );
2441  }
2442      /**
2443       * Return URL to the topic edit page
2444       *
2445       * @since 2.0.0 bbPress (r2753)
2446       *
2447       * @param int $topic_id Optional. Topic id
2448       * @return string Topic edit url
2449       */
2450  	function bbp_get_topic_edit_url( $topic_id = 0 ) {
2451  
2452          $topic = bbp_get_topic( $topic_id );
2453          if ( empty( $topic ) ) {
2454              return;
2455          }
2456  
2457          // Remove view=all link from edit
2458          $topic_link = bbp_remove_view_all( bbp_get_topic_permalink( $topic_id ) );
2459  
2460          // Pretty permalinks, previously used `bbp_use_pretty_urls()`
2461          // https://bbpress.trac.wordpress.org/ticket/3054
2462          if ( false === strpos( $topic_link, '?' ) ) {
2463              $url = trailingslashit( $topic_link ) . bbp_get_edit_slug();
2464              $url = user_trailingslashit( $url );
2465  
2466          // Unpretty permalinks
2467          } else {
2468              $url = add_query_arg( array(
2469                  bbp_get_topic_post_type() => $topic->post_name,
2470                  bbp_get_edit_rewrite_id() => '1'
2471              ), $topic_link );
2472          }
2473  
2474          // Maybe add view=all
2475          $url = bbp_add_view_all( $url );
2476  
2477          // Filter & return
2478          return apply_filters( 'bbp_get_topic_edit_url', $url, $topic_id );
2479      }
2480  
2481  /**
2482   * Output the trash link of the topic
2483   *
2484   * @since 2.0.0 bbPress (r2727)
2485   *
2486   * @param array $args See {@link bbp_get_topic_trash_link()}
2487   */
2488  function bbp_topic_trash_link( $args = array() ) {
2489      echo bbp_get_topic_trash_link( $args );
2490  }
2491  
2492      /**
2493       * Return the trash link of the topic
2494       *
2495       * @since 2.0.0 bbPress (r2727)
2496       *
2497       * @param array $args This function supports these args:
2498       *  - id: Optional. Topic id
2499       *  - link_before: Before the link
2500       *  - link_after: After the link
2501       *  - sep: Links separator
2502       *  - trash_text: Trash text
2503       *  - restore_text: Restore text
2504       *  - delete_text: Delete text
2505       * @return string Topic trash link
2506       */
2507  	function bbp_get_topic_trash_link( $args = array() ) {
2508  
2509          // Parse arguments against default values
2510          $r = bbp_parse_args( $args, array(
2511              'id'           => 0,
2512              'link_before'  => '',
2513              'link_after'   => '',
2514              'sep'          => ' | ',
2515              'trash_text'   => esc_html__( 'Trash',   'bbpress' ),
2516              'restore_text' => esc_html__( 'Restore', 'bbpress' ),
2517              'delete_text'  => esc_html__( 'Delete',  'bbpress' )
2518          ), 'get_topic_trash_link' );
2519  
2520          // Get topic
2521          $topic = bbp_get_topic( $r['id'] );
2522  
2523          // Bail if no topic or current user cannot delete
2524          if ( empty( $topic ) || ! current_user_can( 'delete_topic', $topic->ID ) ) {
2525              return;
2526          }
2527  
2528          $actions    = array();
2529          $trash_days = bbp_get_trash_days( bbp_get_topic_post_type() );
2530  
2531          if ( bbp_is_topic_trash( $topic->ID ) ) {
2532              $actions['untrash'] = '<a title="' . esc_attr__( 'Restore this item from the Trash', 'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'untrash', 'topic_id' => $topic->ID ) ), 'untrash-' . $topic->post_type . '_' . $topic->ID ) ) . '" class="bbp-topic-restore-link">' . $r['restore_text'] . '</a>';
2533          } elseif ( ! empty( $trash_days ) ) {
2534              $actions['trash']   = '<a title="' . esc_attr__( 'Move this item to the Trash',      'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'trash',   'topic_id' => $topic->ID ) ), 'trash-'   . $topic->post_type . '_' . $topic->ID ) ) . '" class="bbp-topic-trash-link">'   . $r['trash_text']   . '</a>';
2535          }
2536  
2537          if ( bbp_is_topic_trash( $topic->ID ) || empty( $trash_days ) ) {
2538              $actions['delete']  = '<a title="' . esc_attr__( 'Delete this item permanently',     'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_topic_trash', 'sub_action' => 'delete',  'topic_id' => $topic->ID ) ), 'delete-'  . $topic->post_type . '_' . $topic->ID ) ) . '" onclick="return confirm(\'' . esc_js( esc_html__( 'Are you sure you want to delete that permanently?', 'bbpress' ) ) . '\' );" class="bbp-topic-delete-link">' . $r['delete_text'] . '</a>';
2539          }
2540  
2541          // Process the admin links
2542          $retval = $r['link_before'] . implode( $r['sep'], $actions ) . $r['link_after'];
2543  
2544          // Filter & return
2545          return apply_filters( 'bbp_get_topic_trash_link', $retval, $r, $args );
2546      }
2547  
2548  /**
2549   * Output the close link of the topic
2550   *
2551   * @since 2.0.0 bbPress (r2727)
2552   *
2553   * @param array $args See {@link bbp_get_topic_close_link()}
2554   */
2555  function bbp_topic_close_link( $args = array() ) {
2556      echo bbp_get_topic_close_link( $args );
2557  }
2558  
2559      /**
2560       * Return the close link of the topic
2561       *
2562       * @since 2.0.0 bbPress (r2727)
2563       *
2564       * @param array $args This function supports these args:
2565       *  - id: Optional. Topic id
2566       *  - link_before: Before the link
2567       *  - link_after: After the link
2568       *  - close_text: Close text
2569       *  - open_text: Open text
2570       * @return string Topic close link
2571       */
2572  	function bbp_get_topic_close_link( $args = array() ) {
2573  
2574          // Parse arguments against default values
2575          $r = bbp_parse_args( $args, array(
2576              'id'          => 0,
2577              'link_before' => '',
2578              'link_after'  => '',
2579              'sep'         => ' | ',
2580              'close_text'  => esc_html_x( 'Close', 'Close the topic', 'bbpress' ),
2581              'open_text'   => esc_html_x( 'Open',  'Open the topic', 'bbpress' )
2582          ), 'get_topic_close_link' );
2583  
2584          // Get topic
2585          $topic = bbp_get_topic( $r['id'] );
2586  
2587          // Bail if no topic or current user cannot moderate
2588          if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2589              return;
2590          }
2591  
2592          $display = bbp_is_topic_open( $topic->ID ) ? $r['close_text'] : $r['open_text'];
2593          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_topic_close', 'topic_id' => $topic->ID ) );
2594          $uri     = wp_nonce_url( $uri, 'close-topic_' . $topic->ID );
2595          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-close-link">' . $display . '</a>' . $r['link_after'];
2596  
2597          // Filter & return
2598          return apply_filters( 'bbp_get_topic_close_link', $retval, $r, $args );
2599      }
2600  
2601  /**
2602   * Output the approve link of the topic
2603   *
2604   * @since 2.6.0 bbPress (r5504)
2605   *
2606   * @param array $args See {@link bbp_get_topic_approve_link()}
2607   */
2608  function bbp_topic_approve_link( $args = array() ) {
2609      echo bbp_get_topic_approve_link( $args );
2610  }
2611  
2612      /**
2613       * Return the approve link of the topic
2614       *
2615       * @since 2.6.0 bbPress (r5504)
2616       *
2617       * @param array $args This function supports these args:
2618       *  - id: Optional. Topic id
2619       *  - link_before: Before the link
2620       *  - link_after: After the link
2621       *  - sep: Separator between links
2622       *  - approve_text: Approve text
2623       *  - unapprove_text: Unapprove text
2624       * @return string Topic approve link
2625       */
2626  	function bbp_get_topic_approve_link( $args = array() ) {
2627  
2628          // Parse arguments against default values
2629          $r = bbp_parse_args( $args, array(
2630              'id'             => 0,
2631              'link_before'    => '',
2632              'link_after'     => '',
2633              'sep'            => ' | ',
2634              'approve_text'   => esc_html_x( 'Approve',   'Approve the topic', 'bbpress' ),
2635              'unapprove_text' => esc_html_x( 'Unapprove', 'Unapprove the topic', 'bbpress' )
2636          ), 'get_topic_approve_link' );
2637  
2638          // Get topic
2639          $topic = bbp_get_topic( $r['id'] );
2640  
2641          // Bail if no topic or current user cannot moderate
2642          if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2643              return;
2644          }
2645  
2646          $display = bbp_is_topic_pending( $topic->ID ) ? $r['approve_text'] : $r['unapprove_text'];
2647          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_topic_approve', 'topic_id' => $topic->ID ) );
2648          $uri     = wp_nonce_url( $uri, 'approve-topic_' . $topic->ID );
2649          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-approve-link">' . $display . '</a>' . $r['link_after'];
2650  
2651          // Filter & return
2652          return apply_filters( 'bbp_get_topic_approve_link', $retval, $r, $args );
2653      }
2654  
2655  /**
2656   * Output the stick link of the topic
2657   *
2658   * @since 2.0.0 bbPress (r2754)
2659   *
2660   * @param array $args See {@link bbp_get_topic_stick_link()}
2661   */
2662  function bbp_topic_stick_link( $args = array() ) {
2663      echo bbp_get_topic_stick_link( $args );
2664  }
2665  
2666      /**
2667       * Return the stick link of the topic
2668       *
2669       * @since 2.0.0 bbPress (r2754)
2670       *
2671       * @param array $args This function supports these args:
2672       *  - id: Optional. Topic id
2673       *  - link_before: Before the link
2674       *  - link_after: After the link
2675       *  - stick_text: Stick text
2676       *  - unstick_text: Unstick text
2677       *  - super_text: Stick to front text
2678       *
2679       * @return string Topic stick link
2680       */
2681  	function bbp_get_topic_stick_link( $args = array() ) {
2682  
2683          // Parse arguments against default values
2684          $r = bbp_parse_args( $args, array(
2685              'id'           => 0,
2686              'link_before'  => '',
2687              'link_after'   => '',
2688              'stick_text'   => esc_html__( 'Stick',      'bbpress' ),
2689              'unstick_text' => esc_html__( 'Unstick',    'bbpress' ),
2690              'super_text'   => esc_html__( '(to front)', 'bbpress' ),
2691          ), 'get_topic_stick_link' );
2692  
2693          // Get topic
2694          $topic = bbp_get_topic( $r['id'] );
2695  
2696          // Bail if no topic or current user cannot moderate
2697          if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2698              return;
2699          }
2700  
2701          $is_sticky = bbp_is_topic_sticky( $topic->ID );
2702  
2703          $stick_uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_stick', 'topic_id' => $topic->ID ) );
2704          $stick_uri = wp_nonce_url( $stick_uri, 'stick-topic_' . $topic->ID );
2705  
2706          $stick_display = ( true === $is_sticky ) ? $r['unstick_text'] : $r['stick_text'];
2707          $stick_display = '<a href="' . esc_url( $stick_uri ) . '" class="bbp-topic-sticky-link">' . $stick_display . '</a>';
2708  
2709          if ( empty( $is_sticky ) ) {
2710              $super_uri = add_query_arg( array( 'action' => 'bbp_toggle_topic_stick', 'topic_id' => $topic->ID, 'super' => 1 ) );
2711              $super_uri = wp_nonce_url( $super_uri, 'stick-topic_' . $topic->ID );
2712  
2713              $super_display = ' <a href="' . esc_url( $super_uri ) . '" class="bbp-topic-super-sticky-link">' . $r['super_text'] . '</a>';
2714          } else {
2715              $super_display = '';
2716          }
2717  
2718          // Combine the HTML into 1 string
2719          $retval = $r['link_before'] . $stick_display . $super_display . $r['link_after'];
2720  
2721          // Filter & return
2722          return apply_filters( 'bbp_get_topic_stick_link', $retval, $r, $args );
2723      }
2724  
2725  /**
2726   * Output the merge link of the topic
2727   *
2728   * @since 2.0.0 bbPress (r2756)
2729   *
2730   * @param array $args
2731   */
2732  function bbp_topic_merge_link( $args = array() ) {
2733      echo bbp_get_topic_merge_link( $args );
2734  }
2735  
2736      /**
2737       * Return the merge link of the topic
2738       *
2739       * @since 2.0.0 bbPress (r2756)
2740       *
2741       * @param array $args This function supports these args:
2742       *  - id: Optional. Topic id
2743       *  - link_before: Before the link
2744       *  - link_after: After the link
2745       *  - merge_text: Merge text
2746       *
2747       * @return string Topic merge link
2748       */
2749  	function bbp_get_topic_merge_link( $args = array() ) {
2750  
2751          // Parse arguments against default values
2752          $r = bbp_parse_args( $args, array(
2753              'id'           => 0,
2754              'link_before'  => '',
2755              'link_after'   => '',
2756              'merge_text'   => esc_html__( 'Merge', 'bbpress' ),
2757          ), 'get_topic_merge_link' );
2758  
2759          // Get topic
2760          $topic = bbp_get_topic( $r['id'] );
2761  
2762          // Bail if no topic or current user cannot moderate
2763          if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2764              return;
2765          }
2766  
2767          $uri    = add_query_arg( array( 'action' => 'merge' ), bbp_get_topic_edit_url( $topic->ID ) );
2768          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-merge-link">' . $r['merge_text'] . '</a>' . $r['link_after'];
2769  
2770          // Filter & return
2771          return apply_filters( 'bbp_get_topic_merge_link', $retval, $r, $args );
2772      }
2773  
2774  /**
2775   * Output the spam link of the topic
2776   *
2777   * @since 2.0.0 bbPress (r2727)
2778   *
2779   * @param array $args See {@link bbp_get_topic_spam_link()}
2780   */
2781  function bbp_topic_spam_link( $args = array() ) {
2782      echo bbp_get_topic_spam_link( $args );
2783  }
2784  
2785      /**
2786       * Return the spam link of the topic
2787       *
2788       * @since 2.0.0 bbPress (r2727)
2789       *
2790       * @param array $args This function supports these args:
2791       *  - id: Optional. Topic id
2792       *  - link_before: Before the link
2793       *  - link_after: After the link
2794       *  - spam_text: Spam text
2795       *  - unspam_text: Unspam text
2796       *
2797       * @return string Topic spam link
2798       */
2799  	function bbp_get_topic_spam_link( $args = array() ) {
2800  
2801          // Parse arguments against default values
2802          $r = bbp_parse_args( $args, array(
2803              'id'           => 0,
2804              'link_before'  => '',
2805              'link_after'   => '',
2806              'sep'          => ' | ',
2807              'spam_text'    => esc_html__( 'Spam',   'bbpress' ),
2808              'unspam_text'  => esc_html__( 'Unspam', 'bbpress' )
2809          ), 'get_topic_spam_link' );
2810  
2811          $topic = bbp_get_topic( $r['id'] );
2812  
2813          if ( empty( $topic ) || ! current_user_can( 'moderate', $topic->ID ) ) {
2814              return;
2815          }
2816  
2817          $display = bbp_is_topic_spam( $topic->ID ) ? $r['unspam_text'] : $r['spam_text'];
2818          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_topic_spam', 'topic_id' => $topic->ID ) );
2819          $uri     = wp_nonce_url( $uri, 'spam-topic_' . $topic->ID );
2820          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-topic-spam-link">' . $display . '</a>' . $r['link_after'];
2821  
2822          // Filter & return
2823          return apply_filters( 'bbp_get_topic_spam_link', $retval, $r, $args );
2824      }
2825  
2826  /**
2827   * Output the link to go directly to the reply form
2828   *
2829   * @since 2.4.0 bbPress (r4966)
2830   *
2831   * @param array $args
2832   */
2833  function bbp_topic_reply_link( $args = array() ) {
2834      echo bbp_get_topic_reply_link( $args );
2835  }
2836  
2837      /**
2838       * Return the link to go directly to the reply form
2839       *
2840       * @since 2.4.0 bbPress (r4966)
2841       *
2842       * @param array $args Arguments
2843       *
2844       * @return string Link for a reply to a topic
2845       */
2846  	function bbp_get_topic_reply_link( $args = array() ) {
2847  
2848          // Parse arguments against default values
2849          $r = bbp_parse_args( $args, array(
2850              'id'          => 0,
2851              'link_before' => '',
2852              'link_after'  => '',
2853              'reply_text'  => esc_html_x( 'Reply', 'verb', 'bbpress' ),
2854              'add_below'   => 'post',
2855              'respond_id'  => 'new-reply-' . bbp_get_topic_id(),
2856          ), 'get_topic_reply_link' );
2857  
2858          // Get the topic to use it's ID and post_parent
2859          $topic = bbp_get_topic( $r['id'] );
2860  
2861          // Bail if no topic or user cannot reply
2862          if ( empty( $topic ) || bbp_is_single_reply() || ! bbp_current_user_can_access_create_reply_form() ) {
2863              return;
2864          }
2865  
2866          // Only add onclick if replies are threaded
2867          $onclick = bbp_thread_replies()
2868              ? ' onclick="return addReply.cancelForm();"'
2869              : '';
2870  
2871           // Add $uri to the array, to be passed through the filter
2872          $r['uri'] = remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) . '#new-post';
2873          $retval   = $r['link_before'] . '<a role="button" href="' . esc_url( $r['uri'] ) . '" class="bbp-topic-reply-link"' . $onclick . '>' . $r['reply_text'] . '</a>' . $r['link_after'];
2874  
2875          // Filter & return
2876          return apply_filters( 'bbp_get_topic_reply_link', $retval, $r, $args );
2877      }
2878  
2879  /** Topic Pagination **********************************************************/
2880  
2881  /**
2882   * Return the base URL used inside of pagination links
2883   *
2884   * @since 2.6.0 bbPress (r6402)
2885   *
2886   * @param int $forum_id
2887   * @return string
2888   */
2889  function bbp_get_topics_pagination_base( $forum_id = 0 ) {
2890  
2891      // If pretty permalinks are enabled, make our pagination pretty
2892      if ( bbp_use_pretty_urls() ) {
2893  
2894          // User's topics
2895          if ( bbp_is_single_user_topics() ) {
2896              $base = bbp_get_user_topics_created_url( bbp_get_displayed_user_id() );
2897  
2898          // User's engagements
2899          } elseif ( bbp_is_single_user_engagements() ) {
2900              $base = bbp_get_user_engagements_url( bbp_get_displayed_user_id() );
2901  
2902          // User's favorites
2903          } elseif ( bbp_is_favorites() ) {
2904              $base = bbp_get_favorites_permalink( bbp_get_displayed_user_id() );
2905  
2906          // User's subscriptions
2907          } elseif ( bbp_is_subscriptions() ) {
2908              $base = bbp_get_subscriptions_permalink( bbp_get_displayed_user_id() );
2909  
2910          // Root profile page
2911          } elseif ( bbp_is_single_user() ) {
2912              $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
2913  
2914          // Any single post (for shortcodes, ahead of shortcodeables below)
2915          } elseif ( is_singular() ) {
2916              $base = get_permalink();
2917  
2918          // View
2919          } elseif ( bbp_is_single_view() ) {
2920              $base = bbp_get_view_url();
2921  
2922          // Topic tag
2923          } elseif ( bbp_is_topic_tag() ) {
2924              $base = bbp_get_topic_tag_link();
2925  
2926          // Forum archive
2927          } elseif ( bbp_is_forum_archive() ) {
2928              $base = bbp_get_forums_url();
2929  
2930          // Topic archive
2931          } elseif ( bbp_is_topic_archive() ) {
2932              $base = bbp_get_topics_url();
2933  
2934          // Default
2935          } else {
2936              $base = get_permalink( $forum_id );
2937          }
2938  
2939          // Use pagination base
2940          $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
2941  
2942      // Unpretty pagination
2943      } else {
2944          $base = add_query_arg( 'paged', '%#%' );
2945      }
2946  
2947      // Filter & return
2948      return apply_filters( 'bbp_get_topics_pagination_base', $base, $forum_id );
2949  }
2950  
2951  /**
2952   * Output the pagination count
2953   *
2954   * The results are unescaped by design, to allow them to be filtered freely via
2955   * the 'bbp_get_forum_pagination_count' filter.
2956   *
2957   * @since 2.0.0 bbPress (r2519)
2958   */
2959  function bbp_forum_pagination_count() {
2960      echo bbp_get_forum_pagination_count();
2961  }
2962      /**
2963       * Return the pagination count
2964       *
2965       * @since 2.0.0 bbPress (r2519)
2966       *
2967       * @return string Forum Pagination count
2968       */
2969  	function bbp_get_forum_pagination_count() {
2970          $bbp = bbpress();
2971  
2972          // Define local variable(s)
2973          $retstr = '';
2974  
2975          // Topic query exists
2976          if ( ! empty( $bbp->topic_query ) ) {
2977  
2978              // Set pagination values
2979              $count_int = intval( $bbp->topic_query->post_count );
2980              $start_num = intval( ( $bbp->topic_query->paged - 1 ) * $bbp->topic_query->posts_per_page ) + 1;
2981              $total_int = ! empty( $bbp->topic_query->found_posts )
2982                  ? (int) $bbp->topic_query->found_posts
2983                  : $count_int;
2984  
2985              // Format numbers for display
2986              $count_num = bbp_number_format( $count_int );
2987              $from_num  = bbp_number_format( $start_num );
2988              $total     = bbp_number_format( $total_int );
2989              $to_num    = bbp_number_format( ( $start_num + ( $bbp->topic_query->posts_per_page - 1 ) > $bbp->topic_query->found_posts )
2990                  ? $bbp->topic_query->found_posts
2991                  : $start_num + ( $bbp->topic_query->posts_per_page - 1 ) );
2992  
2993              // Several topics in a forum with a single page
2994              if ( empty( $to_num ) ) {
2995                  $retstr = sprintf( _n( 'Viewing %1$s topic', 'Viewing %1$s topics', $total_int, 'bbpress' ), $total );
2996  
2997              // Several topics in a forum with several pages
2998              } else {
2999                  $retstr = sprintf( _n( 'Viewing topic %2$s (of %4$s total)', 'Viewing %1$s topics - %2$s through %3$s (of %4$s total)', $total_int, 'bbpress' ), $count_num, $from_num, $to_num, $total );  //phpcs:ignore
3000              }
3001  
3002              // Escape results of _n()
3003              $retstr = esc_html( $retstr );
3004          }
3005  
3006          // Filter & return
3007          return apply_filters( 'bbp_get_forum_pagination_count', $retstr );
3008      }
3009  
3010  /**
3011   * Output pagination links
3012   *
3013   * @since 2.0.0 bbPress (r2519)
3014   */
3015  function bbp_forum_pagination_links() {
3016      echo bbp_get_forum_pagination_links();
3017  }
3018      /**
3019       * Return pagination links
3020       *
3021       * @since 2.0.0 bbPress (r2519)
3022       *
3023       * @return string Pagination links
3024       */
3025  	function bbp_get_forum_pagination_links() {
3026          $bbp = bbpress();
3027  
3028          if ( empty( $bbp->topic_query ) ) {
3029              return false;
3030          }
3031  
3032          // Filter & return
3033          return apply_filters( 'bbp_get_forum_pagination_links', $bbp->topic_query->pagination_links );
3034      }
3035  
3036  /**
3037   * Displays topic notices
3038   *
3039   * @since 2.0.0 bbPress (r2744)
3040   */
3041  function bbp_topic_notices() {
3042  
3043      // Bail if not viewing a topic
3044      if ( ! bbp_is_single_topic() ) {
3045          return;
3046      }
3047  
3048      // Get the topic_status
3049      $topic_status = bbp_get_topic_status();
3050  
3051      // Get the topic status
3052      switch ( $topic_status ) {
3053  
3054          // Spam notice
3055          case bbp_get_spam_status_id() :
3056              $notice_text = esc_html__( 'This topic is marked as spam.', 'bbpress' );
3057              break;
3058  
3059          // Trashed notice
3060          case bbp_get_trash_status_id() :
3061              $notice_text = esc_html__( 'This topic is in the trash.', 'bbpress' );
3062              break;
3063  
3064          // Pending notice
3065          case bbp_get_pending_status_id() :
3066              $notice_text = esc_html__( 'This topic is pending moderation.', 'bbpress' );
3067              break;
3068  
3069          // Standard status
3070          default :
3071              $notice_text = '';
3072              break;
3073      }
3074  
3075      // Filter notice text and bail if empty
3076      $notice_text = apply_filters( 'bbp_topic_notices', $notice_text, $topic_status, bbp_get_topic_id() );
3077      if ( empty( $notice_text ) ) {
3078          return;
3079      }
3080  
3081      bbp_add_error( 'topic_notice', $notice_text, 'message' );
3082  }
3083  
3084  /**
3085   * Displays topic type select box (normal/sticky/super sticky)
3086   *
3087   * @since 2.0.0 bbPress (r2784)
3088   *
3089   * @deprecated 2.4.0 bbPress (r5059)
3090   *
3091   * @param $args This function supports these arguments:
3092   *  - select_id: Select id. Defaults to bbp_stick_topic
3093   *  - tab: Deprecated. Tabindex
3094   *  - topic_id: Topic id
3095   *  - selected: Override the selected option
3096   */
3097  function bbp_topic_type_select( $args = array() ) {
3098      echo bbp_get_form_topic_type_dropdown( $args );
3099  }
3100  
3101  /**
3102   * Displays topic type select box (normal/sticky/super sticky)
3103   *
3104   * @since 2.4.0 bbPress (r5059)
3105   *
3106   * @param $args This function supports these arguments:
3107   *  - select_id: Select id. Defaults to bbp_stick_topic
3108   *  - tab: Deprecated. Tabindex
3109   *  - topic_id: Topic id
3110   *  - selected: Override the selected option
3111   */
3112  function bbp_form_topic_type_dropdown( $args = array() ) {
3113      echo bbp_get_form_topic_type_dropdown( $args );
3114  }
3115      /**
3116       * Returns topic type select box (normal/sticky/super sticky)
3117       *
3118       * @since 2.4.0 bbPress (r5059)
3119       *
3120       * @param $args This function supports these arguments:
3121       *  - select_id: Select id. Defaults to bbp_stick_topic
3122       *  - tab: Deprecated. Tabindex
3123       *  - topic_id: Topic id
3124       *  - selected: Override the selected option
3125       */
3126  	function bbp_get_form_topic_type_dropdown( $args = array() ) {
3127  
3128          // Parse arguments against default values
3129          $r = bbp_parse_args( $args, array(
3130              'select_id'    => 'bbp_stick_topic',
3131              'select_class' => 'bbp_dropdown',
3132              'tab'          => false,
3133              'topic_id'     => 0,
3134              'selected'     => false
3135          ), 'topic_type_select' );
3136  
3137          // No specific selected value passed
3138          if ( empty( $r['selected'] ) ) {
3139  
3140              // Post value is passed
3141              if ( bbp_is_topic_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
3142                  $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
3143  
3144              // No Post value passed
3145              } else {
3146  
3147                  // Edit topic
3148                  if ( bbp_is_single_topic() || bbp_is_topic_edit() ) {
3149  
3150                      // Get current topic id
3151                      $r['topic_id'] = bbp_get_topic_id( $r['topic_id'] );
3152  
3153                      // Topic is super sticky
3154                      if ( bbp_is_topic_super_sticky( $r['topic_id'] ) ) {
3155                          $r['selected'] = 'super';
3156  
3157                      // Topic is sticky or normal
3158                      } else {
3159                          $r['selected'] = bbp_is_topic_sticky( $r['topic_id'], false )
3160                              ? 'stick'
3161                              : 'unstick';
3162                      }
3163                  }
3164              }
3165          }
3166  
3167          // Start an output buffer, we'll finish it after the select loop
3168          ob_start(); ?>
3169  
3170          <select name="<?php echo esc_attr( $r['select_id'] ); ?>" id="<?php echo esc_attr( $r['select_id'] ); ?>_select" class="<?php echo esc_attr( $r['select_class'] ); ?>"<?php bbp_tab_index_attribute( $r['tab'] ); ?>>
3171  
3172              <?php foreach ( bbp_get_topic_types( $r['topic_id'] ) as $key => $label ) : ?>
3173  
3174                  <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
3175  
3176              <?php endforeach; ?>
3177  
3178          </select>
3179  
3180          <?php
3181  
3182          // Filter & return
3183          return apply_filters( 'bbp_get_form_topic_type_dropdown', ob_get_clean(), $r, $args );
3184      }
3185  
3186  /**
3187   * Output value topic status dropdown
3188   *
3189   * @since 2.4.0 bbPress (r5059)
3190   *
3191   * @param $args This function supports these arguments:
3192   *  - select_id: Select id. Defaults to bbp_topic_status
3193   *  - tab: Deprecated. Tabindex
3194   *  - topic_id: Topic id
3195   *  - selected: Override the selected option
3196   */
3197  function bbp_form_topic_status_dropdown( $args = array() ) {
3198      echo bbp_get_form_topic_status_dropdown( $args );
3199  }
3200      /**
3201       * Returns topic status dropdown
3202       *
3203       * This dropdown is only intended to be seen by users with the 'moderate'
3204       * capability. Because of this, no additional capability checks are performed
3205       * within this function to check available topic statuses.
3206       *
3207       * @since 2.4.0 bbPress (r5059)
3208       *
3209       * @param $args This function supports these arguments:
3210       *  - select_id: Select id. Defaults to bbp_topic_status
3211       *  - tab: Deprecated. Tabindex
3212       *  - topic_id: Topic id
3213       *  - selected: Override the selected option
3214       */
3215  	function bbp_get_form_topic_status_dropdown( $args = array() ) {
3216  
3217          // Parse arguments against default values
3218          $r = bbp_parse_args( $args, array(
3219              'select_id'    => 'bbp_topic_status',
3220              'select_class' => 'bbp_dropdown',
3221              'tab'          => false,
3222              'topic_id'     => 0,
3223              'selected'     => false
3224          ), 'topic_open_close_select' );
3225  
3226          // No specific selected value passed
3227          if ( empty( $r['selected'] ) ) {
3228  
3229              // Post value is passed
3230              if ( bbp_is_topic_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
3231                  $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
3232  
3233              // No Post value was passed
3234              } else {
3235  
3236                  // Edit topic
3237                  if ( bbp_is_topic_edit() ) {
3238                      $r['topic_id'] = bbp_get_topic_id( $r['topic_id'] );
3239                      $r['selected'] = bbp_get_topic_status( $r['topic_id'] );
3240  
3241                  // New topic
3242                  } else {
3243                      $r['selected'] = bbp_get_public_status_id();
3244                  }
3245              }
3246          }
3247  
3248          // Start an output buffer, we'll finish it after the select loop
3249          ob_start(); ?>
3250  
3251          <select name="<?php echo esc_attr( $r['select_id'] ); ?>" id="<?php echo esc_attr( $r['select_id'] ); ?>_select" class="<?php echo esc_attr( $r['select_class'] ); ?>"<?php bbp_tab_index_attribute( $r['tab'] ); ?>>
3252  
3253              <?php foreach ( bbp_get_topic_statuses( $r['topic_id'] ) as $key => $label ) : ?>
3254  
3255                  <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
3256  
3257              <?php endforeach; ?>
3258  
3259          </select>
3260  
3261          <?php
3262  
3263          // Filter & return
3264          return apply_filters( 'bbp_get_form_topic_status_dropdown', ob_get_clean(), $r, $args );
3265      }
3266  
3267  /** Single Topic **************************************************************/
3268  
3269  /**
3270   * Output a fancy description of the current topic, including total topics,
3271   * total replies, and last activity.
3272   *
3273   * @since 2.0.0 bbPress (r2860)
3274   *
3275   * @param array $args See {@link bbp_get_single_topic_description()}
3276   */
3277  function bbp_single_topic_description( $args = array() ) {
3278      echo bbp_get_single_topic_description( $args );
3279  }
3280      /**
3281       * Return a fancy description of the current topic, including total topics,
3282       * total replies, and last activity.
3283       *
3284       * @since 2.0.0 bbPress (r2860)
3285       *
3286       * @param array $args This function supports these arguments:
3287       *  - topic_id: Topic id
3288       *  - before: Before the text
3289       *  - after: After the text
3290       *  - size: Size of the avatar
3291       * @return string Filtered topic description
3292       */
3293  	function bbp_get_single_topic_description( $args = array() ) {
3294  
3295          // Parse arguments against default values
3296          $r = bbp_parse_args( $args, array(
3297              'topic_id'  => 0,
3298              'before'    => '<div class="bbp-template-notice info"><ul><li class="bbp-topic-description">',
3299              'after'     => '</li></ul></div>',
3300              'size'      => 14
3301          ), 'get_single_topic_description' );
3302  
3303          // Validate topic_id
3304          $topic_id = bbp_get_topic_id( $r['topic_id'] );
3305  
3306          // Unhook the 'view all' query var adder
3307          remove_filter( 'bbp_get_topic_permalink', 'bbp_add_view_all' );
3308  
3309          // Build the topic description
3310          $vc_int      = bbp_get_topic_voice_count   ( $topic_id, true  );
3311          $voice_count = bbp_get_topic_voice_count   ( $topic_id, false );
3312          $reply_count = bbp_get_topic_replies_link  ( $topic_id        );
3313          $time_since  = bbp_get_topic_freshness_link( $topic_id        );
3314  
3315          // Singular/Plural
3316          $voice_count = sprintf( _n( '%s voice', '%s voices', $vc_int, 'bbpress' ), $voice_count );
3317  
3318          // Topic has activity (could be from reply or topic author)
3319          $last_active = bbp_get_topic_last_active_id( $topic_id );
3320          if ( ! empty( $vc_int ) && ! empty( $last_active ) ) {
3321              $last_updated_by = bbp_get_author_link( array( 'post_id' => $last_active, 'size' => $r['size'] ) );
3322              $retstr          = sprintf( esc_html__( 'This topic has %1$s, %2$s, and was last updated %3$s by %4$s.', 'bbpress' ), $reply_count, $voice_count, $time_since, $last_updated_by );
3323  
3324          // Topic has no replies
3325          } elseif ( ! empty( $vc_int ) && ! empty( $reply_count ) ) {
3326              $retstr = sprintf( esc_html__( 'This topic has %1$s and %2$s.', 'bbpress' ), $voice_count, $reply_count );
3327  
3328          // Topic has no replies and no voices
3329          } elseif ( empty( $vc_int ) && empty( $reply_count ) ) {
3330              $retstr = esc_html__( 'This topic has no replies.', 'bbpress' );
3331  
3332          // Topic is pending
3333          } elseif ( bbp_get_topic_status( $topic_id ) === bbp_get_pending_status_id() ) {
3334              $retstr = esc_html__( 'This topic is pending moderation.', 'bbpress' );
3335  
3336          // Fallback
3337          } else {
3338              $retstr = esc_html__( 'This topic is empty.', 'bbpress' );
3339          }
3340  
3341          // Add the 'view all' filter back
3342          add_filter( 'bbp_get_topic_permalink', 'bbp_add_view_all' );
3343  
3344          // Combine the elements together
3345          $retstr = $r['before'] . $retstr . $r['after'];
3346  
3347          // Filter & return
3348          return apply_filters( 'bbp_get_single_topic_description', $retstr, $r, $args );
3349      }
3350  
3351  /** Topic Tags ****************************************************************/
3352  
3353  /**
3354   * Output the unique id of the topic tag taxonomy
3355   *
3356   * @since 2.0.0 bbPress (r3348)
3357   */
3358  function bbp_topic_tag_tax_id() {
3359      echo bbp_get_topic_tag_tax_id();
3360  }
3361      /**
3362       * Return the unique id of the topic tag taxonomy
3363       *
3364       * @since 2.0.0 bbPress (r3348)
3365       *
3366       * @return string The unique topic tag taxonomy
3367       */
3368  	function bbp_get_topic_tag_tax_id() {
3369  
3370          // Filter & return
3371          return apply_filters( 'bbp_get_topic_tag_tax_id', bbpress()->topic_tag_tax_id );
3372      }
3373  
3374  /**
3375   * Return array of labels used by the topic-tag taxonomy
3376   *
3377   * @since 2.5.0 bbPress (r5129)
3378   *
3379   * @return array
3380   */
3381  function bbp_get_topic_tag_tax_labels() {
3382  
3383      // Filter & return
3384      return (array) apply_filters( 'bbp_get_topic_tag_tax_labels', array(
3385          'name'                       => esc_attr__( 'Topic Tags',                      'bbpress' ),
3386          'menu_name'                  => esc_attr__( 'Topic Tags',                      'bbpress' ),
3387          'singular_name'              => esc_attr__( 'Topic Tag',                       'bbpress' ),
3388          'search_items'               => esc_attr__( 'Search Tags',                     'bbpress' ),
3389          'popular_items'              => esc_attr__( 'Popular Tags',                    'bbpress' ),
3390          'all_items'                  => esc_attr__( 'All Tags',                        'bbpress' ),
3391          'parent_item'                => esc_attr__( 'Parent Tag',                      'bbpress' ),
3392          'parent_item_colon'          => esc_attr__( 'Parent Tag:',                     'bbpress' ),
3393          'edit_item'                  => esc_attr__( 'Edit Tag',                        'bbpress' ),
3394          'view_item'                  => esc_attr__( 'View Topic Tag',                  'bbpress' ),
3395          'update_item'                => esc_attr__( 'Update Tag',                      'bbpress' ),
3396          'add_new_item'               => esc_attr__( 'Add New Tag',                     'bbpress' ),
3397          'new_item_name'              => esc_attr__( 'New Tag Name',                    'bbpress' ),
3398          'separate_items_with_commas' => esc_attr__( 'Separate topic tags with commas', 'bbpress' ),
3399          'add_or_remove_items'        => esc_attr__( 'Add or remove tags',              'bbpress' ),
3400          'choose_from_most_used'      => esc_attr__( 'Choose from the most used tags',  'bbpress' ),
3401          'not_found'                  => esc_attr__( 'No topic tags found.',            'bbpress' ),
3402          'no_terms'                   => esc_attr__( 'No topic tags',                   'bbpress' ),
3403          'items_list_navigation'      => esc_attr__( 'Topic tags list navigation',      'bbpress' ),
3404          'items_list'                 => esc_attr__( 'Topic tags list',                 'bbpress' ),
3405          'most_used'                  => esc_attr__( 'Most used topic tags',            'bbpress' ),
3406          'back_to_items'              => esc_attr__( '&larr; Back to Tags',             'bbpress' )
3407      ) );
3408  }
3409  
3410  /**
3411   * Return an array of topic-tag taxonomy rewrite settings
3412   *
3413   * @since 2.5.0 bbPress (r5129)
3414   *
3415   * @return array
3416   */
3417  function bbp_get_topic_tag_tax_rewrite() {
3418  
3419      // Filter & return
3420      return (array) apply_filters( 'bbp_get_topic_tag_tax_rewrite', array(
3421          'slug'       => bbp_get_topic_tag_tax_slug(),
3422          'with_front' => false
3423      ) );
3424  }
3425  
3426  /**
3427   * Output the id of the current tag
3428   *
3429   * @since 2.0.0 bbPress (r3109)
3430   *
3431   */
3432  function bbp_topic_tag_id( $tag = '' ) {
3433      echo bbp_get_topic_tag_id( $tag );
3434  }
3435      /**
3436       * Return the id of the current tag
3437       *
3438       * @since 2.0.0 bbPress (r3109)
3439       *
3440       * @return string Term Name
3441       */
3442  	function bbp_get_topic_tag_id( $tag = '' ) {
3443  
3444          // Get the term
3445          if ( ! empty( $tag ) ) {
3446              $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3447          } else {
3448              $tag  = get_query_var( 'term' );
3449              $term = get_queried_object();
3450          }
3451  
3452          // Get the term ID
3453          $retval = ! empty( $term->term_id )
3454              ? $term->term_id
3455              : 0;
3456  
3457          // Filter & return
3458          return (int) apply_filters( 'bbp_get_topic_tag_id', (int) $retval, $tag, $term );
3459      }
3460  
3461  /**
3462   * Output the name of the current tag
3463   *
3464   * @since 2.0.0 bbPress (r3109)
3465   */
3466  function bbp_topic_tag_name( $tag = '' ) {
3467      echo bbp_get_topic_tag_name( $tag );
3468  }
3469      /**
3470       * Return the name of the current tag
3471       *
3472       * @since 2.0.0 bbPress (r3109)
3473       *
3474       * @return string Term Name
3475       */
3476  	function bbp_get_topic_tag_name( $tag = '' ) {
3477  
3478          // Get the term
3479          if ( ! empty( $tag ) ) {
3480              $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3481          } else {
3482              $tag  = get_query_var( 'term' );
3483              $term = get_queried_object();
3484          }
3485  
3486          // Get the term name
3487          $retval = ! empty( $term->name )
3488              ? $term->name
3489              : '';
3490  
3491          // Filter & return
3492          return apply_filters( 'bbp_get_topic_tag_name', $retval, $tag, $term );
3493      }
3494  
3495  /**
3496   * Output the slug of the current tag
3497   *
3498   * @since 2.0.0 bbPress (r3109)
3499   */
3500  function bbp_topic_tag_slug( $tag = '' ) {
3501      echo bbp_get_topic_tag_slug( $tag );
3502  }
3503      /**
3504       * Return the slug of the current tag
3505       *
3506       * @since 2.0.0 bbPress (r3109)
3507       *
3508       * @return string Term Name
3509       */
3510  	function bbp_get_topic_tag_slug( $tag = '' ) {
3511  
3512          // Get the term
3513          if ( ! empty( $tag ) ) {
3514              $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3515          } else {
3516              $tag  = get_query_var( 'term' );
3517              $term = get_queried_object();
3518          }
3519  
3520          // Get the term slug
3521          $retval = ! empty( $term->slug )
3522              ? $term->slug
3523              : '';
3524  
3525          // Filter & return
3526          return apply_filters( 'bbp_get_topic_tag_slug', $retval, $tag, $term );
3527      }
3528  
3529  /**
3530   * Output the link of the current tag
3531   *
3532   * @since 2.0.0 bbPress (r3348)
3533   */
3534  function bbp_topic_tag_link( $tag = '' ) {
3535      echo esc_url( bbp_get_topic_tag_link( $tag ) );
3536  }
3537      /**
3538       * Return the link of the current tag
3539       *
3540       * @since 2.0.0 bbPress (r3348)
3541       *
3542       * @return string Term Name
3543       */
3544  	function bbp_get_topic_tag_link( $tag = '' ) {
3545  
3546          // Get the term
3547          if ( ! empty( $tag ) ) {
3548              $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3549          } else {
3550              $tag  = get_query_var( 'term' );
3551              $term = get_queried_object();
3552          }
3553  
3554          // Get the term link
3555          $retval = ! empty( $term->term_id )
3556              ? get_term_link( $term, bbp_get_topic_tag_tax_id() )
3557              : '';
3558  
3559          // Filter & return
3560          return apply_filters( 'bbp_get_topic_tag_link', $retval, $tag, $term );
3561      }
3562  
3563  /**
3564   * Output the link of the current tag
3565   *
3566   * @since 2.0.0 bbPress (r3348)
3567   */
3568  function bbp_topic_tag_edit_link( $tag = '' ) {
3569      echo esc_url( bbp_get_topic_tag_edit_link( $tag ) );
3570  }
3571      /**
3572       * Return the link of the current tag
3573       *
3574       * @since 2.0.0 bbPress (r3348)
3575       *
3576       * @return string Term Name
3577       */
3578  	function bbp_get_topic_tag_edit_link( $tag = '' ) {
3579  
3580          // Get the term
3581          if ( ! empty( $tag ) ) {
3582              $term = get_term_by( 'slug', $tag, bbp_get_topic_tag_tax_id() );
3583          } else {
3584              $tag  = get_query_var( 'term' );
3585              $term = get_queried_object();
3586          }
3587  
3588          // Get the term's edit link
3589          if ( ! empty( $term->term_id ) ) {
3590  
3591              // Pretty or ugly URL
3592              $retval = bbp_use_pretty_urls()
3593                  ? user_trailingslashit( trailingslashit( bbp_get_topic_tag_link() ) . bbp_get_edit_slug() )
3594                  : add_query_arg( array( bbp_get_edit_rewrite_id() => '1' ), bbp_get_topic_tag_link() );
3595  
3596          // No link
3597          } else {
3598              $retval = '';
3599          }
3600  
3601          // Filter & return
3602          return apply_filters( 'bbp_get_topic_tag_edit_link', $retval, $tag, $term );
3603      }
3604  
3605  /**
3606   * Output the description of the current tag
3607   *
3608   * @since 2.0.0 bbPress (r3109)
3609   */
3610  function bbp_topic_tag_description( $args = array() ) {
3611      echo bbp_get_topic_tag_description( $args );
3612  }
3613      /**
3614       * Return the description of the current tag
3615       *
3616       * @since 2.0.0 bbPress (r3109)
3617       *
3618       * @param array $args before|after|tag
3619       *
3620       * @return string Term Name
3621       */
3622  	function bbp_get_topic_tag_description( $args = array() ) {
3623  
3624          // Parse arguments against default values
3625          $r = bbp_parse_args( $args, array(
3626              'before' => '<div class="bbp-topic-tag-description"><p>',
3627              'after'  => '</p></div>',
3628              'tag'    => ''
3629          ), 'get_topic_tag_description' );
3630  
3631          // Get the term
3632          if ( ! empty( $r['tag'] ) ) {
3633              $term = get_term_by( 'slug', $r['tag'], bbp_get_topic_tag_tax_id() );
3634          } else {
3635              $tag  = $r['tag'] = get_query_var( 'term' );
3636              $term = get_queried_object();
3637          }
3638  
3639          // Add before & after if description exists
3640          $retval = ! empty( $term->description )
3641              ? $r['before'] . $term->description . $r['after']
3642              : '';
3643  
3644          // Filter & return
3645          return apply_filters( 'bbp_get_topic_tag_description', $retval, $r, $args, $tag, $term );
3646      }
3647  
3648  /** Forms *********************************************************************/
3649  
3650  /**
3651   * Output the value of topic title field
3652   *
3653   * @since 2.0.0 bbPress (r2976)
3654   */
3655  function bbp_form_topic_title() {
3656      echo bbp_get_form_topic_title();
3657  }
3658      /**
3659       * Return the value of topic title field
3660       *
3661       * @since 2.0.0 bbPress (r2976)
3662       *
3663       * @return string Value of topic title field
3664       */
3665  	function bbp_get_form_topic_title() {
3666  
3667          // Get _POST data
3668          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_title'] ) ) {
3669              $topic_title = wp_unslash( $_POST['bbp_topic_title'] );
3670  
3671          // Get edit data
3672          } elseif ( bbp_is_topic_edit() ) {
3673              $topic_title = bbp_get_global_post_field( 'post_title', 'raw' );
3674  
3675          // No data
3676          } else {
3677              $topic_title = '';
3678          }
3679  
3680          // Filter & return
3681          return apply_filters( 'bbp_get_form_topic_title', $topic_title );
3682      }
3683  
3684  /**
3685   * Output the value of topic content field
3686   *
3687   * @since 2.0.0 bbPress (r2976)
3688   */
3689  function bbp_form_topic_content() {
3690      echo bbp_get_form_topic_content();
3691  }
3692      /**
3693       * Return the value of topic content field
3694       *
3695       * @since 2.0.0 bbPress (r2976)
3696       *
3697       * @return string Value of topic content field
3698       */
3699  	function bbp_get_form_topic_content() {
3700  
3701          // Get _POST data
3702          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_content'] ) ) {
3703              $topic_content = wp_unslash( $_POST['bbp_topic_content'] );
3704  
3705          // Get edit data
3706          } elseif ( bbp_is_topic_edit() ) {
3707              $topic_content = bbp_get_global_post_field( 'post_content', 'raw' );
3708  
3709          // No data
3710          } else {
3711              $topic_content = '';
3712          }
3713  
3714          // Filter & return
3715          return apply_filters( 'bbp_get_form_topic_content', $topic_content );
3716      }
3717  
3718  /**
3719   * Allow topic rows to have administrative actions
3720   *
3721   * @since 2.1.0 bbPress (r3653)
3722   *
3723   * @todo Links and filter
3724   */
3725  function bbp_topic_row_actions() {
3726      do_action( 'bbp_topic_row_actions' );
3727  }
3728  
3729  /**
3730   * Output value of topic tags field
3731   *
3732   * @since 2.0.0 bbPress (r2976)
3733   */
3734  function bbp_form_topic_tags() {
3735      echo bbp_get_form_topic_tags();
3736  }
3737      /**
3738       * Return value of topic tags field
3739       *
3740       * @since 2.0.0 bbPress (r2976)
3741       *
3742       * @return string Value of topic tags field
3743       */
3744  	function bbp_get_form_topic_tags() {
3745  
3746          // Default return value
3747          $topic_tags = '';
3748  
3749          // Get _POST data
3750          if ( ( bbp_is_topic_form_post_request() || bbp_is_reply_form_post_request() ) && isset( $_POST['bbp_topic_tags'] ) ) {
3751              $topic_tags = wp_unslash( $_POST['bbp_topic_tags'] );
3752  
3753          // Get edit data
3754          } elseif ( bbp_is_single_topic() || bbp_is_single_reply() || bbp_is_topic_edit() || bbp_is_reply_edit() ) {
3755  
3756              // Determine the topic id based on the post type
3757              switch ( get_post_type() ) {
3758  
3759                  // Post is a topic
3760                  case bbp_get_topic_post_type() :
3761                      $topic_id = bbp_get_topic_id( get_the_ID() );
3762                      break;
3763  
3764                  // Post is a reply
3765                  case bbp_get_reply_post_type() :
3766                      $topic_id = bbp_get_reply_topic_id( get_the_ID() );
3767                      break;
3768              }
3769  
3770              // Topic exists
3771              if ( ! empty( $topic_id ) ) {
3772  
3773                  // Topic is spammed so display pre-spam terms
3774                  if ( bbp_is_topic_spam( $topic_id ) ) {
3775  
3776                      // Get pre-spam terms
3777                      $spam_terms = get_post_meta( $topic_id, '_bbp_spam_topic_tags', true );
3778                      $topic_tags = ( ! empty( $spam_terms ) ) ? implode( ', ', $spam_terms ) : '';
3779  
3780                  // Topic is not spam so get real terms
3781                  } else {
3782                      $topic_tags = bbp_get_topic_tag_names( $topic_id );
3783                  }
3784              }
3785          }
3786  
3787          // Filter & return
3788          return apply_filters( 'bbp_get_form_topic_tags', $topic_tags );
3789      }
3790  
3791  /**
3792   * Output value of topic forum
3793   *
3794   * @since 2.0.0 bbPress (r2976)
3795   */
3796  function bbp_form_topic_forum() {
3797      echo bbp_get_form_topic_forum();
3798  }
3799      /**
3800       * Return value of topic forum
3801       *
3802       * @since 2.0.0 bbPress (r2976)
3803       *
3804       * @return string Value of topic content field
3805       */
3806  	function bbp_get_form_topic_forum() {
3807  
3808          // Get _POST data
3809          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_forum_id'] ) ) {
3810              $topic_forum = (int) $_POST['bbp_forum_id'];
3811  
3812          // Get edit data
3813          } elseif ( bbp_is_topic_edit() ) {
3814              $topic_forum = bbp_get_topic_forum_id();
3815  
3816          // No data
3817          } else {
3818              $topic_forum = 0;
3819          }
3820  
3821          // Filter & return
3822          return apply_filters( 'bbp_get_form_topic_forum', $topic_forum );
3823      }
3824  
3825  /**
3826   * Output checked value of topic subscription
3827   *
3828   * @since 2.0.0 bbPress (r2976)
3829   */
3830  function bbp_form_topic_subscribed() {
3831      echo bbp_get_form_topic_subscribed();
3832  }
3833      /**
3834       * Return checked value of topic subscription
3835       *
3836       * @since 2.0.0 bbPress (r2976)
3837       *
3838       * @return string Checked value of topic subscription
3839       */
3840  	function bbp_get_form_topic_subscribed() {
3841  
3842          // Default value
3843          $topic_subscribed = false;
3844  
3845          // Get _POST data
3846          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_subscription'] ) ) {
3847              $topic_subscribed = (bool) $_POST['bbp_topic_subscription'];
3848  
3849          // Get edit data
3850          } elseif ( bbp_is_topic_edit() || bbp_is_reply_edit() ) {
3851              $post_author      = (int) bbp_get_global_post_field( 'post_author', 'raw' );
3852              $topic_subscribed = bbp_is_user_subscribed( $post_author, bbp_get_topic_id() );
3853  
3854          // Get current status
3855          } elseif ( bbp_is_single_topic() ) {
3856              $topic_subscribed = bbp_is_user_subscribed( bbp_get_current_user_id(), bbp_get_topic_id() );
3857          }
3858  
3859          // Get checked output
3860          $checked = checked( $topic_subscribed, true, false );
3861  
3862          // Filter & return
3863          return apply_filters( 'bbp_get_form_topic_subscribed', $checked, $topic_subscribed );
3864      }
3865  
3866  /**
3867   * Output checked value of topic log edit field
3868   *
3869   * @since 2.0.0 bbPress (r2976)
3870   */
3871  function bbp_form_topic_log_edit() {
3872      echo bbp_get_form_topic_log_edit();
3873  }
3874      /**
3875       * Return checked value of topic log edit field
3876       *
3877       * @since 2.0.0 bbPress (r2976)
3878       *
3879       * @return string Topic log edit checked value
3880       */
3881  	function bbp_get_form_topic_log_edit() {
3882  
3883          // Get _POST data
3884          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_log_topic_edit'] ) ) {
3885              $topic_revision = (bool) $_POST['bbp_log_topic_edit'];
3886  
3887          // No data
3888          } else {
3889              $topic_revision = true;
3890          }
3891  
3892          // Get checked output
3893          $checked = checked( $topic_revision, true, false );
3894  
3895          // Filter & return
3896          return apply_filters( 'bbp_get_form_topic_log_edit', $checked, $topic_revision );
3897      }
3898  
3899  /**
3900   * Output the value of the topic edit reason
3901   *
3902   * @since 2.0.0 bbPress (r2976)
3903   */
3904  function bbp_form_topic_edit_reason() {
3905      echo bbp_get_form_topic_edit_reason();
3906  }
3907      /**
3908       * Return the value of the topic edit reason
3909       *
3910       * @since 2.0.0 bbPress (r2976)
3911       *
3912       * @return string Topic edit reason value
3913       */
3914  	function bbp_get_form_topic_edit_reason() {
3915  
3916          // Get _POST data
3917          if ( bbp_is_topic_form_post_request() && isset( $_POST['bbp_topic_edit_reason'] ) ) {
3918              $topic_edit_reason = wp_unslash( $_POST['bbp_topic_edit_reason'] );
3919  
3920          // No data
3921          } else {
3922              $topic_edit_reason = '';
3923          }
3924  
3925          // Filter & return
3926          return apply_filters( 'bbp_get_form_topic_edit_reason', $topic_edit_reason );
3927      }
3928  
3929  /**
3930   * Verify if a POST request came from a failed topic attempt.
3931   *
3932   * Used to avoid cross-site request forgeries when checking posted topic form
3933   * content.
3934   *
3935   * @see bbp_topic_form_fields()
3936   *
3937   * @since 2.6.0 bbPress (r5558)
3938   *
3939   * @return boolean True if is a post request with valid nonce
3940   */
3941  function bbp_is_topic_form_post_request() {
3942  
3943      // Bail if not a post request
3944      if ( ! bbp_is_post_request() ) {
3945          return false;
3946      }
3947  
3948      // Creating a new topic
3949      if ( bbp_verify_nonce_request( 'bbp-new-topic' ) ) {
3950          return true;
3951      }
3952  
3953      // Editing an existing topic
3954      if ( bbp_verify_nonce_request( 'bbp-edit-topic_' . bbp_get_topic_id() ) ) {
3955          return true;
3956      }
3957  
3958      return false;
3959  }
3960  
3961  /** Warning *******************************************************************/
3962  
3963  /**
3964   * Should the topic-lock alert appear?
3965   *
3966   * @since 2.6.0 bbPress (r6342)
3967   *
3968   * @return bool
3969   */
3970  function bbp_show_topic_lock_alert() {
3971  
3972      // Default to not showing the alert
3973      $retval = false;
3974  
3975      // Get the current topic ID
3976      $topic_id = bbp_get_topic_id();
3977  
3978      // Only show on single topic pages
3979      if ( bbp_is_topic_edit() || bbp_is_single_topic() ) {
3980  
3981          // Only show to moderators
3982          if ( current_user_can( 'moderate', $topic_id ) ) {
3983  
3984              // Locked?
3985              $user_id = bbp_check_post_lock( $topic_id );
3986  
3987              // Only show if not locked by the current user
3988              if ( ! empty( $user_id ) && ( bbp_get_current_user_id() !== $user_id ) ) {
3989                  $retval = true;
3990              }
3991          }
3992      }
3993  
3994      // Filter & return
3995      return (bool) apply_filters( 'bbp_show_topic_lock_alert', $retval, $topic_id );
3996  }
3997  
3998  /**
3999   * Output the topic lock description
4000   *
4001   * @since 2.6.0 bbPress (r6343)
4002   *
4003   * @param int $topic_id Optional. Topic id
4004   */
4005  function bbp_topic_lock_description( $topic_id = 0 ) {
4006      echo bbp_get_topic_lock_description( $topic_id );
4007  }
4008      /**
4009       * Return the topic lock description
4010       *
4011       * @since 2.6.0 bbPress (r6343)
4012       *
4013       * @param int $topic_id Optional. Topic id
4014       */
4015  	function bbp_get_topic_lock_description( $topic_id = 0 ) {
4016  
4017          // Check if topic is edit locked
4018          $topic_id = bbp_get_topic_id( $topic_id );
4019          $user_id  = bbp_check_post_lock( $topic_id );
4020          $person   = empty( $user_id )
4021              ? esc_html__( 'Nobody', 'bbpress' )
4022              : bbp_get_user_profile_link( $user_id );
4023  
4024          // Get the text
4025          $text = sprintf( esc_html__( '%1$s is currently editing this topic.', 'bbpress' ), $person );
4026  
4027          // Filter & return
4028          return apply_filters( 'bbp_get_topic_lock_description', $text, $user_id, $topic_id );
4029      }


Generated: Sat Apr 27 01:00:49 2024 Cross-referenced by PHPXref 0.7.1