[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

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

   1  <?php
   2  
   3  /**
   4   * bbPress Reply 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   * Return the unique id of the custom post type for replies
  17   *
  18   * @since 2.0.0 bbPress (r2857)
  19   *
  20   */
  21  function bbp_reply_post_type() {
  22      echo bbp_get_reply_post_type();
  23  }
  24      /**
  25       * Return the unique id of the custom post type for replies
  26       *
  27       * @since 2.0.0 bbPress (r2857)
  28       *
  29       *                        post type id
  30       * @return string The unique reply post type id
  31       */
  32  	function bbp_get_reply_post_type() {
  33  
  34          // Filter & return
  35          return apply_filters( 'bbp_get_reply_post_type', bbpress()->reply_post_type );
  36      }
  37  
  38  /**
  39   * Return array of labels used by the reply post type
  40   *
  41   * @since 2.5.0 bbPress (r5129)
  42   *
  43   * @return array
  44   */
  45  function bbp_get_reply_post_type_labels() {
  46  
  47      // Filter & return
  48      return (array) apply_filters( 'bbp_get_reply_post_type_labels', array(
  49          'name'                     => esc_attr__( 'Replies',                    'bbpress' ),
  50          'menu_name'                => esc_attr__( 'Replies',                    'bbpress' ),
  51          'singular_name'            => esc_attr_x( 'Reply', 'noun',              'bbpress' ),
  52          'all_items'                => esc_attr__( 'All Replies',                'bbpress' ),
  53          'add_new'                  => esc_attr__( 'Add New',                    'bbpress' ),
  54          'add_new_item'             => esc_attr__( 'Create New Reply',           'bbpress' ),
  55          'edit'                     => esc_attr__( 'Edit',                       'bbpress' ),
  56          'edit_item'                => esc_attr__( 'Edit Reply',                 'bbpress' ),
  57          'new_item'                 => esc_attr__( 'New Reply',                  'bbpress' ),
  58          'view'                     => esc_attr__( 'View Reply',                 'bbpress' ),
  59          'view_item'                => esc_attr__( 'View Reply',                 'bbpress' ),
  60          'view_items'               => esc_attr__( 'View Replies',               'bbpress' ),
  61          'search_items'             => esc_attr__( 'Search Replies',             'bbpress' ),
  62          'not_found'                => esc_attr__( 'No replies found',           'bbpress' ),
  63          'not_found_in_trash'       => esc_attr__( 'No replies found in Trash',  'bbpress' ),
  64          'filter_items_list'        => esc_attr__( 'Filter replies list',        'bbpress' ),
  65          'items_list'               => esc_attr__( 'Replies list',               'bbpress' ),
  66          'items_list_navigation'    => esc_attr__( 'Replies list navigation',    'bbpress' ),
  67          'parent_item_colon'        => esc_attr__( 'Parent Topic:',              'bbpress' ),
  68          'archives'                 => esc_attr__( 'Forum Replies',              'bbpress' ),
  69          'attributes'               => esc_attr__( 'Reply Attributes',           'bbpress' ),
  70          'insert_into_item'         => esc_attr__( 'Insert into reply',          'bbpress' ),
  71          'uploaded_to_this_item'    => esc_attr__( 'Uploaded to this reply',     'bbpress' ),
  72          'featured_image'           => esc_attr__( 'Reply Image',                'bbpress' ),
  73          'set_featured_image'       => esc_attr__( 'Set reply image',            'bbpress' ),
  74          'remove_featured_image'    => esc_attr__( 'Remove reply image',         'bbpress' ),
  75          'use_featured_image'       => esc_attr__( 'Use as reply image',         'bbpress' ),
  76          'item_published'           => esc_attr__( 'Reply published.',           'bbpress' ),
  77          'item_published_privately' => esc_attr__( 'Reply published privately.', 'bbpress' ),
  78          'item_reverted_to_draft'   => esc_attr__( 'Reply reverted to draft.',   'bbpress' ),
  79          'item_scheduled'           => esc_attr__( 'Reply scheduled.',           'bbpress' ),
  80          'item_updated'             => esc_attr__( 'Reply updated.',             'bbpress' )
  81      ) );
  82  }
  83  
  84  /**
  85   * Return array of reply post type rewrite settings
  86   *
  87   * @since 2.5.0 bbPress (r5129)
  88   *
  89   * @return array
  90   */
  91  function bbp_get_reply_post_type_rewrite() {
  92  
  93      // Filter & return
  94      return (array) apply_filters( 'bbp_get_reply_post_type_rewrite', array(
  95          'slug'       => bbp_get_reply_slug(),
  96          'with_front' => false
  97      ) );
  98  }
  99  
 100  /**
 101   * Return array of features the reply post type supports
 102   *
 103   * @since 2.5.0 bbPress (r5129)
 104   *
 105   * @return array
 106   */
 107  function bbp_get_reply_post_type_supports() {
 108  
 109      // Filter & return
 110      return (array) apply_filters( 'bbp_get_reply_post_type_supports', array(
 111          'title',
 112          'editor',
 113          'revisions'
 114      ) );
 115  }
 116  
 117  /** Reply Loop Functions ******************************************************/
 118  
 119  /**
 120   * The main reply loop. WordPress makes this easy for us
 121   *
 122   * @since 2.0.0 bbPress (r2553)
 123   *
 124   * @param array $args All the arguments supported by {@link WP_Query}
 125   * @return object Multidimensional array of reply information
 126   */
 127  function bbp_has_replies( $args = array() ) {
 128  
 129      /** Defaults **************************************************************/
 130  
 131      // Other defaults
 132      $default_reply_search   = bbp_sanitize_search_request( 'rs' );
 133      $default_post_parent    = ( bbp_is_single_topic() ) ? bbp_get_topic_id() : 'any';
 134      $default_post_type      = ( bbp_is_single_topic() && bbp_show_lead_topic() ) ? bbp_get_reply_post_type() : array( bbp_get_topic_post_type(), bbp_get_reply_post_type() );
 135      $default_thread_replies = (bool) ( bbp_is_single_topic() && bbp_thread_replies() );
 136  
 137      // Default query args
 138      $default = array(
 139          'post_type'              => $default_post_type,         // Only replies
 140          'post_parent'            => $default_post_parent,       // Of this topic
 141          'posts_per_page'         => bbp_get_replies_per_page(), // This many
 142          'paged'                  => bbp_get_paged(),            // On this page
 143          'orderby'                => 'date',                     // Sorted by date
 144          'order'                  => 'ASC',                      // Oldest to newest
 145          'hierarchical'           => $default_thread_replies,    // Hierarchical replies
 146          'ignore_sticky_posts'    => true,                       // Stickies not supported
 147          'update_post_term_cache' => false,                      // No terms to cache
 148  
 149          // Conditionally prime the cache for all related posts
 150          'update_post_family_cache' => true
 151      );
 152  
 153      // Only add 's' arg if searching for replies
 154      // See https://bbpress.trac.wordpress.org/ticket/2607
 155      if ( ! empty( $default_reply_search ) ) {
 156          $default['s'] = $default_reply_search;
 157      }
 158  
 159      // What are the default allowed statuses (based on user caps)
 160      if ( bbp_get_view_all( 'edit_others_replies' ) ) {
 161  
 162          // Default view=all statuses
 163          $post_statuses = array_keys( bbp_get_topic_statuses() );
 164  
 165          // Add support for private status
 166          if ( current_user_can( 'read_private_replies' ) ) {
 167              $post_statuses[] = bbp_get_private_status_id();
 168          }
 169  
 170          // Join post statuses together
 171          $default['post_status'] = $post_statuses;
 172  
 173      // Lean on the 'perm' query var value of 'readable' to provide statuses
 174      } else {
 175          $default['perm'] = 'readable';
 176      }
 177  
 178      /** Setup *****************************************************************/
 179  
 180      // Parse arguments against default values
 181      $r = bbp_parse_args( $args, $default, 'has_replies' );
 182  
 183      // Set posts_per_page value if replies are threaded
 184      $replies_per_page = (int) $r['posts_per_page'];
 185      if ( true === $r['hierarchical'] ) {
 186          $r['posts_per_page'] = -1;
 187      }
 188  
 189      // Get bbPress
 190      $bbp = bbpress();
 191  
 192      // Call the query
 193      $bbp->reply_query = new WP_Query( $r );
 194  
 195      // Maybe prime the post author caches
 196      if ( ! empty( $r['update_post_family_cache'] ) ) {
 197          bbp_update_post_family_caches( $bbp->reply_query->posts );
 198      }
 199  
 200      // Add pagination values to query object
 201      $bbp->reply_query->posts_per_page = (int) $replies_per_page;
 202      $bbp->reply_query->paged          = (int) $r['paged'];
 203  
 204      // Never home, regardless of what parse_query says
 205      $bbp->reply_query->is_home        = false;
 206  
 207      // Reset is_single if single topic
 208      if ( bbp_is_single_topic() ) {
 209          $bbp->reply_query->is_single = true;
 210      }
 211  
 212      // Only add reply to if query returned results
 213      if ( ! empty( $bbp->reply_query->found_posts ) ) {
 214  
 215          // Get reply to for each reply
 216          foreach ( $bbp->reply_query->posts as &$post ) {
 217  
 218              // Check for reply post type
 219              if ( bbp_get_reply_post_type() === $post->post_type ) {
 220                  $reply_to = bbp_get_reply_to( $post->ID );
 221  
 222                  // Make sure it's a reply to a reply
 223                  if ( empty( $reply_to ) || ( bbp_get_reply_topic_id( $post->ID ) === $reply_to ) ) {
 224                      $reply_to = 0;
 225                  }
 226  
 227                  // Add reply_to to the post object so we can walk it later
 228                  $post->reply_to = $reply_to;
 229              }
 230          }
 231      }
 232  
 233      // Only add pagination if query returned results
 234      if ( ! empty( $bbp->reply_query->found_posts ) && ! empty( $bbp->reply_query->posts_per_page ) ) {
 235  
 236          // Figure out total pages
 237          if ( true === $r['hierarchical'] ) {
 238              $walker      = new BBP_Walker_Reply;
 239              $total_pages = ceil( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) / $bbp->reply_query->posts_per_page );
 240          } else {
 241  
 242              // Total for pagination boundaries
 243              $total_pages = ( $bbp->reply_query->posts_per_page === $bbp->reply_query->found_posts )
 244                  ? 1
 245                  : ceil( $bbp->reply_query->found_posts / $bbp->reply_query->posts_per_page );
 246  
 247              // Pagination settings with filter
 248              $bbp_replies_pagination = apply_filters( 'bbp_replies_pagination', array(
 249                  'base'    => bbp_get_replies_pagination_base( bbp_get_topic_id() ),
 250                  'total'   => $total_pages,
 251                  'current' => $bbp->reply_query->paged
 252              ) );
 253  
 254              // Add pagination to query object
 255              $bbp->reply_query->pagination_links = bbp_paginate_links( $bbp_replies_pagination );
 256          }
 257      }
 258  
 259      // Filter & return
 260      return apply_filters( 'bbp_has_replies', $bbp->reply_query->have_posts(), $bbp->reply_query );
 261  }
 262  
 263  /**
 264   * Whether there are more replies available in the loop
 265   *
 266   * @since 2.0.0 bbPress (r2553)
 267   *
 268   * @return object Replies information
 269   */
 270  function bbp_replies() {
 271  
 272      // Put into variable to check against next
 273      $have_posts = bbpress()->reply_query->have_posts();
 274  
 275      // Reset the post data when finished
 276      if ( empty( $have_posts ) ) {
 277          wp_reset_postdata();
 278      }
 279  
 280      return $have_posts;
 281  }
 282  
 283  /**
 284   * Loads up the current reply in the loop
 285   *
 286   * @since 2.0.0 bbPress (r2553)
 287   *
 288   * @return object Reply information
 289   */
 290  function bbp_the_reply() {
 291      return bbpress()->reply_query->the_post();
 292  }
 293  
 294  /**
 295   * Output reply id
 296   *
 297   * @since 2.0.0 bbPress (r2553)
 298   *
 299   * @param $reply_id Optional. Used to check emptiness
 300   */
 301  function bbp_reply_id( $reply_id = 0 ) {
 302      echo bbp_get_reply_id( $reply_id );
 303  }
 304      /**
 305       * Return the id of the reply in a replies loop
 306       *
 307       * @since 2.0.0 bbPress (r2553)
 308       *
 309       * @param $reply_id Optional. Used to check emptiness
 310       * @return int The reply id
 311       */
 312  	function bbp_get_reply_id( $reply_id = 0 ) {
 313          $bbp      = bbpress();
 314          $wp_query = bbp_get_wp_query();
 315  
 316          // Easy empty checking
 317          if ( ! empty( $reply_id ) && is_numeric( $reply_id ) ) {
 318              $bbp_reply_id = $reply_id;
 319  
 320          // Currently inside a replies loop
 321          } elseif ( ! empty( $bbp->reply_query->in_the_loop ) && isset( $bbp->reply_query->post->ID ) ) {
 322              $bbp_reply_id = $bbp->reply_query->post->ID;
 323  
 324          // Currently inside a search loop
 325          } elseif ( ! empty( $bbp->search_query->in_the_loop ) && isset( $bbp->search_query->post->ID ) && bbp_is_reply( $bbp->search_query->post->ID ) ) {
 326              $bbp_reply_id = $bbp->search_query->post->ID;
 327  
 328          // Currently viewing a forum
 329          } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && ! empty( $bbp->current_reply_id ) ) {
 330              $bbp_reply_id = $bbp->current_reply_id;
 331  
 332          // Currently viewing a reply
 333          } elseif ( ( bbp_is_single_reply() || bbp_is_reply_edit() ) && isset( $wp_query->post->ID ) ) {
 334              $bbp_reply_id = $wp_query->post->ID;
 335  
 336          // Fallback
 337          } else {
 338              $bbp_reply_id = 0;
 339          }
 340  
 341          // Filter & return
 342          return (int) apply_filters( 'bbp_get_reply_id', $bbp_reply_id, $reply_id );
 343      }
 344  
 345  /**
 346   * Gets a reply
 347   *
 348   * @since 2.0.0 bbPress (r2787)
 349   *
 350   * @param int|object $reply reply id or reply object
 351   * @param string $output Optional. OBJECT, ARRAY_A, or ARRAY_N. Default = OBJECT
 352   * @param string $filter Optional Sanitation filter. See {@link sanitize_post()}
 353   * @return mixed Null if error or reply (in specified form) if success
 354   */
 355  function bbp_get_reply( $reply, $output = OBJECT, $filter = 'raw' ) {
 356  
 357      // Maybe get ID from empty or int
 358      if ( empty( $reply ) || is_numeric( $reply ) ) {
 359          $reply = bbp_get_reply_id( $reply );
 360      }
 361  
 362      // Bail if no post object
 363      $reply = get_post( $reply, OBJECT, $filter );
 364      if ( empty( $reply ) ) {
 365          return $reply;
 366      }
 367  
 368      // Bail if not correct post type
 369      if ( $reply->post_type !== bbp_get_reply_post_type() ) {
 370          return null;
 371      }
 372  
 373      // Default return value is OBJECT
 374      $retval = $reply;
 375  
 376      // Array A
 377      if ( $output === ARRAY_A ) {
 378          $retval = get_object_vars( $reply );
 379  
 380      // Array N
 381      } elseif ( $output === ARRAY_N ) {
 382          $retval = array_values( get_object_vars( $reply ) );
 383      }
 384  
 385      // Filter & return
 386      return apply_filters( 'bbp_get_reply', $retval, $reply, $output, $filter );
 387  }
 388  
 389  /**
 390   * Output the link to the reply in the reply loop
 391   *
 392   * @since 2.0.0 bbPress (r2553)
 393   *
 394   * @param int $reply_id Optional. Reply id
 395   */
 396  function bbp_reply_permalink( $reply_id = 0 ) {
 397      echo esc_url( bbp_get_reply_permalink( $reply_id ) );
 398  }
 399      /**
 400       * Return the link to the reply
 401       *
 402       * @since 2.0.0 bbPress (r2553)
 403       *
 404       * @param int $reply_id Optional. Reply id
 405       *                        and reply id
 406       * @return string Permanent link to reply
 407       */
 408  	function bbp_get_reply_permalink( $reply_id = 0 ) {
 409          $reply_id = bbp_get_reply_id( $reply_id );
 410  
 411          // Filter & return
 412          return apply_filters( 'bbp_get_reply_permalink', get_permalink( $reply_id ), $reply_id );
 413      }
 414  
 415  /**
 416   * Output the paginated url to the reply in the reply loop
 417   *
 418   * @since 2.0.0 bbPress (r2679)
 419   *
 420   * @param int $reply_id Optional. Reply id
 421   */
 422  function bbp_reply_url( $reply_id = 0 ) {
 423      echo esc_url( bbp_get_reply_url( $reply_id ) );
 424  }
 425      /**
 426       * Return the paginated url to the reply in the reply loop
 427       *
 428       * @since 2.0.0 bbPress (r2679)
 429       *
 430       * @param int $reply_id Optional. Reply id
 431       * @param string $redirect_to Optional. Pass a redirect value for use with
 432       *                              shortcodes and other fun things.
 433       * @return string Link to reply relative to paginated topic
 434       */
 435  	function bbp_get_reply_url( $reply_id = 0, $redirect_to = '' ) {
 436  
 437          // Set needed variables
 438          $reply_id = bbp_get_reply_id( $reply_id );
 439  
 440          // Juggle reply & topic IDs for unpretty URL formatting
 441          if ( bbp_is_reply( $reply_id ) ) {
 442              $topic_id = bbp_get_reply_topic_id( $reply_id );
 443              $topic    = bbp_get_topic( $topic_id );
 444          } elseif ( bbp_is_topic( $reply_id ) ) {
 445              $topic_id = bbp_get_topic_id( $reply_id );
 446              $topic    = bbp_get_topic( $topic_id );
 447              $reply_id = $topic_id;
 448          }
 449  
 450          // Hierarchical reply page
 451          if ( bbp_thread_replies() ) {
 452              $reply_page = 1;
 453  
 454          // Standard reply page
 455          } else {
 456              $reply_page = ceil( (int) bbp_get_reply_position( $reply_id, $topic_id ) / (int) bbp_get_replies_per_page() );
 457          }
 458  
 459          // Get links & URLS
 460          $reply_hash = '#post-' . $reply_id;
 461          $topic_link = bbp_get_topic_permalink( $topic_id, $redirect_to );
 462          $topic_url  = remove_query_arg( 'view', $topic_link );
 463  
 464          // Get vars needed to support pending topics with unpretty links
 465          $has_slug   = ! empty( $topic ) ? $topic->post_name : '';
 466          $pretty     = bbp_use_pretty_urls();
 467          $published  = ! bbp_is_topic_pending( $topic_id );
 468  
 469          // Don't include pagination if on first page
 470          if ( 1 >= $reply_page ) {
 471  
 472              // Pretty permalinks
 473              if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
 474                  $url = user_trailingslashit( $topic_url ) . $reply_hash;
 475  
 476              // Unpretty links
 477              } else {
 478                  $url = $topic_url . $reply_hash;
 479              }
 480  
 481          // Include pagination
 482          } else {
 483  
 484              // Pretty permalinks
 485              if ( ! empty( $has_slug ) && ! empty( $pretty ) && ! empty( $published ) ) {
 486                  $url = trailingslashit( $topic_url ) . trailingslashit( bbp_get_paged_slug() ) . $reply_page;
 487                  $url = user_trailingslashit( $url ) . $reply_hash;
 488  
 489              // Unpretty links
 490              } else {
 491                  $url = add_query_arg( 'paged', $reply_page, $topic_url ) . $reply_hash;
 492              }
 493          }
 494  
 495          // Add topic view query arg back to end if it is set
 496          if ( bbp_get_view_all() ) {
 497              $url = bbp_add_view_all( $url );
 498          }
 499  
 500          // Filter & return
 501          return apply_filters( 'bbp_get_reply_url', $url, $reply_id, $redirect_to );
 502      }
 503  
 504  /**
 505   * Output the title of the reply
 506   *
 507   * @since 2.0.0 bbPress (r2553)
 508   *
 509   * @param int $reply_id Optional. Reply id
 510   */
 511  function bbp_reply_title( $reply_id = 0 ) {
 512      echo bbp_get_reply_title( $reply_id );
 513  }
 514  
 515      /**
 516       * Return the title of the reply
 517       *
 518       * @since 2.0.0 bbPress (r2553)
 519       *
 520       * @param int $reply_id Optional. Reply id
 521       * @return string Title of reply
 522       */
 523  	function bbp_get_reply_title( $reply_id = 0 ) {
 524          $reply_id = bbp_get_reply_id( $reply_id );
 525          $title    = get_the_title( $reply_id );
 526  
 527          // Filter & return
 528          return apply_filters( 'bbp_get_reply_title', $title, $reply_id );
 529      }
 530  
 531      /**
 532       * Get empty reply title fallback.
 533       *
 534       * @since 2.5.0 bbPress (r5177)
 535       *
 536       * @param string $post_title Required. Reply Title
 537       * @param int $post_id Required. Reply ID
 538       * @return string Title of reply
 539       */
 540  	function bbp_get_reply_title_fallback( $post_title = '', $post_id = 0 ) {
 541  
 542          // Bail if title not empty, or post is not a reply
 543          if ( ! empty( $post_title ) || ! bbp_is_reply( $post_id ) ) {
 544              return $post_title;
 545          }
 546  
 547          // Get reply topic title.
 548          $topic_title = bbp_get_reply_topic_title( $post_id );
 549  
 550          // Get empty reply title fallback.
 551          $reply_title = sprintf( esc_html__( 'Reply To: %s', 'bbpress' ), $topic_title );
 552  
 553          // Filter & return
 554          return apply_filters( 'bbp_get_reply_title_fallback', $reply_title, $post_id, $topic_title );
 555      }
 556  
 557  /**
 558   * Output the content of the reply
 559   *
 560   * @since 2.0.0 bbPress (r2553)
 561   *
 562   * @param int $reply_id Optional. reply id
 563   */
 564  function bbp_reply_content( $reply_id = 0 ) {
 565      echo bbp_get_reply_content( $reply_id );
 566  }
 567      /**
 568       * Return the content of the reply
 569       *
 570       * @since 2.0.0 bbPress (r2780)
 571       *
 572       * @param int $reply_id Optional. reply id
 573       * @return string Content of the reply
 574       */
 575  	function bbp_get_reply_content( $reply_id = 0 ) {
 576          $reply_id = bbp_get_reply_id( $reply_id );
 577  
 578          // Check if password is required
 579          if ( post_password_required( $reply_id ) ) {
 580              return get_the_password_form();
 581          }
 582  
 583          $content = get_post_field( 'post_content', $reply_id );
 584  
 585          // Filter & return
 586          return apply_filters( 'bbp_get_reply_content', $content, $reply_id );
 587      }
 588  
 589  /**
 590   * Output the excerpt of the reply
 591   *
 592   * @since 2.0.0 bbPress (r2751)
 593   *
 594   * @param int $reply_id Optional. Reply id
 595   * @param int $length Optional. Length of the excerpt. Defaults to 100 letters
 596   */
 597  function bbp_reply_excerpt( $reply_id = 0, $length = 100 ) {
 598      echo bbp_get_reply_excerpt( $reply_id, $length );
 599  }
 600      /**
 601       * Return the excerpt of the reply
 602       *
 603       * @since 2.0.0 bbPress (r2751)
 604       *
 605       * @param int $reply_id Optional. Reply id
 606       * @param int $length Optional. Length of the excerpt. Defaults to 100
 607       *                     letters
 608       * @return string Reply Excerpt
 609       */
 610  	function bbp_get_reply_excerpt( $reply_id = 0, $length = 100 ) {
 611          $reply_id = bbp_get_reply_id( $reply_id );
 612          $length   = (int) $length;
 613          $excerpt  = get_post_field( 'post_excerpt', $reply_id );
 614  
 615          if ( empty( $excerpt ) ) {
 616              $excerpt = bbp_get_reply_content( $reply_id );
 617          }
 618  
 619          $excerpt = trim ( strip_tags( $excerpt ) );
 620  
 621          // Multibyte support
 622          if ( function_exists( 'mb_strlen' ) ) {
 623              $excerpt_length = mb_strlen( $excerpt );
 624          } else {
 625              $excerpt_length = strlen( $excerpt );
 626          }
 627  
 628          if ( ! empty( $length ) && ( $excerpt_length > $length ) ) {
 629              $excerpt  = mb_substr( $excerpt, 0, $length - 1 );
 630              $excerpt .= '&hellip;';
 631          }
 632  
 633          // Filter & return
 634          return apply_filters( 'bbp_get_reply_excerpt', $excerpt, $reply_id, $length );
 635      }
 636  
 637  /**
 638   * Output the post date and time of a reply
 639   *
 640   * @since 2.2.0 bbPress (r4155)
 641   *
 642   * @param int $reply_id Optional. Reply id.
 643   * @param bool $humanize Optional. Humanize output using time_since
 644   * @param bool $gmt Optional. Use GMT
 645   */
 646  function bbp_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
 647      echo bbp_get_reply_post_date( $reply_id, $humanize, $gmt );
 648  }
 649      /**
 650       * Return the post date and time of a reply
 651       *
 652       * @since 2.2.0 bbPress (r4155)
 653       *
 654       * @param int $reply_id Optional. Reply id.
 655       * @param bool $humanize Optional. Humanize output using time_since
 656       * @param bool $gmt Optional. Use GMT
 657       * @return string
 658       */
 659  	function bbp_get_reply_post_date( $reply_id = 0, $humanize = false, $gmt = false ) {
 660          $reply_id = bbp_get_reply_id( $reply_id );
 661  
 662          // 4 days, 4 hours ago
 663          if ( ! empty( $humanize ) ) {
 664              $gmt_s  = ! empty( $gmt ) ? 'G' : 'U';
 665              $date   = get_post_time( $gmt_s, $gmt, $reply_id );
 666              $time   = false; // For filter below
 667              $result = bbp_get_time_since( $date );
 668  
 669          // August 4, 2012 at 2:37 pm
 670          } else {
 671              $date   = get_post_time( get_option( 'date_format' ), $gmt, $reply_id, true );
 672              $time   = get_post_time( get_option( 'time_format' ), $gmt, $reply_id, true );
 673              $result = sprintf( _x( '%1$s at %2$s', 'date at time', 'bbpress' ), $date, $time );
 674          }
 675  
 676          // Filter & return
 677          return apply_filters( 'bbp_get_reply_post_date', $result, $reply_id, $humanize, $gmt, $date, $time );
 678      }
 679  
 680  /**
 681   * Append revisions to the reply content
 682   *
 683   * @since 2.0.0 bbPress (r2782)
 684   *
 685   * @param string $content Optional. Content to which we need to append the revisions to
 686   * @param int $reply_id Optional. Reply id
 687   * @return string Content with the revisions appended
 688   */
 689  function bbp_reply_content_append_revisions( $content = '', $reply_id = 0 ) {
 690  
 691      // Bail if in admin or feed
 692      if ( is_admin() || is_feed() ) {
 693          return $content;
 694      }
 695  
 696      // Validate the ID
 697      $reply_id = bbp_get_reply_id( $reply_id );
 698  
 699      // Filter & return
 700      return apply_filters( 'bbp_reply_append_revisions', $content . bbp_get_reply_revision_log( $reply_id ), $content, $reply_id );
 701  }
 702  
 703  /**
 704   * Output the revision log of the reply
 705   *
 706   * @since 2.0.0 bbPress (r2782)
 707   *
 708   * @param int $reply_id Optional. Reply id
 709   */
 710  function bbp_reply_revision_log( $reply_id = 0 ) {
 711      echo bbp_get_reply_revision_log( $reply_id );
 712  }
 713      /**
 714       * Return the formatted revision log of the reply
 715       *
 716       * @since 2.0.0 bbPress (r2782)
 717       *
 718       * @param int $reply_id Optional. Reply id
 719       * @return string Revision log of the reply
 720       */
 721  	function bbp_get_reply_revision_log( $reply_id = 0 ) {
 722  
 723          // Create necessary variables
 724          $reply_id = bbp_get_reply_id( $reply_id );
 725  
 726          // Show the topic reply log if this is a topic in a reply loop
 727          if ( bbp_is_topic( $reply_id ) ) {
 728              return bbp_get_topic_revision_log( $reply_id );
 729          }
 730  
 731          // Get the reply revision log (out of post meta
 732          $revision_log = bbp_get_reply_raw_revision_log( $reply_id );
 733  
 734          // Check reply and revision log exist
 735          if ( empty( $reply_id ) || empty( $revision_log ) || ! is_array( $revision_log ) ) {
 736              return false;
 737          }
 738  
 739          // Get the actual revisions
 740          $revisions = bbp_get_reply_revisions( $reply_id );
 741          if ( empty( $revisions ) ) {
 742              return false;
 743          }
 744  
 745          $r = "\n\n" . '<ul id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '" class="bbp-reply-revision-log">' . "\n\n";
 746  
 747          // Loop through revisions
 748          foreach ( (array) $revisions as $revision ) {
 749  
 750              if ( empty( $revision_log[ $revision->ID ] ) ) {
 751                  $author_id = $revision->post_author;
 752                  $reason    = '';
 753              } else {
 754                  $author_id = $revision_log[ $revision->ID ]['author'];
 755                  $reason    = $revision_log[ $revision->ID ]['reason'];
 756              }
 757  
 758              $author = bbp_get_author_link( array( 'size' => 14, 'link_text' => bbp_get_reply_author_display_name( $revision->ID ), 'post_id' => $revision->ID ) );
 759              $since  = bbp_get_time_since( bbp_convert_date( $revision->post_modified ) );
 760  
 761              $r .= "\t" . '<li id="bbp-reply-revision-log-' . esc_attr( $reply_id ) . '-item-' . esc_attr( $revision->ID ) . '" class="bbp-reply-revision-log-item">' . "\n";
 762              if ( ! empty( $reason ) ) {
 763                  $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s. Reason: %3$s', 'bbpress' ), esc_html( $since ), $author, esc_html( $reason ) ) . "\n";
 764              } else {
 765                  $r .= "\t\t" . sprintf( esc_html__( 'This reply was modified %1$s by %2$s.', 'bbpress' ), esc_html( $since ), $author ) . "\n";
 766              }
 767              $r .= "\t" . '</li>' . "\n";
 768  
 769          }
 770  
 771          $r .= "\n" . '</ul>' . "\n\n";
 772  
 773          // Filter & return
 774          return apply_filters( 'bbp_get_reply_revision_log', $r, $reply_id );
 775      }
 776          /**
 777           * Return the raw revision log of the reply
 778           *
 779           * @since 2.0.0 bbPress (r2782)
 780           *
 781           * @param int $reply_id Optional. Reply id
 782           * @return string Raw revision log of the reply
 783           */
 784  		function bbp_get_reply_raw_revision_log( $reply_id = 0 ) {
 785              $reply_id     = bbp_get_reply_id( $reply_id );
 786              $revision_log = get_post_meta( $reply_id, '_bbp_revision_log', true );
 787              $revision_log = ! empty( $revision_log )
 788                  ? $revision_log
 789                  : array();
 790  
 791              // Filter & return
 792              return apply_filters( 'bbp_get_reply_raw_revision_log', $revision_log, $reply_id );
 793          }
 794  
 795  /**
 796   * Return the revisions of the reply
 797   *
 798   * @since 2.0.0 bbPress (r2782)
 799   *
 800   * @param int $reply_id Optional. Reply id
 801   * @return string reply revisions
 802   */
 803  function bbp_get_reply_revisions( $reply_id = 0 ) {
 804      $reply_id  = bbp_get_reply_id( $reply_id );
 805      $revisions = wp_get_post_revisions( $reply_id, array( 'order' => 'ASC' ) );
 806  
 807      // Filter & return
 808      return apply_filters( 'bbp_get_reply_revisions', $revisions, $reply_id );
 809  }
 810  
 811  /**
 812   * Return the revision count of the reply
 813   *
 814   * @since 2.0.0 bbPress (r2782)
 815   *
 816   * @param int $reply_id Optional. Reply id
 817   * @param boolean $integer Optional. Whether or not to format the result
 818   * @return string reply revision count
 819   */
 820  function bbp_get_reply_revision_count( $reply_id = 0, $integer = false ) {
 821      $reply_id = bbp_get_reply_id( $reply_id );
 822      $count    = count( bbp_get_reply_revisions( $reply_id ) );
 823      $filter   = ( true === $integer )
 824          ? 'bbp_get_reply_revision_count_int'
 825          : 'bbp_get_reply_revision_count';
 826  
 827      return apply_filters( $filter, $count, $reply_id );
 828  }
 829  
 830  /**
 831   * Output the status of the reply
 832   *
 833   * @since 2.0.0 bbPress (r2667)
 834   *
 835   * @param int $reply_id Optional. Reply id
 836   */
 837  function bbp_reply_status( $reply_id = 0 ) {
 838      echo bbp_get_reply_status( $reply_id );
 839  }
 840      /**
 841       * Return the status of the reply
 842       *
 843       * @since 2.0.0 bbPress (r2667)
 844       *
 845       * @param int $reply_id Optional. Reply id
 846       * @return string Status of reply
 847       */
 848  	function bbp_get_reply_status( $reply_id = 0 ) {
 849          $reply_id = bbp_get_reply_id( $reply_id );
 850  
 851          // Filter & return
 852          return apply_filters( 'bbp_get_reply_status', get_post_status( $reply_id ), $reply_id );
 853      }
 854  
 855  /**
 856   * Is the reply publicly viewable?
 857   *
 858   * See bbp_get_public_reply_statuses() for public statuses.
 859   *
 860   * @since 2.6.0 bbPress (r6391)
 861   *
 862   * @param int $reply_id Optional. Reply id
 863   * @return bool True if public, false if not.
 864   */
 865  function bbp_is_reply_public( $reply_id = 0 ) {
 866      $reply_id  = bbp_get_reply_id( $reply_id );
 867      $status    = bbp_get_reply_status( $reply_id );
 868      $public    = bbp_get_public_reply_statuses();
 869      $is_public = in_array( $status, $public, true );
 870  
 871      // Filter & return
 872      return (bool) apply_filters( 'bbp_is_reply_public', $is_public, $reply_id );
 873  }
 874  
 875  /**
 876   * Is the reply not spam or deleted?
 877   *
 878   * @since 2.0.0 bbPress (r3496)
 879   * @since 2.6.0 bbPress (r6922) Returns false if topic is also not published
 880   *
 881   * @param int $reply_id Optional. Topic id
 882   * @return bool True if published, false if not.
 883   */
 884  function bbp_is_reply_published( $reply_id = 0 ) {
 885      $reply_id     = bbp_get_reply_id( $reply_id );
 886      $topic_id     = bbp_get_reply_topic_id( $reply_id );
 887      $status       = bbp_get_public_status_id();
 888      $topic_status = bbp_is_topic_published( $topic_id );
 889      $reply_status = ( bbp_get_reply_status( $reply_id ) === $status );
 890      $retval       = ( $reply_status && $topic_status );
 891  
 892      // Filter & return
 893      return (bool) apply_filters( 'bbp_is_reply_published', (bool) $retval, $reply_id );
 894  }
 895  
 896  /**
 897   * Is the reply marked as spam?
 898   *
 899   * @since 2.0.0 bbPress (r2740)
 900   *
 901   * @param int $reply_id Optional. Reply id
 902   * @return bool True if spam, false if not.
 903   */
 904  function bbp_is_reply_spam( $reply_id = 0 ) {
 905      $reply_id     = bbp_get_reply_id( $reply_id );
 906      $status       = bbp_get_spam_status_id();
 907      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 908  
 909      // Filter & return
 910      return (bool) apply_filters( 'bbp_is_reply_spam', (bool) $reply_status, $reply_id );
 911  }
 912  
 913  /**
 914   * Is the reply trashed?
 915   *
 916   * @since 2.0.0 bbPress (r2884)
 917   *
 918   * @param int $reply_id Optional. Topic id
 919   * @return bool True if spam, false if not.
 920   */
 921  function bbp_is_reply_trash( $reply_id = 0 ) {
 922      $reply_id     = bbp_get_reply_id( $reply_id );
 923      $status       = bbp_get_trash_status_id();
 924      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 925  
 926      // Filter & return
 927      return (bool) apply_filters( 'bbp_is_reply_trash', (bool) $reply_status, $reply_id );
 928  }
 929  
 930  /**
 931   * Is the reply pending?
 932   *
 933   * @since 2.6.0 bbPress (r5507)
 934   *
 935   * @param int $reply_id Optional. Topic id
 936   * @return bool True if pending, false if not.
 937   */
 938  function bbp_is_reply_pending( $reply_id = 0 ) {
 939      $reply_id     = bbp_get_reply_id( $reply_id );
 940      $status       = bbp_get_pending_status_id();
 941      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 942  
 943      // Filter & return
 944      return (bool) apply_filters( 'bbp_is_reply_pending', (bool) $reply_status, $reply_id );
 945  }
 946  
 947  /**
 948   * Is the reply private?
 949   *
 950   * @since 2.6.0 bbPress (r5507)
 951   *
 952   * @param int $reply_id Optional. Topic id
 953   * @return bool True if private, false if not.
 954   */
 955  function bbp_is_reply_private( $reply_id = 0 ) {
 956      $reply_id     = bbp_get_reply_id( $reply_id );
 957      $status       = bbp_get_private_status_id();
 958      $reply_status = bbp_get_reply_status( $reply_id ) === $status;
 959  
 960      // Filter & return
 961      return (bool) apply_filters( 'bbp_is_reply_private', (bool) $reply_status, $reply_id );
 962  }
 963  
 964  /**
 965   * Is the reply by an anonymous user?
 966   *
 967   * @since 2.0.0 bbPress (r2753)
 968   *
 969   * @param int $reply_id Optional. Reply id
 970   * @return bool True if the post is by an anonymous user, false if not.
 971   */
 972  function bbp_is_reply_anonymous( $reply_id = 0 ) {
 973      $reply_id = bbp_get_reply_id( $reply_id );
 974      $retval   = false;
 975  
 976      if ( ! bbp_get_reply_author_id( $reply_id ) ) {
 977          $retval = true;
 978  
 979      } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_name', true ) ) {
 980          $retval = true;
 981  
 982      } elseif ( get_post_meta( $reply_id, '_bbp_anonymous_email', true ) ) {
 983          $retval = true;
 984      }
 985  
 986      // Filter & return
 987      return (bool) apply_filters( 'bbp_is_reply_anonymous', $retval, $reply_id );
 988  }
 989  
 990  /**
 991   * Deprecated. Use bbp_reply_author_display_name() instead.
 992   *
 993   * Output the author of the reply
 994   *
 995   * @since 2.0.0 bbPress (r2667)
 996   *
 997   * @deprecated 2.5.0 bbPress (r5119)
 998   *
 999   * @param int $reply_id Optional. Reply id
1000   */
1001  function bbp_reply_author( $reply_id = 0 ) {
1002      echo bbp_get_reply_author( $reply_id );
1003  }
1004      /**
1005       * Deprecated. Use bbp_get_reply_author_display_name() instead.
1006       *
1007       * Return the author of the reply
1008       *
1009       * @since 2.0.0 bbPress (r2667)
1010       *
1011       * @deprecated 2.5.0 bbPress (r5119)
1012       *
1013       * @param int $reply_id Optional. Reply id
1014       * @return string Author of reply
1015       */
1016  	function bbp_get_reply_author( $reply_id = 0 ) {
1017          $reply_id = bbp_get_reply_id( $reply_id );
1018  
1019          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1020              $author = get_the_author_meta( 'display_name', bbp_get_reply_author_id( $reply_id ) );
1021          } else {
1022              $author = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1023          }
1024  
1025          // Filter & return
1026          return apply_filters( 'bbp_get_reply_author', $author, $reply_id );
1027      }
1028  
1029  /**
1030   * Output the author ID of the reply
1031   *
1032   * @since 2.0.0 bbPress (r2667)
1033   *
1034   * @param int $reply_id Optional. Reply id
1035   */
1036  function bbp_reply_author_id( $reply_id = 0 ) {
1037      echo bbp_get_reply_author_id( $reply_id );
1038  }
1039      /**
1040       * Return the author ID of the reply
1041       *
1042       * @since 2.0.0 bbPress (r2667)
1043       *
1044       * @param int $reply_id Optional. Reply id
1045       * @return string Author id of reply
1046       */
1047  	function bbp_get_reply_author_id( $reply_id = 0 ) {
1048          $reply_id  = bbp_get_reply_id( $reply_id );
1049          $author_id = get_post_field( 'post_author', $reply_id );
1050  
1051          // Filter & return
1052          return (int) apply_filters( 'bbp_get_reply_author_id', $author_id, $reply_id );
1053      }
1054  
1055  /**
1056   * Output the author display_name of the reply
1057   *
1058   * @since 2.0.0 bbPress (r2667)
1059   *
1060   * @param int $reply_id Optional. Reply id
1061   */
1062  function bbp_reply_author_display_name( $reply_id = 0 ) {
1063      echo bbp_get_reply_author_display_name( $reply_id );
1064  }
1065      /**
1066       * Return the author display_name of the reply
1067       *
1068       * @since 2.0.0 bbPress (r2667)
1069       *
1070       * @param int $reply_id Optional. Reply id
1071       * @return string The display name of the author of the reply
1072       */
1073  	function bbp_get_reply_author_display_name( $reply_id = 0 ) {
1074          $reply_id = bbp_get_reply_id( $reply_id );
1075  
1076          // User is not a guest
1077          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1078  
1079              // Get the author ID
1080              $author_id = bbp_get_reply_author_id( $reply_id );
1081  
1082              // Try to get a display name
1083              $author_name = get_the_author_meta( 'display_name', $author_id );
1084  
1085              // Fall back to user login
1086              if ( empty( $author_name ) ) {
1087                  $author_name = get_the_author_meta( 'user_login', $author_id );
1088              }
1089  
1090          // User does not have an account
1091          } else {
1092              $author_name = get_post_meta( $reply_id, '_bbp_anonymous_name', true );
1093          }
1094  
1095          // Fallback if nothing could be found
1096          if ( empty( $author_name ) ) {
1097              $author_name = bbp_get_fallback_display_name( $reply_id );
1098          }
1099  
1100          // Encode possible UTF8 display names
1101          if ( seems_utf8( $author_name ) === false ) {
1102              $author_name = utf8_encode( $author_name );
1103          }
1104  
1105          // Filter & return
1106          return apply_filters( 'bbp_get_reply_author_display_name', $author_name, $reply_id );
1107      }
1108  
1109  /**
1110   * Output the author avatar of the reply
1111   *
1112   * @since 2.0.0 bbPress (r2667)
1113   *
1114   * @param int $reply_id Optional. Reply id
1115   * @param int $size Optional. Size of the avatar. Defaults to 40
1116   */
1117  function bbp_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1118      echo bbp_get_reply_author_avatar( $reply_id, $size );
1119  }
1120      /**
1121       * Return the author avatar of the reply
1122       *
1123       * @since 2.0.0 bbPress (r2667)
1124       *
1125       * @param int $reply_id Optional. Reply id
1126       * @param int $size Optional. Size of the avatar. Defaults to 40
1127       * @return string Avatar of author of the reply
1128       */
1129  	function bbp_get_reply_author_avatar( $reply_id = 0, $size = 40 ) {
1130          $reply_id = bbp_get_reply_id( $reply_id );
1131          if ( ! empty( $reply_id ) ) {
1132              // Check for anonymous user
1133              if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1134                  $author_avatar = get_avatar( bbp_get_reply_author_id( $reply_id ), $size );
1135              } else {
1136                  $author_avatar = get_avatar( get_post_meta( $reply_id, '_bbp_anonymous_email', true ), $size );
1137              }
1138          } else {
1139              $author_avatar = '';
1140          }
1141  
1142          // Filter & return
1143          return apply_filters( 'bbp_get_reply_author_avatar', $author_avatar, $reply_id, $size );
1144      }
1145  
1146  /**
1147   * Output the author link of the reply
1148   *
1149   * @since 2.0.0 bbPress (r2717)
1150   *
1151   * @param array $args Optional. If it is an integer, it is used as reply id.
1152   */
1153  function bbp_reply_author_link( $args = array() ) {
1154      echo bbp_get_reply_author_link( $args );
1155  }
1156      /**
1157       * Return the author link of the reply
1158       *
1159       * @since 2.0.0 bbPress (r2717)
1160       *
1161       * @param array $args Optional. If an integer, it is used as reply id.
1162       * @return string Author link of reply
1163       */
1164  	function bbp_get_reply_author_link( $args = array() ) {
1165  
1166          // Parse arguments against default values
1167          $r = bbp_parse_args( $args, array(
1168              'post_id'    => 0,
1169              'link_title' => '',
1170              'type'       => 'both',
1171              'size'       => 80,
1172              'sep'        => '',
1173              'show_role'  => false
1174          ), 'get_reply_author_link' );
1175  
1176          // Default return value
1177          $author_link = '';
1178  
1179          // Used as reply_id
1180          $reply_id = is_numeric( $args )
1181              ? bbp_get_reply_id( $args )
1182              : bbp_get_reply_id( $r['post_id'] );
1183  
1184          // Reply ID is good
1185          if ( ! empty( $reply_id ) ) {
1186  
1187              // Get some useful reply information
1188              $author_url = bbp_get_reply_author_url( $reply_id );
1189              $anonymous  = bbp_is_reply_anonymous( $reply_id );
1190  
1191              // Tweak link title if empty
1192              if ( empty( $r['link_title'] ) ) {
1193                  $author = bbp_get_reply_author_display_name( $reply_id );
1194                  $title  = empty( $anonymous )
1195                      ? esc_attr__( "View %s's profile",  'bbpress' )
1196                      : esc_attr__( "Visit %s's website", 'bbpress' );
1197  
1198                  $link_title = sprintf( $title, $author );
1199  
1200              // Use what was passed if not
1201              } else {
1202                  $link_title = $r['link_title'];
1203              }
1204  
1205              // Setup title and author_links array
1206              $author_links = array();
1207              $link_title   = ! empty( $link_title )
1208                  ? ' title="' . esc_attr( $link_title ) . '"'
1209                  : '';
1210  
1211              // Get avatar (unescaped, because HTML)
1212              if ( ( 'avatar' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1213                  $author_links['avatar'] = bbp_get_reply_author_avatar( $reply_id, $r['size'] );
1214              }
1215  
1216              // Get display name (escaped, because never HTML)
1217              if ( ( 'name' === $r['type'] ) || ( 'both' === $r['type'] ) ) {
1218                  $author_links['name'] = esc_html( bbp_get_reply_author_display_name( $reply_id ) );
1219              }
1220  
1221              // Empty array
1222              $links  = array();
1223              $sprint = '<span %1$s>%2$s</span>';
1224  
1225              // Wrap each link
1226              foreach ( $author_links as $link => $link_text ) {
1227                  $link_class = ' class="bbp-author-' . esc_attr( $link ) . '"';
1228                  $links[]    = sprintf( $sprint, $link_class, $link_text );
1229              }
1230  
1231              // Juggle
1232              $author_links = $links;
1233              unset( $links );
1234  
1235              // Filter sections
1236              $sections    = apply_filters( 'bbp_get_reply_author_links', $author_links, $r, $args );
1237  
1238              // Assemble sections into author link
1239              $author_link = implode( $r['sep'], $sections );
1240  
1241              // Only wrap in link if profile exists
1242              if ( empty( $anonymous ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1243                  $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 );
1244              }
1245  
1246              // Role is not linked
1247              if ( true === $r['show_role'] ) {
1248                  $author_link .= bbp_get_reply_author_role( array( 'reply_id' => $reply_id ) );
1249              }
1250          }
1251  
1252          // Filter & return
1253          return apply_filters( 'bbp_get_reply_author_link', $author_link, $r, $args );
1254      }
1255  
1256  /**
1257   * Output the author url of the reply
1258   *
1259   * @since 2.0.0 bbPress (r2667)
1260   *
1261   * @param int $reply_id Optional. Reply id
1262   */
1263  function bbp_reply_author_url( $reply_id = 0 ) {
1264      echo esc_url( bbp_get_reply_author_url( $reply_id ) );
1265  }
1266      /**
1267       * Return the author url of the reply
1268       *
1269       * @since 2.0.0 bbPress (r2667)
1270       *
1271       * @param int $reply_id Optional. Reply id
1272       * @return string Author URL of the reply
1273       */
1274  	function bbp_get_reply_author_url( $reply_id = 0 ) {
1275          $reply_id = bbp_get_reply_id( $reply_id );
1276  
1277          // Check for anonymous user or non-existant user
1278          if ( ! bbp_is_reply_anonymous( $reply_id ) && bbp_user_has_profile( bbp_get_reply_author_id( $reply_id ) ) ) {
1279              $author_url = bbp_get_user_profile_url( bbp_get_reply_author_id( $reply_id ) );
1280          } else {
1281              $author_url = get_post_meta( $reply_id, '_bbp_anonymous_website', true );
1282              if ( empty( $author_url ) ) {
1283                  $author_url = '';
1284              }
1285          }
1286  
1287          // Filter & return
1288          return apply_filters( 'bbp_get_reply_author_url', $author_url, $reply_id );
1289      }
1290  
1291  /**
1292   * Output the reply author email address
1293   *
1294   * @since 2.0.0 bbPress (r3445)
1295   *
1296   * @param int $reply_id Optional. Reply id
1297   */
1298  function bbp_reply_author_email( $reply_id = 0 ) {
1299      echo bbp_get_reply_author_email( $reply_id );
1300  }
1301      /**
1302       * Return the reply author email address
1303       *
1304       * @since 2.0.0 bbPress (r3445)
1305       *
1306       * @param int $reply_id Optional. Reply id
1307       * @return string Reply author email address
1308       */
1309  	function bbp_get_reply_author_email( $reply_id = 0 ) {
1310          $reply_id = bbp_get_reply_id( $reply_id );
1311  
1312          // Not anonymous
1313          if ( ! bbp_is_reply_anonymous( $reply_id ) ) {
1314  
1315              // Use reply author email address
1316              $user_id      = bbp_get_reply_author_id( $reply_id );
1317              $user         = get_userdata( $user_id );
1318              $author_email = ! empty( $user->user_email ) ? $user->user_email : '';
1319  
1320          // Anonymous
1321          } else {
1322  
1323              // Get email from post meta
1324              $author_email = get_post_meta( $reply_id, '_bbp_anonymous_email', true );
1325  
1326              // Sanity check for missing email address
1327              if ( empty( $author_email ) ) {
1328                  $author_email = '';
1329              }
1330          }
1331  
1332          // Filter & return
1333          return apply_filters( 'bbp_get_reply_author_email', $author_email, $reply_id );
1334      }
1335  
1336  /**
1337   * Output the reply author role
1338   *
1339   * @since 2.1.0 bbPress (r3860)
1340   *
1341   * @param array $args Optional.
1342   */
1343  function bbp_reply_author_role( $args = array() ) {
1344      echo bbp_get_reply_author_role( $args );
1345  }
1346      /**
1347       * Return the reply author role
1348       *
1349       * @since 2.1.0 bbPress (r3860)
1350       *
1351       * @param array $args Optional.
1352       * @return string Reply author role
1353       */
1354  	function bbp_get_reply_author_role( $args = array() ) {
1355  
1356          // Parse arguments against default values
1357          $r = bbp_parse_args( $args, array(
1358              'reply_id' => 0,
1359              'class'    => false,
1360              'before'   => '<div class="bbp-author-role">',
1361              'after'    => '</div>'
1362          ), 'get_reply_author_role' );
1363  
1364          $reply_id    = bbp_get_reply_id( $r['reply_id'] );
1365          $role        = bbp_get_user_display_role( bbp_get_reply_author_id( $reply_id ) );
1366  
1367          // Backwards compatibilty with old 'class' argument
1368          if ( ! empty( $r['class'] ) ) {
1369              $author_role = sprintf( '%1$s<div class="%2$s">%3$s</div>%4$s', $r['before'], esc_attr( $r['class'] ), esc_html( $role ), $r['after'] );
1370  
1371          // Simpler before & after arguments
1372          // https://bbpress.trac.wordpress.org/ticket/2557
1373          } else {
1374              $author_role = $r['before'] . $role . $r['after'];
1375          }
1376  
1377          // Filter & return
1378          return apply_filters( 'bbp_get_reply_author_role', $author_role, $r, $args );
1379      }
1380  
1381  /**
1382   * Output the topic title a reply belongs to
1383   *
1384   * @since 2.0.0 bbPress (r2553)
1385   *
1386   * @param int $reply_id Optional. Reply id
1387   */
1388  function bbp_reply_topic_title( $reply_id = 0 ) {
1389      echo bbp_get_reply_topic_title( $reply_id );
1390  }
1391      /**
1392       * Return the topic title a reply belongs to
1393       *
1394       * @since 2.0.0 bbPress (r2553)
1395       *
1396       * @param int $reply_id Optional. Reply id
1397       * @return string The topic title of the reply
1398       */
1399  	function bbp_get_reply_topic_title( $reply_id = 0 ) {
1400          $reply_id = bbp_get_reply_id( $reply_id );
1401          $topic_id = bbp_get_reply_topic_id( $reply_id );
1402  
1403          // Filter & return
1404          return apply_filters( 'bbp_get_reply_topic_title', bbp_get_topic_title( $topic_id ), $reply_id );
1405      }
1406  
1407  /**
1408   * Output the topic id a reply belongs to
1409   *
1410   * @since 2.0.0 bbPress (r2553)
1411   *
1412   * @param int $reply_id Optional. Reply id
1413   */
1414  function bbp_reply_topic_id( $reply_id = 0 ) {
1415      echo bbp_get_reply_topic_id( $reply_id );
1416  }
1417      /**
1418       * Return the topic id a reply belongs to
1419       *
1420       * @since 2.0.0 bbPress (r2553)
1421       *
1422       * @param int $reply_id Optional. Reply id
1423       * @return int The topic id of the reply
1424       */
1425  	function bbp_get_reply_topic_id( $reply_id = 0 ) {
1426          $reply_id = bbp_get_reply_id( $reply_id );
1427          $topic_id = (int) get_post_field( 'post_parent', $reply_id );
1428  
1429          // Meta-data fallback
1430          if ( empty( $topic_id ) ) {
1431              $topic_id = (int) get_post_meta( $reply_id, '_bbp_topic_id', true );
1432          }
1433  
1434          // Filter
1435          if ( ! empty( $topic_id ) ) {
1436              $topic_id = (int) bbp_get_topic_id( $topic_id );
1437          }
1438  
1439          // Filter & return
1440          return (int) apply_filters( 'bbp_get_reply_topic_id', $topic_id, $reply_id );
1441      }
1442  
1443  /**
1444   * Output the forum id a reply belongs to
1445   *
1446   * @since 2.0.0 bbPress (r2679)
1447   *
1448   * @param int $reply_id Optional. Reply id
1449   */
1450  function bbp_reply_forum_id( $reply_id = 0 ) {
1451      echo bbp_get_reply_forum_id( $reply_id );
1452  }
1453      /**
1454       * Return the forum id a reply belongs to
1455       *
1456       * @since 2.0.0 bbPress (r2679)
1457       *
1458       * @param int $reply_id Optional. Reply id
1459       *                        id and reply id
1460       * @return int The forum id of the reply
1461       */
1462  	function bbp_get_reply_forum_id( $reply_id = 0 ) {
1463          $reply_id = bbp_get_reply_id( $reply_id );
1464          $topic_id = bbp_get_reply_topic_id( $reply_id );
1465          $forum_id = (int) get_post_field( 'post_parent', $topic_id );
1466  
1467          // Meta-data fallback
1468          if ( empty( $forum_id ) ) {
1469              $forum_id = (int) get_post_meta( $reply_id, '_bbp_forum_id', true );
1470          }
1471  
1472          // Filter
1473          if ( ! empty( $forum_id ) ) {
1474              $forum_id = (int) bbp_get_forum_id( $forum_id );
1475          }
1476  
1477          // Filter & return
1478          return (int) apply_filters( 'bbp_get_reply_forum_id', $forum_id, $reply_id );
1479      }
1480  
1481  /**
1482   * Output the ancestor reply id of a reply
1483   *
1484   * @since 2.4.0 bbPress (r4944)
1485   *
1486   * @param int $reply_id Optional. Reply id
1487   */
1488  function bbp_reply_ancestor_id( $reply_id = 0 ) {
1489      echo bbp_get_reply_ancestor_id( $reply_id );
1490  }
1491      /**
1492       * Return the ancestor reply id of a reply
1493       *
1494       * @since 2.4.0 bbPress (r4944)
1495       *
1496       * @param in $reply_id Reply id
1497       */
1498  	function bbp_get_reply_ancestor_id( $reply_id = 0 ) {
1499  
1500          // Validation
1501          $reply_id = bbp_get_reply_id( $reply_id );
1502          if ( empty( $reply_id ) ) {
1503              return false;
1504          }
1505  
1506          // Find highest reply ancestor
1507          $ancestor_id = $reply_id;
1508          while ( $parent_id = bbp_get_reply_to( $ancestor_id ) ) {
1509              if ( empty( $parent_id ) || ( $parent_id === $ancestor_id ) || ( bbp_get_reply_topic_id( $reply_id ) === $parent_id ) || ( $parent_id === $reply_id ) ) {
1510                  break;
1511              }
1512              $ancestor_id = $parent_id;
1513          }
1514  
1515          return (int) $ancestor_id;
1516      }
1517  
1518  /**
1519   * Output the reply to id of a reply
1520   *
1521   * @since 2.4.0 bbPress (r4944)
1522   *
1523   * @param int $reply_id Optional. Reply id
1524   */
1525  function bbp_reply_to( $reply_id = 0 ) {
1526      echo bbp_get_reply_to( $reply_id );
1527  }
1528      /**
1529       * Return the reply to id of a reply
1530       *
1531        * @since 2.4.0 bbPress (r4944)
1532       *
1533       * @param int $reply_id Optional. Reply id
1534       * @return int The parent reply id of the reply
1535       */
1536  	function bbp_get_reply_to( $reply_id = 0 ) {
1537  
1538          // Assume there is no reply_to set
1539          $reply_to = 0;
1540  
1541          // Check that reply_id is valid
1542          $reply_id = bbp_get_reply_id( $reply_id );
1543  
1544          // Get reply_to value
1545          if ( ! empty( $reply_id ) ) {
1546              $reply_to = (int) get_post_meta( $reply_id, '_bbp_reply_to', true );
1547          }
1548  
1549          // Filter & return
1550          return (int) apply_filters( 'bbp_get_reply_to', $reply_to, $reply_id );
1551      }
1552  
1553  /**
1554   * Output the link for the reply to
1555   *
1556   * @since 2.4.0 bbPress (r4944)
1557   *
1558   * @param array $args
1559   */
1560  function bbp_reply_to_link( $args = array() ) {
1561      echo bbp_get_reply_to_link( $args );
1562  }
1563  
1564      /**
1565       * Return the link for a reply to a reply
1566       *
1567       * @since 2.4.0 bbPress (r4944)
1568       *
1569       * @param array $args Arguments
1570       * @return string Link for a reply to a reply
1571       */
1572  	function bbp_get_reply_to_link( $args = array() ) {
1573  
1574          // Parse arguments against default values
1575          $r = bbp_parse_args( $args, array(
1576              'id'           => 0,
1577              'link_before'  => '',
1578              'link_after'   => '',
1579              'reply_text'   => esc_html_x( 'Reply', 'verb', 'bbpress' ),
1580              'depth'        => 0,
1581              'add_below'    => 'post',
1582              'respond_id'   => 'new-reply-' . bbp_get_topic_id(),
1583          ), 'get_reply_to_link' );
1584  
1585          // Get the reply to use it's ID and post_parent
1586          $reply    = bbp_get_reply( $r['id'] );
1587          $topic_id = bbp_get_reply_topic_id( $reply->ID );
1588  
1589          // Bail if no reply or user cannot reply
1590          if ( empty( $reply ) || empty( $topic_id ) || bbp_is_single_reply() || ! bbp_current_user_can_access_create_reply_form() ) {
1591              return;
1592          }
1593  
1594          // Build the URI and return value
1595          $uri = remove_query_arg( array( 'bbp_reply_to' ) );
1596          $uri = add_query_arg( array( 'bbp_reply_to' => $reply->ID ) );
1597          $uri = wp_nonce_url( $uri, 'respond_id_' . $reply->ID );
1598          $uri = $uri . '#new-post';
1599  
1600          // Only add onclick if replies are threaded
1601          if ( bbp_thread_replies() ) {
1602  
1603              // Array of classes to pass to moveForm
1604              $move_form = array(
1605                  $r['add_below'] . '-' . $reply->ID,
1606                  $reply->ID,
1607                  $r['respond_id'],
1608                  $reply->post_parent
1609              );
1610  
1611              // Build the onclick
1612              $onclick  = ' onclick="return addReply.moveForm(\'' . implode( "','", $move_form ) . '\');"';
1613  
1614          // No onclick if replies are not threaded
1615          } else {
1616              $onclick  = '';
1617          }
1618  
1619          // Add $uri to the array, to be passed through the filter
1620          $r['uri'] = $uri;
1621          $retval   = $r['link_before'] . '<a role="button" href="' . esc_url( $r['uri'] ) . '" class="bbp-reply-to-link"' . $onclick . '>' . $r['reply_text'] . '</a>' . $r['link_after'];
1622  
1623          // Filter & return
1624          return apply_filters( 'bbp_get_reply_to_link', $retval, $r, $args );
1625      }
1626  
1627  /**
1628   * Output the reply to a reply cancellation link
1629   *
1630   * @since 2.4.0 bbPress (r4944)
1631   */
1632  function bbp_cancel_reply_to_link( $text = '' ) {
1633      echo bbp_get_cancel_reply_to_link( $text );
1634  }
1635      /**
1636       * Return the cancellation link for a reply to a reply
1637       *
1638       * @since 2.4.0 bbPress (r4944)
1639       *
1640       * @param string $text The cancel text
1641       * @return string The cancellation link
1642       */
1643  	function bbp_get_cancel_reply_to_link( $text = '' ) {
1644  
1645          // Bail if not hierarchical or editing a reply
1646          if ( ! bbp_thread_replies() || bbp_is_reply_edit() ) {
1647              return;
1648          }
1649  
1650          // Set default text
1651          if ( empty( $text ) ) {
1652              $text = esc_html__( 'Cancel', 'bbpress' );
1653          }
1654  
1655          // Replying to...
1656          $reply_to = isset( $_GET['bbp_reply_to'] )
1657              ? (int) $_GET['bbp_reply_to']
1658              : 0;
1659  
1660          // Set visibility
1661          $style  = ! empty( $reply_to ) ? '' : ' style="display:none;"';
1662          $link   = remove_query_arg( array( 'bbp_reply_to', '_wpnonce' ) ) . "#post-{$reply_to}";
1663          $retval = sprintf( '<a href="%1$s" id="bbp-cancel-reply-to-link"%2$s>%3$s</a>', esc_url( $link ), $style, esc_html( $text ) );
1664  
1665          // Filter & return
1666          return apply_filters( 'bbp_get_cancel_reply_to_link', $retval, $link, $text );
1667      }
1668  
1669  /**
1670   * Output the numeric position of a reply within a topic
1671   *
1672   * @since 2.0.0 bbPress (r2984)
1673   *
1674   * @param int $reply_id Optional. Reply id
1675   * @param int $topic_id Optional. Topic id
1676   */
1677  function bbp_reply_position( $reply_id = 0, $topic_id = 0 ) {
1678      echo bbp_get_reply_position( $reply_id, $topic_id );
1679  }
1680      /**
1681       * Return the numeric position of a reply within a topic
1682       *
1683       * @since 2.0.0 bbPress (r2984)
1684       *
1685       * @param int $reply_id Optional. Reply id
1686       * @param int $topic_id Optional. Topic id
1687       * @return int Reply position
1688       */
1689  	function bbp_get_reply_position( $reply_id = 0, $topic_id = 0 ) {
1690  
1691          // Get required data
1692          $reply_id       = bbp_get_reply_id( $reply_id );
1693          $reply_position = get_post_field( 'menu_order', $reply_id );
1694  
1695          // Reply doesn't have a position so get the raw value
1696          if ( empty( $reply_position ) ) {
1697  
1698              // Get topic ID
1699              $topic_id = ! empty( $topic_id )
1700                  ? bbp_get_topic_id( $topic_id )
1701                  : bbp_get_reply_topic_id( $reply_id );
1702  
1703              // Post is not the topic
1704              if ( $reply_id !== $topic_id ) {
1705                  $reply_position = bbp_get_reply_position_raw( $reply_id, $topic_id );
1706  
1707                  // Update the reply position in the posts table so we'll never have
1708                  // to hit the DB again.
1709                  if ( ! empty( $reply_position ) ) {
1710                      bbp_update_reply_position( $reply_id, $reply_position );
1711                  }
1712  
1713              // Topic's position is always 0
1714              } else {
1715                  $reply_position = 0;
1716              }
1717          }
1718  
1719          // Bump the position by one if the topic is included in the reply loop
1720          if ( ! bbp_show_lead_topic() ) {
1721              $reply_position++;
1722          }
1723  
1724          // Filter & return
1725          return (int) apply_filters( 'bbp_get_reply_position', $reply_position, $reply_id, $topic_id );
1726      }
1727  
1728  /** Reply Admin Links *********************************************************/
1729  
1730  /**
1731   * Output admin links for reply
1732   *
1733   * @since 2.0.0 bbPress (r2667)
1734   *
1735   * @param array $args See {@link bbp_get_reply_admin_links()}
1736   */
1737  function bbp_reply_admin_links( $args = array() ) {
1738      echo bbp_get_reply_admin_links( $args );
1739  }
1740      /**
1741       * Return admin links for reply
1742       *
1743       * @since 2.0.0 bbPress (r2667)
1744       *
1745       * @param array $args This function supports these arguments:
1746       *  - id: Optional. Reply id
1747       *  - before: HTML before the links. Defaults to
1748       *             '<span class="bbp-admin-links">'
1749       *  - after: HTML after the links. Defaults to '</span>'
1750       *  - sep: Separator. Defaults to ' | '
1751       *  - links: Array of the links to display. By default, edit, trash,
1752       *            spam, reply move, and topic split links are displayed
1753       * @return string Reply admin links
1754       */
1755  	function bbp_get_reply_admin_links( $args = array() ) {
1756  
1757          // Parse arguments against default values
1758          $r = bbp_parse_args( $args, array(
1759              'id'     => 0,
1760              'before' => '<span class="bbp-admin-links">',
1761              'after'  => '</span>',
1762              'sep'    => ' | ',
1763              'links'  => array()
1764          ), 'get_reply_admin_links' );
1765  
1766          $r['id'] = bbp_get_reply_id( $r['id'] );
1767  
1768          // If post is a topic, return the topic admin links instead
1769          if ( bbp_is_topic( $r['id'] ) ) {
1770              return bbp_get_topic_admin_links( $args );
1771          }
1772  
1773          // If post is not a reply, return
1774          if ( ! bbp_is_reply( $r['id'] ) ) {
1775              return;
1776          }
1777  
1778          // If topic is trashed, do not show admin links
1779          if ( bbp_is_topic_trash( bbp_get_reply_topic_id( $r['id'] ) ) ) {
1780              return;
1781          }
1782  
1783          // If no links were passed, default to the standard
1784          if ( empty( $r['links'] ) ) {
1785              $r['links'] = apply_filters( 'bbp_reply_admin_links', array(
1786                  'edit'    => bbp_get_reply_edit_link   ( $r ),
1787                  'move'    => bbp_get_reply_move_link   ( $r ),
1788                  'split'   => bbp_get_topic_split_link  ( $r ),
1789                  'trash'   => bbp_get_reply_trash_link  ( $r ),
1790                  'spam'    => bbp_get_reply_spam_link   ( $r ),
1791                  'approve' => bbp_get_reply_approve_link( $r ),
1792                  'reply'   => bbp_get_reply_to_link     ( $r )
1793              ), $r['id'] );
1794          }
1795  
1796          // See if links need to be unset
1797          $reply_status = bbp_get_reply_status( $r['id'] );
1798          if ( in_array( $reply_status, array( bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id() ), true ) ) {
1799  
1800              // Spam link shouldn't be visible on trashed topics
1801              if ( bbp_get_trash_status_id() === $reply_status ) {
1802                  unset( $r['links']['spam'] );
1803  
1804              // Trash link shouldn't be visible on spam topics
1805              } elseif ( bbp_get_spam_status_id() === $reply_status ) {
1806                  unset( $r['links']['trash'] );
1807              }
1808          }
1809  
1810          // Process the admin links
1811          $links  = implode( $r['sep'], array_filter( $r['links'] ) );
1812          $retval = $r['before'] . $links . $r['after'];
1813  
1814          // Filter & return
1815          return apply_filters( 'bbp_get_reply_admin_links', $retval, $r, $args );
1816      }
1817  
1818  /**
1819   * Output the edit link of the reply
1820   *
1821   * @since 2.0.0 bbPress (r2740)
1822   *
1823   * @param array $args See {@link bbp_get_reply_edit_link()}
1824   */
1825  function bbp_reply_edit_link( $args = array() ) {
1826      echo bbp_get_reply_edit_link( $args );
1827  }
1828  
1829      /**
1830       * Return the edit link of the reply
1831       *
1832       * @since 2.0.0 bbPress (r2740)
1833       *
1834       * @param array $args This function supports these arguments:
1835       *  - id: Reply id
1836       *  - link_before: HTML before the link
1837       *  - link_after: HTML after the link
1838       *  - edit_text: Edit text. Defaults to 'Edit'
1839       * @return string Reply edit link
1840       */
1841  	function bbp_get_reply_edit_link( $args = array() ) {
1842  
1843          // Parse arguments against default values
1844          $r = bbp_parse_args( $args, array(
1845              'id'           => 0,
1846              'link_before'  => '',
1847              'link_after'   => '',
1848              'edit_text'    => esc_html__( 'Edit', 'bbpress' )
1849          ), 'get_reply_edit_link' );
1850  
1851          // Get reply
1852          $reply = bbp_get_reply( $r['id'] );
1853  
1854          // Bypass check if user has caps
1855          if ( ! current_user_can( 'edit_others_replies' ) ) {
1856  
1857              // User cannot edit or it is past the lock time
1858              if ( empty( $reply ) || ! current_user_can( 'edit_reply', $reply->ID ) || bbp_past_edit_lock( $reply->post_date_gmt ) ) {
1859                  return;
1860              }
1861          }
1862  
1863          // Get uri
1864          $uri = bbp_get_reply_edit_url( $r['id'] );
1865  
1866          // Bail if no uri
1867          if ( empty( $uri ) ) {
1868              return;
1869          }
1870  
1871          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-edit-link">' . $r['edit_text'] . '</a>' . $r['link_after'];
1872  
1873          // Filter & return
1874          return apply_filters( 'bbp_get_reply_edit_link', $retval, $r, $args );
1875      }
1876  
1877  /**
1878   * Output URL to the reply edit page
1879   *
1880   * @since 2.0.0 bbPress (r2753)
1881   *
1882   * @param int $reply_id Optional. Reply id
1883   */
1884  function bbp_reply_edit_url( $reply_id = 0 ) {
1885      echo esc_url( bbp_get_reply_edit_url( $reply_id ) );
1886  }
1887      /**
1888       * Return URL to the reply edit page
1889       *
1890       * @since 2.0.0 bbPress (r2753)
1891       *
1892       * @param int $reply_id Optional. Reply id
1893       * @return string Reply edit url
1894       */
1895  	function bbp_get_reply_edit_url( $reply_id = 0 ) {
1896  
1897          // Bail if no reply
1898          $reply = bbp_get_reply( $reply_id );
1899          if ( empty( $reply ) ) {
1900              return;
1901          }
1902  
1903          $reply_link = bbp_remove_view_all( bbp_get_reply_permalink( $reply_id ) );
1904  
1905          // Pretty permalinks, previously used `bbp_use_pretty_urls()`
1906          // https://bbpress.trac.wordpress.org/ticket/3054
1907          if ( false === strpos( $reply_link, '?' ) ) {
1908              $url = trailingslashit( $reply_link ) . bbp_get_edit_rewrite_id();
1909              $url = user_trailingslashit( $url );
1910  
1911          // Unpretty permalinks
1912          } else {
1913              $url = add_query_arg( array(
1914                  bbp_get_reply_post_type() => $reply->post_name,
1915                  bbp_get_edit_rewrite_id() => '1'
1916              ), $reply_link );
1917          }
1918  
1919          // Maybe add view all
1920          $url = bbp_add_view_all( $url );
1921  
1922          // Filter & return
1923          return apply_filters( 'bbp_get_reply_edit_url', $url, $reply_id );
1924      }
1925  
1926  /**
1927   * Output the trash link of the reply
1928   *
1929   * @since 2.0.0 bbPress (r2740)
1930   *
1931   * @param array $args See {@link bbp_get_reply_trash_link()}
1932   */
1933  function bbp_reply_trash_link( $args = array() ) {
1934      echo bbp_get_reply_trash_link( $args );
1935  }
1936  
1937      /**
1938       * Return the trash link of the reply
1939       *
1940       * @since 2.0.0 bbPress (r2740)
1941       *
1942       * @param array $args This function supports these arguments:
1943       *  - id: Reply id
1944       *  - link_before: HTML before the link
1945       *  - link_after: HTML after the link
1946       *  - sep: Separator
1947       *  - trash_text: Trash text
1948       *  - restore_text: Restore text
1949       *  - delete_text: Delete text
1950       * @return string Reply trash link
1951       */
1952  	function bbp_get_reply_trash_link( $args = array() ) {
1953  
1954          // Parse arguments against default values
1955          $r = bbp_parse_args( $args, array(
1956              'id'           => 0,
1957              'link_before'  => '',
1958              'link_after'   => '',
1959              'sep'          => ' | ',
1960              'trash_text'   => esc_html__( 'Trash',   'bbpress' ),
1961              'restore_text' => esc_html__( 'Restore', 'bbpress' ),
1962              'delete_text'  => esc_html__( 'Delete',  'bbpress' )
1963          ), 'get_reply_trash_link' );
1964  
1965          // Get reply
1966          $reply = bbp_get_reply( $r['id'] );
1967  
1968          // Bail if no reply or current user cannot delete
1969          if ( empty( $reply ) || ! current_user_can( 'delete_reply', $reply->ID ) ) {
1970              return;
1971          }
1972  
1973          $actions    = array();
1974          $trash_days = bbp_get_trash_days( bbp_get_reply_post_type() );
1975  
1976          // Trashed
1977          if ( bbp_is_reply_trash( $reply->ID ) ) {
1978              $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_reply_trash', 'sub_action' => 'untrash', 'reply_id' => $reply->ID ) ), 'untrash-' . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-restore-link">' . $r['restore_text'] . '</a>';
1979  
1980          // Trash
1981          } elseif ( ! empty( $trash_days ) ) {
1982              $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_reply_trash', 'sub_action' => 'trash',   'reply_id' => $reply->ID ) ), 'trash-'   . $reply->post_type . '_' . $reply->ID ) ) . '" class="bbp-reply-trash-link">'   . $r['trash_text']   . '</a>';
1983          }
1984  
1985          // No trash
1986          if ( bbp_is_reply_trash( $reply->ID ) || empty( $trash_days ) ) {
1987              $actions['delete']  = '<a title="' . esc_attr__( 'Delete this item permanently',     'bbpress' ) . '" href="' . esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'bbp_toggle_reply_trash', 'sub_action' => 'delete',  'reply_id' => $reply->ID ) ), 'delete-'  . $reply->post_type . '_' . $reply->ID ) ) . '" onclick="return confirm(\'' . esc_js( __( 'Are you sure you want to delete that permanently?', 'bbpress' ) ) . '\' );" class="bbp-reply-delete-link">' . $r['delete_text'] . '</a>';
1988          }
1989  
1990          // Process the admin links
1991          $retval = $r['link_before'] . implode( $r['sep'], $actions ) . $r['link_after'];
1992  
1993          // Filter & return
1994          return apply_filters( 'bbp_get_reply_trash_link', $retval, $r, $args );
1995      }
1996  
1997  /**
1998   * Output the spam link of the reply
1999   *
2000   * @since 2.0.0 bbPress (r2740)
2001   *
2002   * @param array $args See {@link bbp_get_reply_spam_link()}
2003   */
2004  function bbp_reply_spam_link( $args = array() ) {
2005      echo bbp_get_reply_spam_link( $args );
2006  }
2007  
2008      /**
2009       * Return the spam link of the reply
2010       *
2011       * @since 2.0.0 bbPress (r2740)
2012       *
2013       * @param array $args This function supports these arguments:
2014       *  - id: Reply id
2015       *  - link_before: HTML before the link
2016       *  - link_after: HTML after the link
2017       *  - spam_text: Spam text
2018       *  - unspam_text: Unspam text
2019       * @return string Reply spam link
2020       */
2021  	function bbp_get_reply_spam_link( $args = array() ) {
2022  
2023          // Parse arguments against default values
2024          $r = bbp_parse_args( $args, array(
2025              'id'           => 0,
2026              'link_before'  => '',
2027              'link_after'   => '',
2028              'spam_text'    => esc_html__( 'Spam',   'bbpress' ),
2029              'unspam_text'  => esc_html__( 'Unspam', 'bbpress' )
2030          ), 'get_reply_spam_link' );
2031  
2032          // Get reply
2033          $reply = bbp_get_reply( $r['id'] );
2034  
2035          // Bail if no reply or current user cannot moderate
2036          if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2037              return;
2038          }
2039  
2040          $display = bbp_is_reply_spam( $reply->ID ) ? $r['unspam_text'] : $r['spam_text'];
2041          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_reply_spam', 'reply_id' => $reply->ID ) );
2042          $uri     = wp_nonce_url( $uri, 'spam-reply_' . $reply->ID );
2043          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-spam-link">' . $display . '</a>' . $r['link_after'];
2044  
2045          // Filter & return
2046          return apply_filters( 'bbp_get_reply_spam_link', $retval, $r, $args );
2047      }
2048  
2049  /**
2050   * Move reply link
2051   *
2052   * Output the move link of the reply
2053   *
2054   * @since 2.3.0 bbPress (r4521)
2055   *
2056   * @param array $args See {@link bbp_get_reply_move_link()}
2057   */
2058  function bbp_reply_move_link( $args = array() ) {
2059      echo bbp_get_reply_move_link( $args );
2060  }
2061  
2062      /**
2063       * Get move reply link
2064       *
2065       * Return the move link of the reply
2066       *
2067       * @since 2.3.0 bbPress (r4521)
2068       *
2069       * @param array $args This function supports these arguments:
2070       *  - id: Reply id
2071       *  - link_before: HTML before the link
2072       *  - link_after: HTML after the link
2073       *  - move_text: Move text
2074       *  - move_title: Move title attribute
2075       * @return string Reply move link
2076       */
2077  	function bbp_get_reply_move_link( $args = array() ) {
2078  
2079          // Parse arguments against default values
2080          $r = bbp_parse_args( $args, array(
2081              'id'          => 0,
2082              'link_before' => '',
2083              'link_after'  => '',
2084              'split_text'  => esc_html__( 'Move',            'bbpress' ),
2085              'split_title' => esc_attr__( 'Move this reply', 'bbpress' )
2086          ), 'get_reply_move_link' );
2087  
2088          // Get IDs
2089          $reply_id = bbp_get_reply_id( $r['id'] );
2090          $topic_id = bbp_get_reply_topic_id( $reply_id );
2091  
2092          // Bail if no reply ID or user cannot moderate
2093          if ( empty( $reply_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2094              return;
2095          }
2096  
2097          $uri = add_query_arg( array(
2098              'action'   => 'move',
2099              'reply_id' => $reply_id
2100          ), bbp_get_reply_edit_url( $reply_id ) );
2101  
2102          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-reply-move-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2103  
2104          // Filter & return
2105          return apply_filters( 'bbp_get_reply_move_link', $retval, $r, $args );
2106      }
2107  
2108  /**
2109   * Split topic link
2110   *
2111   * Output the split link of the topic (but is bundled with each reply)
2112   *
2113   * @since 2.0.0 bbPress (r2756)
2114   *
2115   * @param array $args See {@link bbp_get_topic_split_link()}
2116   */
2117  function bbp_topic_split_link( $args = array() ) {
2118      echo bbp_get_topic_split_link( $args );
2119  }
2120  
2121      /**
2122       * Get split topic link
2123       *
2124       * Return the split link of the topic (but is bundled with each reply)
2125       *
2126       * @since 2.0.0 bbPress (r2756)
2127       *
2128       * @param array $args This function supports these arguments:
2129       *  - id: Reply id
2130       *  - link_before: HTML before the link
2131       *  - link_after: HTML after the link
2132       *  - split_text: Split text
2133       *  - split_title: Split title attribute
2134       * @return string Topic split link
2135       */
2136  	function bbp_get_topic_split_link( $args = array() ) {
2137  
2138          // Parse arguments against default values
2139          $r = bbp_parse_args( $args, array(
2140              'id'          => 0,
2141              'link_before' => '',
2142              'link_after'  => '',
2143              'split_text'  => esc_html__( 'Split',                           'bbpress' ),
2144              'split_title' => esc_attr__( 'Split the topic from this reply', 'bbpress' )
2145          ), 'get_topic_split_link' );
2146  
2147          // Get IDs
2148          $reply_id = bbp_get_reply_id( $r['id'] );
2149          $topic_id = bbp_get_reply_topic_id( $reply_id );
2150  
2151          // Bail if no reply/topic ID, or user cannot moderate
2152          if ( empty( $reply_id ) || empty( $topic_id ) || ! current_user_can( 'moderate', $topic_id ) ) {
2153              return;
2154          }
2155  
2156          $uri = add_query_arg( array(
2157              'action'   => 'split',
2158              'reply_id' => $reply_id
2159          ), bbp_get_topic_edit_url( $topic_id ) );
2160  
2161          $retval = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" title="' . $r['split_title'] . '" class="bbp-topic-split-link">' . $r['split_text'] . '</a>' . $r['link_after'];
2162  
2163          // Filter & return
2164          return apply_filters( 'bbp_get_topic_split_link', $retval, $r, $args );
2165      }
2166  
2167  /**
2168   * Output the approve link of the reply
2169   *
2170   * @since 2.6.0 bbPress (r5507)
2171   *
2172   * @param array $args See {@link bbp_get_reply_approve_link()}
2173   */
2174  function bbp_reply_approve_link( $args = array() ) {
2175      echo bbp_get_reply_approve_link( $args );
2176  }
2177  
2178      /**
2179       * Return the approve link of the reply
2180       *
2181       * @since 2.6.0 bbPress (r5507)
2182       *
2183       * @param array $args This function supports these args:
2184       *  - id: Optional. Reply id
2185       *  - link_before: Before the link
2186       *  - link_after: After the link
2187       *  - sep: Separator between links
2188       *  - approve_text: Approve text
2189       *  - unapprove_text: Unapprove text
2190       * @return string Reply approve link
2191       */
2192  	function bbp_get_reply_approve_link( $args = array() ) {
2193  
2194          // Parse arguments against default values
2195          $r = bbp_parse_args( $args, array(
2196              'id'             => 0,
2197              'link_before'    => '',
2198              'link_after'     => '',
2199              'sep'            => ' | ',
2200              'approve_text'   => _x( 'Approve',   'Pending Status', 'bbpress' ),
2201              'unapprove_text' => _x( 'Unapprove', 'Pending Status', 'bbpress' )
2202          ), 'get_reply_approve_link' );
2203  
2204          // Get reply
2205          $reply = bbp_get_reply( $r['id'] );
2206  
2207          // Bail if no reply or current user cannot moderate
2208          if ( empty( $reply ) || ! current_user_can( 'moderate', $reply->ID ) ) {
2209              return;
2210          }
2211  
2212          $display = bbp_is_reply_pending( $reply->ID ) ? $r['approve_text'] : $r['unapprove_text'];
2213          $uri     = add_query_arg( array( 'action' => 'bbp_toggle_reply_approve', 'reply_id' => $reply->ID ) );
2214          $uri     = wp_nonce_url( $uri, 'approve-reply_' . $reply->ID );
2215          $retval  = $r['link_before'] . '<a href="' . esc_url( $uri ) . '" class="bbp-reply-approve-link">' . $display . '</a>' . $r['link_after'];
2216  
2217          // Filter & return
2218          return apply_filters( 'bbp_get_reply_approve_link', $retval, $r, $args );
2219      }
2220  
2221  /**
2222   * Output the row class of a reply
2223   *
2224   * @since 2.0.0 bbPress (r2678)
2225   *
2226   * @param int $reply_id Optional. Reply ID
2227   * @param array Extra classes you can pass when calling this function
2228   */
2229  function bbp_reply_class( $reply_id = 0, $classes = array() ) {
2230      echo bbp_get_reply_class( $reply_id, $classes );
2231  }
2232      /**
2233       * Return the row class of a reply
2234       *
2235       * @since 2.0.0 bbPress (r2678)
2236       *
2237       * @param int $reply_id Optional. Reply ID
2238       * @param array Extra classes you can pass when calling this function
2239       * @return string Row class of the reply
2240       */
2241  	function bbp_get_reply_class( $reply_id = 0, $classes = array() ) {
2242          $bbp       = bbpress();
2243          $reply_id  = bbp_get_reply_id( $reply_id );
2244          $topic_id  = bbp_get_reply_topic_id( $reply_id );
2245          $forum_id  = bbp_get_reply_forum_id( $reply_id );
2246          $author_id = bbp_get_reply_author_id( $reply_id );
2247          $reply_pos = bbp_get_reply_position( $reply_id, true );
2248          $classes   = array_filter( (array) $classes );
2249          $count     = isset( $bbp->reply_query->current_post )
2250              ? (int) $bbp->reply_query->current_post
2251              : 1;
2252  
2253          //  Stripes
2254          $even_odd = ( $count % 2 )
2255              ? 'even'
2256              : 'odd';
2257  
2258          // Forum moderator replied to topic
2259          $forum_moderator = ( bbp_is_user_forum_moderator( $author_id, $forum_id ) === $author_id )
2260              ? 'forum-mod'
2261              : '';
2262  
2263          // Topic author replied to others
2264          $topic_author = ( bbp_get_topic_author_id( $topic_id ) === $author_id )
2265              ? 'topic-author'
2266              : '';
2267  
2268          // Get reply classes
2269          $reply_classes = array(
2270              'loop-item-'          . $count,
2271              'user-id-'            . $author_id,
2272              'bbp-parent-forum-'   . $forum_id,
2273              'bbp-parent-topic-'   . $topic_id,
2274              'bbp-reply-position-' . $reply_pos,
2275              $even_odd,
2276              $topic_author,
2277              $forum_moderator
2278          );
2279  
2280          // Run the topic classes through the post-class filters, which also
2281          // handles the escaping of each individual class.
2282          $post_classes = get_post_class( array_merge( $classes, $reply_classes ), $reply_id );
2283  
2284          // Filter
2285          $new_classes  = apply_filters( 'bbp_get_reply_class', $post_classes, $reply_id, $classes );
2286  
2287          // Return
2288          return 'class="' . implode( ' ', $new_classes ) . '"';
2289      }
2290  
2291  /** Pagination ****************************************************************/
2292  
2293  /**
2294   * Return the base URL used inside of pagination links
2295   *
2296   * @since 2.6.0 bbPress (r6679)
2297   *
2298   * @param int $topic_id
2299   * @return string
2300   */
2301  function bbp_get_replies_pagination_base( $topic_id = 0 ) {
2302  
2303      // If pretty permalinks are enabled, make our pagination pretty
2304      if ( bbp_use_pretty_urls() && ! bbp_is_topic_pending( $topic_id )) {
2305  
2306          // User's replies
2307          if ( bbp_is_single_user_replies() ) {
2308              $base = bbp_get_user_replies_created_url( bbp_get_displayed_user_id() );
2309  
2310          // Root profile page
2311          } elseif ( bbp_is_single_user() ) {
2312              $base = bbp_get_user_profile_url( bbp_get_displayed_user_id() );
2313  
2314          // Page or single post
2315          } elseif ( is_page() || is_single() ) {
2316              $base = get_permalink();
2317  
2318          // Single topic
2319          } else {
2320              $base = get_permalink( $topic_id );
2321          }
2322  
2323          $base = trailingslashit( $base ) . user_trailingslashit( bbp_get_paged_slug() . '/%#%/' );
2324  
2325      // Unpretty permalinks
2326      } else {
2327          $base = add_query_arg( 'paged', '%#%' );
2328      }
2329  
2330      // Filter & return
2331      return apply_filters( 'bbp_get_replies_pagination_base', $base, $topic_id );
2332  }
2333  
2334  /**
2335   * Output the topic pagination count
2336   *
2337   * The results are unescaped by design, to allow them to be filtered freely via
2338   * the 'bbp_get_topic_pagination_count' filter.
2339   *
2340   * @since 2.0.0 bbPress (r2519)
2341   *
2342   */
2343  function bbp_topic_pagination_count() {
2344      echo bbp_get_topic_pagination_count();
2345  }
2346      /**
2347       * Return the topic pagination count
2348       *
2349       * @since 2.0.0 bbPress (r2519)
2350       *
2351       * @return string Topic pagination count
2352       */
2353  	function bbp_get_topic_pagination_count() {
2354          $bbp = bbpress();
2355  
2356          // Define local variable(s)
2357          $retstr = '';
2358  
2359          // Set pagination values
2360          $count_int = intval( $bbp->reply_query->post_count     );
2361          $total_int = intval( $bbp->reply_query->found_posts    );
2362          $ppp_int   = intval( $bbp->reply_query->posts_per_page );
2363          $start_int = intval( ( $bbp->reply_query->paged - 1 ) * $ppp_int ) + 1;
2364          $to_int    = intval( ( $start_int + ( $ppp_int - 1 ) > $total_int )
2365              ? $total_int
2366              : $start_int + ( $ppp_int - 1 ) );
2367  
2368          // Format numbers for display
2369          $count_num = bbp_number_format( $count_int );
2370          $total_num = bbp_number_format( $total_int );
2371          $from_num  = bbp_number_format( $start_int );
2372          $to_num    = bbp_number_format( $to_int    );
2373  
2374          // We are threading replies
2375          if ( bbp_thread_replies() ) {
2376              $walker  = new BBP_Walker_Reply;
2377              $threads = absint( $walker->get_number_of_root_elements( $bbp->reply_query->posts ) - 1 );
2378              $retstr  = sprintf( _n( 'Viewing %1$s reply thread', 'Viewing %1$s reply threads', $threads, 'bbpress' ), bbp_number_format( $threads ) );
2379  
2380          // We are not including the lead topic
2381          } elseif ( bbp_show_lead_topic() ) {
2382  
2383              // Several replies in a topic with a single page
2384              if ( empty( $to_num ) ) {
2385                  $retstr = sprintf( _n( 'Viewing %1$s reply', 'Viewing %1$s replies', $total_int, 'bbpress' ), $total_num );
2386  
2387              // Several replies in a topic with several pages
2388              } else {
2389                  $retstr = sprintf( _n( 'Viewing %2$s replies (of %4$s total)', 'Viewing %1$s replies - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num );
2390              }
2391  
2392          // We are including the lead topic
2393          } else {
2394  
2395              // Several posts in a topic with a single page
2396              if ( empty( $to_num ) ) {
2397                  $retstr = sprintf( _n( 'Viewing %1$s post', 'Viewing %1$s posts', $total_int, 'bbpress' ), $total_num );
2398  
2399              // Several posts in a topic with several pages
2400              } else {
2401                  $retstr = sprintf( _n( 'Viewing %2$s post (of %4$s total)', 'Viewing %1$s posts - %2$s through %3$s (of %4$s total)', $count_int, 'bbpress' ), $count_num, $from_num, $to_num, $total_num );
2402              }
2403          }
2404  
2405          // Escape results of _n()
2406          $retstr = esc_html( $retstr );
2407  
2408          // Filter & return
2409          return apply_filters( 'bbp_get_topic_pagination_count', $retstr );
2410      }
2411  
2412  /**
2413   * Output topic pagination links
2414   *
2415   * @since 2.0.0 bbPress (r2519)
2416   */
2417  function bbp_topic_pagination_links() {
2418      echo bbp_get_topic_pagination_links();
2419  }
2420      /**
2421       * Return topic pagination links
2422       *
2423       * @since 2.0.0 bbPress (r2519)
2424       *
2425       * @return string Topic pagination links
2426       */
2427  	function bbp_get_topic_pagination_links() {
2428          $bbp = bbpress();
2429  
2430          if ( ! isset( $bbp->reply_query->pagination_links ) || empty( $bbp->reply_query->pagination_links ) ) {
2431              return false;
2432          }
2433  
2434          // Filter & return
2435          return apply_filters( 'bbp_get_topic_pagination_links', $bbp->reply_query->pagination_links );
2436      }
2437  
2438  /** Forms *********************************************************************/
2439  
2440  /**
2441   * Output the value of reply content field
2442   *
2443   * @since 2.0.0 bbPress (r3130)
2444   */
2445  function bbp_form_reply_content() {
2446      echo bbp_get_form_reply_content();
2447  }
2448      /**
2449       * Return the value of reply content field
2450       *
2451       * @since 2.0.0 bbPress (r3130)
2452       *
2453       * @return string Value of reply content field
2454       */
2455  	function bbp_get_form_reply_content() {
2456  
2457          // Get _POST data
2458          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_content'] ) ) {
2459              $reply_content = wp_unslash( $_POST['bbp_reply_content'] );
2460  
2461          // Get edit data
2462          } elseif ( bbp_is_reply_edit() ) {
2463              $reply_content = bbp_get_global_post_field( 'post_content', 'raw' );
2464  
2465          // No data
2466          } else {
2467              $reply_content = '';
2468          }
2469  
2470          // Filter & return
2471          return apply_filters( 'bbp_get_form_reply_content', $reply_content );
2472      }
2473  
2474  /**
2475   * Output the value of the reply to field
2476   *
2477   * @since 2.4.0 bbPress (r4944)
2478   */
2479  function bbp_form_reply_to() {
2480      echo bbp_get_form_reply_to();
2481  }
2482  
2483      /**
2484       * Return the value of reply to field
2485       *
2486       * @since 2.4.0 bbPress (r4944)
2487       *
2488       * @return string Value of reply to field
2489       */
2490  	function bbp_get_form_reply_to() {
2491  
2492          // Set initial value
2493          $reply_to = 0;
2494  
2495          // Get $_REQUEST data
2496          if ( bbp_is_reply_form_post_request() && isset( $_REQUEST['bbp_reply_to'] ) ) {
2497              $reply_to = bbp_validate_reply_to( $_REQUEST['bbp_reply_to'] );
2498          }
2499  
2500          // If empty, get from meta
2501          if ( empty( $reply_to ) ) {
2502              $reply_to = bbp_get_reply_to();
2503          }
2504  
2505          // Filter & return
2506          return apply_filters( 'bbp_get_form_reply_to', $reply_to );
2507      }
2508  
2509  /**
2510   * Output a select box allowing to pick which reply an existing hierarchical
2511   * reply belongs to.
2512   *
2513   * @since 2.6.0 bbPress (r5387)
2514   *
2515   * @param int $reply_id
2516   */
2517  function bbp_reply_to_dropdown( $reply_id = 0 ) {
2518      echo bbp_get_reply_to_dropdown( $reply_id );
2519  }
2520      /**
2521       * Return a select box allowing to pick which topic/reply a reply belongs.
2522       *
2523       * @since 2.6.0 bbPress (r5387)
2524       *
2525       * @param int $reply_id
2526       *
2527       * @return string The dropdown
2528       */
2529  	function bbp_get_reply_to_dropdown( $reply_id = 0 ) {
2530  
2531          // Validate the reply data
2532          $reply_id = bbp_get_reply_id( $reply_id );
2533          $reply_to = bbp_get_reply_to( $reply_id );
2534          $topic_id = bbp_get_reply_topic_id( $reply_id );
2535  
2536          // Get the replies
2537          $posts = get_posts( array(
2538              'post_type'   => bbp_get_reply_post_type(),
2539              'post_status' => bbp_get_public_status_id(),
2540              'post_parent' => $topic_id,
2541              'numberposts' => -1,
2542              'orderby'     => 'menu_order',
2543              'order'       => 'ASC',
2544          ) );
2545  
2546          // Append `reply_to` for each reply so it can be walked
2547          foreach ( $posts as &$post ) {
2548  
2549              // Check for reply post type
2550              $_reply_to = bbp_get_reply_to( $post->ID );
2551  
2552              // Make sure it's a reply to a reply
2553              if ( empty( $_reply_to ) || ( $topic_id === $_reply_to ) ) {
2554                  $_reply_to = 0;
2555              }
2556  
2557              // Add reply_to to the post object so we can walk it later
2558              $post->reply_to = $_reply_to;
2559          }
2560  
2561          // Default "None" text
2562          $show_none = ( 0 === $reply_id )
2563              ? esc_attr_x( 'None', 'Default reply to dropdown text', 'bbpress' )
2564              : sprintf( esc_attr__( '%1$s - %2$s', 'bbpress' ), $topic_id, bbp_get_topic_title( $topic_id ) );
2565  
2566          // Get the dropdown and return it
2567          $retval = bbp_get_dropdown( array(
2568              'show_none'    => $show_none,
2569              'select_id'    => 'bbp_reply_to',
2570              'select_class' => 'bbp_dropdown',
2571              'exclude'      => $reply_id,
2572              'selected'     => $reply_to,
2573              'post_parent'  => $topic_id,
2574              'post_type'    => bbp_get_reply_post_type(),
2575              'max_depth'    => bbp_thread_replies_depth(),
2576              'page'         => 1,
2577              'per_page'     => -1,
2578              'walker'       => new BBP_Walker_Reply_Dropdown(),
2579              'posts'        => $posts
2580          ) );
2581  
2582          // Filter & return
2583          return apply_filters( 'bbp_get_reply_to_dropdown', $retval, $reply_id, $reply_to, $topic_id );
2584      }
2585  
2586  /**
2587   * Output checked value of reply log edit field
2588   *
2589   * @since 2.0.0 bbPress (r3130)
2590   */
2591  function bbp_form_reply_log_edit() {
2592      echo bbp_get_form_reply_log_edit();
2593  }
2594      /**
2595       * Return checked value of reply log edit field
2596       *
2597       * @since 2.0.0 bbPress (r3130)
2598       *
2599       * @return string Reply log edit checked value
2600       */
2601  	function bbp_get_form_reply_log_edit() {
2602  
2603          // Get _POST data
2604          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_log_reply_edit'] ) ) {
2605              $reply_revision = (bool) $_POST['bbp_log_reply_edit'];
2606  
2607          // No data
2608          } else {
2609              $reply_revision = true;
2610          }
2611  
2612          // Get checked output
2613          $checked = checked( $reply_revision, true, false );
2614  
2615          // Filter & return
2616          return apply_filters( 'bbp_get_form_reply_log_edit', $checked, $reply_revision );
2617      }
2618  
2619  /**
2620   * Output the value of the reply edit reason
2621   *
2622   * @since 2.0.0 bbPress (r3130)
2623   */
2624  function bbp_form_reply_edit_reason() {
2625      echo bbp_get_form_reply_edit_reason();
2626  }
2627      /**
2628       * Return the value of the reply edit reason
2629       *
2630       * @since 2.0.0 bbPress (r3130)
2631       *
2632       * @return string Reply edit reason value
2633       */
2634  	function bbp_get_form_reply_edit_reason() {
2635  
2636          // Get _POST data
2637          if ( bbp_is_reply_form_post_request() && isset( $_POST['bbp_reply_edit_reason'] ) ) {
2638              $reply_edit_reason = wp_unslash( $_POST['bbp_reply_edit_reason'] );
2639  
2640          // No data
2641          } else {
2642              $reply_edit_reason = '';
2643          }
2644  
2645          // Filter & return
2646          return apply_filters( 'bbp_get_form_reply_edit_reason', $reply_edit_reason );
2647      }
2648  
2649  /**
2650   * Output value reply status dropdown
2651   *
2652   * @since 2.6.0 bbPress (r5399)
2653   *
2654   * @param $args This function supports these arguments:
2655   *  - select_id: Select id. Defaults to bbp_reply_status
2656   *  - tab: Deprecated. Tabindex
2657   *  - reply_id: Reply id
2658   *  - selected: Override the selected option
2659   */
2660  function bbp_form_reply_status_dropdown( $args = array() ) {
2661      echo bbp_get_form_reply_status_dropdown( $args );
2662  }
2663      /**
2664       * Returns reply status dropdown
2665       *
2666       * This dropdown is only intended to be seen by users with the 'moderate'
2667       * capability. Because of this, no additional capability checks are performed
2668       * within this function to check available reply statuses.
2669       *
2670       * @since 2.6.0 bbPress (r5399)
2671       *
2672       * @param $args This function supports these arguments:
2673       *  - select_id: Select id. Defaults to bbp_reply_status
2674       *  - tab: Deprecated. Tabindex
2675       *  - reply_id: Reply id
2676       *  - selected: Override the selected option
2677       */
2678  	function bbp_get_form_reply_status_dropdown( $args = array() ) {
2679  
2680          // Parse arguments against default values
2681          $r = bbp_parse_args( $args, array(
2682              'select_id'    => 'bbp_reply_status',
2683              'select_class' => 'bbp_dropdown',
2684              'tab'          => false,
2685              'reply_id'     => 0,
2686              'selected'     => false
2687          ), 'reply_status_dropdown' );
2688  
2689          // No specific selected value passed
2690          if ( empty( $r['selected'] ) ) {
2691  
2692              // Post value is passed
2693              if ( bbp_is_reply_form_post_request() && isset( $_POST[ $r['select_id'] ] ) ) {
2694                  $r['selected'] = sanitize_key( $_POST[ $r['select_id'] ] );
2695  
2696              // No Post value was passed
2697              } else {
2698  
2699                  // Edit reply
2700                  if ( bbp_is_reply_edit() ) {
2701                      $r['reply_id'] = bbp_get_reply_id( $r['reply_id'] );
2702                      $r['selected'] = bbp_get_reply_status( $r['reply_id'] );
2703  
2704                  // New reply
2705                  } else {
2706                      $r['selected'] = bbp_get_public_status_id();
2707                  }
2708              }
2709          }
2710  
2711          // Start an output buffer, we'll finish it after the select loop
2712          ob_start(); ?>
2713  
2714          <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'] ); ?>>
2715  
2716              <?php foreach ( bbp_get_reply_statuses( $r['reply_id'] ) as $key => $label ) : ?>
2717  
2718                  <option value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $r['selected'] ); ?>><?php echo esc_html( $label ); ?></option>
2719  
2720              <?php endforeach; ?>
2721  
2722          </select>
2723  
2724          <?php
2725  
2726          // Filter & return
2727          return apply_filters( 'bbp_get_form_reply_status_dropdown', ob_get_clean(), $r, $args );
2728      }
2729  
2730  /**
2731   * Verify if a POST request came from a failed reply attempt.
2732   *
2733   * Used to avoid cross-site request forgeries when checking posted reply form
2734   * content.
2735   *
2736   * @see bbp_reply_form_fields()
2737   *
2738   * @since 2.6.0 bbPress (r5558)
2739   *
2740   * @return boolean True if is a post request with valid nonce
2741   */
2742  function bbp_is_reply_form_post_request() {
2743  
2744      // Bail if not a post request
2745      if ( ! bbp_is_post_request() ) {
2746          return false;
2747      }
2748  
2749      // Creating a new reply
2750      if ( bbp_verify_nonce_request( 'bbp-new-reply' ) ) {
2751          return true;
2752      }
2753  
2754      // Editing an existing reply
2755      if ( bbp_verify_nonce_request( 'bbp-edit-reply' ) ) {
2756          return true;
2757      }
2758  
2759      return false;
2760  }


Generated: Tue Nov 19 01:01:25 2019 Cross-referenced by PHPXref 0.7.1